vercel-labs/skills · critical · ArchiveValidationError
Archive contains unsafe path: ${path}
Error message
Archive contains unsafe path: ${path} What it means
Before writing each extracted zip entry, extractZip joins the entry path with extractDir and validates it with isPathSafe; if the resolved target escapes the extraction directory, it throws ArchiveValidationError. This is the defense against Zip Slip (CVE-2018-12689-style path traversal), where an entry named ../../.bashrc would otherwise overwrite files outside the extraction root.
Source
Thrown at src/download-source.ts:147
} catch {
return false;
}
}
async function extractZip(
filePath: string,
extractDir: string,
limits: DownloadLimits
): Promise<void> {
const files = readZipArchive(await readFile(filePath), {
maxExtractedBytes: limits.extractMaxBytes,
maxEntries: limits.extractMaxFiles,
});
for (const [path, contents] of files) {
const targetPath = join(extractDir, path);
if (!isPathSafe(extractDir, targetPath)) {
throw new ArchiveValidationError(`Archive contains unsafe path: ${path}`);
}
await mkdir(dirname(targetPath), { recursive: true });
await writeFile(targetPath, contents);
}
}
function getTarEntryType(entry: tar.ReadEntry | Stats): string {
if (entry instanceof tar.ReadEntry) {
return entry.type;
}
if (entry.isFile()) return 'File';
if (entry.isDirectory()) return 'Directory';
return '';
}
function isTarEntryFile(entry: tar.ReadEntry | Stats): boolean {
const type = getTarEntryType(entry);View on GitHub (pinned to 435076e789)
Solutions
- Do not extract the archive — treat it as hostile and remove it
- Inspect the offending entries: unzip -l archive.zip | grep -E '(^|/)(\.\.|/)\.' or list entries for ../ patterns
- Obtain the archive from a trusted source or repackage its safe contents yourself
- Report the malicious archive to wherever it was hosted
Example fix
# before skills add https://untrusted.example/skills.zip # unsafe path: ../../.ssh/authorized_keys # after # inspect first unzip -l untrusted-skills.zip # then install from the canonical, trusted repo instead skills add verified-org/agent-skills
Defensive patterns
Strategy: validation
Validate before calling
// Reject archives containing traversal-style entries before extracting
import { createReadStream } from 'node:fs';
import * as unzipper from 'unzipper';
async function assertNoUnsafeEntries(path: string): Promise<void> {
const dir = await unzipper.Open.file(path);
for (const f of dir.files) {
const norm = f.path.replace(/\\/g, '/');
if (norm.startsWith('/') || /^[A-Za-z]:/.test(norm) || norm.split('/').includes('..')) {
throw new Error(`Unsafe entry: ${f.path}`);
}
}
} Type guard
function isSafeEntryPath(entryPath: string): boolean {
const norm = entryPath.replace(/\\/g, '/');
if (norm.startsWith('/') || /^[A-Za-z]:/.test(norm)) return false;
return !norm.split('/').includes('..');
} Try / catch
try {
await extractArchive(file);
} catch (err) {
if (err instanceof ArchiveValidationError && err.message.startsWith('Archive contains unsafe path')) {
// SECURITY event: quarantine the archive, do NOT extract with other tools blindly
} else throw err;
} Prevention
- Only install archives from trusted, pinned sources
- Always extract into a disposable temp directory you control
- Audit third-party archives (unzip -l) for absolute paths and ../ segments before use
When it happens
Trigger: Extracting an archive containing entries with absolute paths (/etc/...), drive letters (C:\...), ../ sequences, or symlink-style traversal that resolves outside extractDir. Usually seen with maliciously crafted archives or buggy packaging scripts that preserve absolute paths.
Common situations: Downloading skill archives from untrusted third parties, archives created with absolute paths by misconfigured build tools, or penetration-test payloads deliberately containing traversal entries.
Related errors
- Archive contains unsafe path: ${entryPath}
- Unsafe archive path: ${path}
- Invalid skill name: potential path traversal detected
- Archive exceeds maximum unpacked size
- Archive contains too many files
AI-assisted analysis of vercel-labs/skills@435076e789 (2026-08-28).
Data as JSON: /api/errors/b4ade01b2d119588.
Report an issue: GitHub.