pbakaus/impeccable · error · Error
Svelte-component source file escapes project root
Error message
Svelte-component source file escapes project root
What it means
Thrown by resolveSourceFile after resolving the relative path: the result, when expressed relative to cwd, starts with '..' or is absolute, meaning the file escapes the project root. The guard prevents path-traversal writes outside the project during svelte-component patching.
Source
Thrown at plugin/skills/impeccable/scripts/live/svelte-component.mjs:449
return null;
}
export function readManifest(manifestPath) {
const data = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
return {
...data,
manifestPath,
};
}
export function resolveSourceFile(sourceFile, cwd = process.cwd()) {
if (!sourceFile || path.isAbsolute(sourceFile)) {
throw new Error('Invalid svelte-component source file');
}
const full = path.resolve(cwd, sourceFile);
const rel = path.relative(cwd, full);
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) {
throw new Error('Svelte-component source file escapes project root');
}
if (!fs.existsSync(full)) {
throw new Error('Svelte-component source file not found: ' + sourceFile);
}
return full;
}
function appendCssToSvelteStyle(lines, cssLines) {
const closeIdx = findLastStyleCloseLine(lines);
const prepared = ['', ...cssLines.map((line) => (line.trim() === '' ? '' : ' ' + line.trimStart()))];
if (closeIdx === -1) {
return [...lines, '', '<style>', ...prepared.slice(1), '</style>'];
}
return [
...lines.slice(0, closeIdx),
...prepared,
...lines.slice(closeIdx),
];View on GitHub (pinned to d14711ae3d)
Solutions
- Resolve against the correct project root: pass cwd matching where the path is relative to.
- Sanitize the input to reject '..' segments before calling resolveSourceFile.
- If traversal is intentional for a monorepo, run from a cwd that legitimately contains the file.
Example fix
// before
resolveSourceFile('../../shared/Comp.svelte', cwd);
// after: run from a cwd that contains the target
resolveSourceFile('packages/shared/Comp.svelte', projectRoot); Defensive patterns
Strategy: validation
Validate before calling
function isWithinRoot(sourceFile, cwd) {
const full = path.resolve(cwd, sourceFile);
const rel = path.relative(cwd, full);
return !!rel && !rel.startsWith('..') && !path.isAbsolute(rel);
} Type guard
function isContainedPath(sourceFile, cwd) {
if (!sourceFile || path.isAbsolute(sourceFile)) return false;
const rel = path.relative(cwd, path.resolve(cwd, sourceFile));
return !!rel && !rel.startsWith('..') && !path.isAbsolute(rel);
} Try / catch
try {
resolveSourceFile(sourceFile, cwd);
} catch (err) {
if (err.message.includes('escapes project root')) {
throw new Error(`refusing path outside project: ${sourceFile}`);
} else throw err;
} Prevention
- Sanitize user-supplied paths: reject any segment equal to '..'.
- Resolve symlinks before the containment check if symlinks are allowed.
- Lock cwd to the project root at process start.
When it happens
Trigger: sourceFile like '../../etc/passwd' or a symlink-adjacent relative path whose resolved location sits above cwd. The first guard (absolute) is not tripped, but this escape check is.
Common situations: User-supplied input with traversal segments, or a cwd that does not match the project root the path was computed against.
Related errors
- Invalid svelte-component source file
- Svelte-component source file not found: ${sourceFile}
- Invalid svelte-component source file
- Svelte-component source file escapes project root
- invalid session id: ${id}
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/b9d8c3be4d32a9bb.
Report an issue: GitHub.