can1357/oh-my-pi · error · ArchiveError
Archive path cannot contain '..'
Error message
Archive path cannot contain '..'
What it means
Path-safety guard in `listDirectory`: `normalizeArchiveLookupPath(subPath)` returned undefined because the supplied path contains a `..` component, which this library forbids to prevent path-traversal-style lookups. Thrown as ArchiveError before any directory resolution happens (packages/utils/src/ar/reader.ts:76).
Source
Thrown at packages/utils/src/ar/reader.ts:76
if (resolvedPath === "") {
return { path: normalizedPath, isDirectory: true, size: 0 };
}
const entry = this.#entries.get(resolvedPath);
if (!entry) return undefined;
return {
path: normalizedPath,
isDirectory: entry.isDirectory,
size: entry.size,
mtimeMs: entry.mtimeMs,
mode: entry.mode,
};
}
/** List one directory's children, sorted case-insensitively by name. */
listDirectory(subPath?: string): ArchiveDirectoryEntry[] {
const normalizedPath = normalizeArchiveLookupPath(subPath);
if (normalizedPath === undefined) {
throw new ArchiveError("Archive path cannot contain '..'");
}
const resolvedPath = normalizedPath
? resolveArchiveLinkPath(this.#entries, normalizedPath, this.limits.maxLinkDepth)
: "";
if (normalizedPath && resolvedPath !== "") {
const entry = this.#entries.get(resolvedPath);
if (!entry) {
throw new ArchiveError(`Archive path '${normalizedPath}' not found`);
}
if (!entry.isDirectory) {
throw new ArchiveError(`Archive path '${normalizedPath}' is not a directory`);
}
}
const sourcePrefix = resolvedPath ? `${resolvedPath}/` : "";
const children = new Map<string, ArchiveDirectoryEntry>();
View on GitHub (pinned to 9690622007)
Solutions
- Remove or reject '..' segments before calling: normalize the requested path (e.g. path.posix.normalize and refuse if it escapes the root).
- Call listDirectory with undefined or a rooted relative path ('sub/dir') — top-level listing uses undefined, not '..' or '/'.
- Sanitize untrusted input at the boundary: strip leading slashes and collapse '.' segments, then re-check for '..'.
- Catch this ArchiveError and show the user that upward traversal is not allowed inside archives.
Example fix
// before: user input passed straight through
reader.listDirectory(userPath); // '../etc' -> throws
// after: normalize and reject traversal first
const clean = path.posix.normalize(userPath.replace(/^\/+/, ''));
if (clean.split('/').includes('..')) {
throw new Error('Directory traversal is not allowed');
}
reader.listDirectory(clean === '.' ? undefined : clean); Defensive patterns
Strategy: validation
Validate before calling
// Sanitize user-supplied subPath before calling listDirectory
function safeArchivePath(input: string): string {
const clean = path.posix.normalize(input.replace(/^\/+/, ''));
if (clean === '.' || clean === '..' || clean.split('/').includes('..')) {
throw new Error(`Path escapes the archive root: ${input}`);
}
return clean;
}
reader.listDirectory(safeArchivePath(userPath)); Type guard
function isTraversalFree(p: string): boolean {
return !p.split('/').includes('..');
} Try / catch
try {
return reader.listDirectory(userPath);
} catch (err) {
if (err instanceof ArchiveError && err.message === "Archive path cannot contain '..'") {
throw new Error(`Invalid directory request (traversal blocked): ${userPath}`);
}
throw err;
} Prevention
- Never pass raw user input as archive paths; normalize and reject '..' at the boundary.
- Use undefined for root listings instead of '.', '/' or '..'.
- Keep a single path-sanitizer helper shared by all archive access points.
- Treat archive paths as rooted and forward-slash separated, not OS-relative paths.
When it happens
Trigger: Calling `reader.listDirectory('../sibling')`, `'a/../../b'`, or passing any subPath containing '..' segments; also occurs when user-supplied input with '..' flows into listDirectory (directly or via allEntries).
Common situations: Building UI paths from user input without sanitizing; joining a user-chosen folder onto a base path such that '..' appears; code that treats archive paths like filesystem-relative paths and walks upward.
Related errors
- Destination paths cannot contain parent traversal or NUL byt
- Shared-folder destination escapes its configured root
- Absolute paths are not allowed in ${scheme}:// URLs: ${rawPa
- Path traversal (..) is not allowed in ${scheme}:// URLs: ${r
- Unsafe #{scheme}:// path (absolute or traversal): #{path}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/eb013f550d669cfc.
Report an issue: GitHub.