From b40982a9678837f49b0cc629c67ce2f485175f0c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 23 Aug 2026 23:30:15 +0000 Subject: [PATCH] Sync generated provider output --- .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .pi/skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ .../skills/impeccable/scripts/live-server.mjs | 22 +++++++++++++------ 16 files changed, 240 insertions(+), 112 deletions(-) diff --git a/.agents/skills/impeccable/scripts/live-server.mjs b/.agents/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.agents/skills/impeccable/scripts/live-server.mjs +++ b/.agents/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.claude/skills/impeccable/scripts/live-server.mjs b/.claude/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.claude/skills/impeccable/scripts/live-server.mjs +++ b/.claude/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.cursor/skills/impeccable/scripts/live-server.mjs b/.cursor/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.cursor/skills/impeccable/scripts/live-server.mjs +++ b/.cursor/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.gemini/skills/impeccable/scripts/live-server.mjs b/.gemini/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.gemini/skills/impeccable/scripts/live-server.mjs +++ b/.gemini/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.github/skills/impeccable/scripts/live-server.mjs b/.github/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.github/skills/impeccable/scripts/live-server.mjs +++ b/.github/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.grok/skills/impeccable/scripts/live-server.mjs b/.grok/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.grok/skills/impeccable/scripts/live-server.mjs +++ b/.grok/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.hermes/skills/impeccable/scripts/live-server.mjs b/.hermes/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.hermes/skills/impeccable/scripts/live-server.mjs +++ b/.hermes/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.kiro/skills/impeccable/scripts/live-server.mjs b/.kiro/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.kiro/skills/impeccable/scripts/live-server.mjs +++ b/.kiro/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.opencode/skills/impeccable/scripts/live-server.mjs b/.opencode/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.opencode/skills/impeccable/scripts/live-server.mjs +++ b/.opencode/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.pi/skills/impeccable/scripts/live-server.mjs b/.pi/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.pi/skills/impeccable/scripts/live-server.mjs +++ b/.pi/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.qoder/skills/impeccable/scripts/live-server.mjs b/.qoder/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.qoder/skills/impeccable/scripts/live-server.mjs +++ b/.qoder/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.rovodev/skills/impeccable/scripts/live-server.mjs b/.rovodev/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.rovodev/skills/impeccable/scripts/live-server.mjs +++ b/.rovodev/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.trae-cn/skills/impeccable/scripts/live-server.mjs b/.trae-cn/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.trae-cn/skills/impeccable/scripts/live-server.mjs +++ b/.trae-cn/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.trae/skills/impeccable/scripts/live-server.mjs b/.trae/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.trae/skills/impeccable/scripts/live-server.mjs +++ b/.trae/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/.vibe/skills/impeccable/scripts/live-server.mjs b/.vibe/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/.vibe/skills/impeccable/scripts/live-server.mjs +++ b/.vibe/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content); diff --git a/plugin/skills/impeccable/scripts/live-server.mjs b/plugin/skills/impeccable/scripts/live-server.mjs index 86b7777be..cba3a222e 100644 --- a/plugin/skills/impeccable/scripts/live-server.mjs +++ b/plugin/skills/impeccable/scripts/live-server.mjs @@ -936,15 +936,23 @@ function createRequestHandler({ detectScript, liveScriptParts }) { const filePath = url.searchParams.get('path'); if (!filePath || filePath.includes('..')) { res.writeHead(400); res.end('Bad path'); return; } const absPath = path.resolve(process.cwd(), filePath); - // Confine to the project root. A bare `startsWith(cwd)` string check lets a - // sibling dir whose name extends the root name (projeto -> projeto-backup) - // slip through; compare on the relative path instead (same pattern as - // sessionFileMetadataFromPollReply below). An empty rel means the request - // resolved to the root directory itself, which this file route never serves. - const rel = path.relative(process.cwd(), absPath); + let realRoot, realTarget; + try { + realRoot = fs.realpathSync(process.cwd()); + realTarget = fs.realpathSync(absPath); + } catch { + res.writeHead(404); res.end('File not found'); return; + } + // Confine to the project root after symlink resolution. A bare + // `startsWith(cwd)` string check lets a sibling dir whose name extends the + // root name (projeto -> projeto-backup) slip through; compare on the + // relative path instead (same pattern as sessionFileMetadataFromPollReply + // below). An empty rel means the request resolved to the root directory + // itself, which this file route never serves. + const rel = path.relative(realRoot, realTarget); if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) { res.writeHead(403); res.end('Forbidden'); return; } let content; - try { content = fs.readFileSync(absPath, 'utf-8'); } + try { content = fs.readFileSync(realTarget, 'utf-8'); } catch { res.writeHead(404); res.end('File not found'); return; } res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }); res.end(content);