vercel-labs/skills · error
Unsafe subpath: "${subpath}" contains path traversal segment
Error message
Unsafe subpath: "${subpath}" contains path traversal segments. Subpaths must not contain ".." components. What it means
sanitizeSubpath() normalizes backslashes to slashes and rejects the whole subpath if any single '..' segment appears. It is the front-line guard in source parsing, so hostile or malformed source specs fail before any filesystem or network operation.
Source
Thrown at src/source-parser.ts:114
// On error, return null to indicate we couldn't determine
return null;
}
}
/**
* Sanitizes a subpath to prevent path traversal attacks.
* Rejects subpaths containing ".." segments that could escape the repository root.
* Returns the sanitized subpath, or throws if the subpath is unsafe.
*/
export function sanitizeSubpath(subpath: string): string {
// Normalize to forward slashes for consistent handling
const normalized = subpath.replace(/\\/g, '/');
// Check each segment for ".."
const segments = normalized.split('/');
for (const segment of segments) {
if (segment === '..') {
throw new Error(
`Unsafe subpath: "${subpath}" contains path traversal segments. ` +
`Subpaths must not contain ".." components.`
);
}
}
return subpath;
}
/**
* Check if a string represents a local file system path
*/
function isLocalPath(input: string): boolean {
return (
isAbsolute(input) ||
input.startsWith('./') ||
input.startsWith('../') ||
input === '.' ||View on GitHub (pinned to 435076e789)
Solutions
- Remove '..' segments (or the whole subpath) from the source string before parsing
- Use explicit, clean subpaths: 'owner/repo/path/to/skill'
- If traversal was unintentional, simplify to the direct path to the skill directory
- In SDKs, validate subpaths against /^[A-Za-z0-9._\/-]+$/ with no '..' component
Example fix
# before skills add github.com/org/repo/skills/../skills/python # after skills add github.com/org/repo/skills/python
Defensive patterns
Strategy: validation
Validate before calling
function isSafeSubpath(sub: string): boolean {
const n = sub.replace(/\\/g, '/');
return !n.split('/').includes('..');
}
if (subpath && !isSafeSubpath(subpath)) throw new Error(`Unsafe subpath: ${subpath}`); Type guard
function isUnsafeSubpath(e: unknown): e is Error {
return e instanceof Error && /Unsafe subpath.*\.\./.test(e.message);
} Try / catch
try { const src = parseSource(input); }
catch (e) {
if (isUnsafeSubpath(e)) {
const cleaned = input.replace(/\.{2}(?:\/[\\/]*)?/g, '').replace(/\\/g, '/');
return parseSource(cleaned); // retry with sanitized input
}
throw e;
} Prevention
- Normalize separators and strip '..' segments from user-supplied source strings
- Validate subpaths with a whitelist regex before parsing
- Return clear user-facing errors for traversal input rather than forwarding to APIs
When it happens
Trigger: parseSource() receiving a source string whose subpath component contains '..' — e.g. 'owner/repo/..', 'github.com/a/b/../../c', or Windows-style 'a\\..\\b'. Any '..' segment, even one that would stay inside, is rejected.
Common situations: Users pasting traversal-style relative paths; automation building source strings by concatenation without sanitizing; inputs mixing Windows backslash separators.
Related errors
- Invalid subpath: "${subpath}" resolves outside the repositor
- Archive contains unsafe path: ${path}
- Archive contains unsafe path: ${entryPath}
- Invalid skill name: potential path traversal detected
- Unsafe archive path: ${path}
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/fdbd329e86fad09d.
Report an issue: GitHub.