paperclipai/paperclip · critical
Daytona syncOut refusing tarball member that escapes the ext
Error message
Daytona syncOut refusing tarball member that escapes the extraction dir: ${name} What it means
Thrown by assertTarballEntriesConfined when a tarball member name (after stripping trailing slashes) escapes the extraction directory: it is absolute, equals '..', or begins with '../'. This is a path-traversal guard run against an untrusted, sandbox-authored archive before the host extracts it, preventing writes outside the target tree.
Source
Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:221
throw new Error(`Daytona syncOut refusing tarball with an unparseable entry listing: ${line}`);
}
const typeFlag = match[1][0];
let name = match[2];
let linkTarget: string | null = null;
if (typeFlag === "l") {
const idx = name.indexOf(" -> ");
if (idx === -1) throw new Error(`Daytona syncOut refusing unparseable symlink entry: ${line}`);
linkTarget = name.slice(idx + " -> ".length);
name = name.slice(0, idx);
} else if (typeFlag === "h") {
const idx = name.indexOf(" link to ");
if (idx === -1) throw new Error(`Daytona syncOut refusing unparseable hardlink entry: ${line}`);
linkTarget = name.slice(idx + " link to ".length);
name = name.slice(0, idx);
}
const cleanName = name.replace(/\/+$/, "");
if (cleanName.length > 0 && posixPathEscapes(cleanName)) {
throw new Error(`Daytona syncOut refusing tarball member that escapes the extraction dir: ${name}`);
}
if (linkTarget !== null) {
const resolved = path.posix.join(path.posix.dirname(cleanName), linkTarget);
if (path.posix.isAbsolute(linkTarget) || posixPathEscapes(resolved)) {
throw new Error(
`Daytona syncOut refusing tarball link whose target escapes the extraction dir: ${name} -> ${linkTarget}`,
);
}
}
}
}
async function extractHostTarball(input: { archivePath: string; localDir: string }): Promise<void> {
// The archive is sandbox-authored and untrusted: validate every member (and
// link target) is confined before letting host-side tar write a single byte.
await assertTarballEntriesConfined(input.archivePath);
await fs.mkdir(input.localDir, { recursive: true });
await execFileAsync("tar", ["-xf", input.archivePath, "-C", input.localDir], {View on GitHub (pinned to 67001ec6eb)
Solutions
- Inspect the offending member `name` in the error message to confirm which sandbox file produced the escaping path.
- Fix the sandbox-side process so it only writes files within the workspace remote dir (no absolute or ../ paths).
- If the entry is legitimate, ensure the syncOut source mapping is rooted inside the confinement directory.
- Re-run syncOut after correcting the source tree; the guard will pass once all members are confined.
Example fix
// before: sandbox writes /etc/override into synced dir
// after: sandbox writes only under $remoteCwd
process.chdir(remoteCwd); fs.writeFileSync('./local-file', data); Defensive patterns
Strategy: validation
Validate before calling
function memberIsConfined(name: string): boolean {
const clean = name.replace(/\/+$/, '');
if (clean.length === 0) return true;
const norm = path.posix.normalize(clean);
return !(norm === '..' || norm.startsWith('../') || path.posix.isAbsolute(norm));
} Try / catch
try {
await extractHostTarball({ archivePath, localDir });
} catch (e) {
if (e instanceof Error && e.message.includes('escapes the extraction dir')) {
// quarantine the archive; do not extract anywhere on the host
}
throw e;
} Prevention
- Treat any 'escapes the extraction dir' error as a potential sandbox escape attempt; do not bypass.
- Ensure sandbox processes only write relative paths rooted under the workspace dir.
- Audit sandbox-authored archives before host extraction; the built-in guard is intentional and should stay enabled.
When it happens
Trigger: A syncOut tarball contains an entry whose cleaned name is an absolute POSIX path, '..', or starts with '../'. The check posixPathEscapes normalizes the path and rejects any breakout.
Common situations: A malicious or buggy sandbox writes files with absolute paths or parent-directory traversal into the tar; a misconfigured source path that resolves outside the workspace remote dir; symlink/hardlink redirection creating out-of-tree member names.
Related errors
- Daytona syncOut refusing tarball link whose target escapes t
- Daytona syncOut refusing unparseable hardlink entry: ${line}
- Daytona sync ${label} path is not a confined absolute path:
- Daytona sync ${label} path escapes the workspace remote dir:
- Daytona syncOut refusing tarball with an unparseable entry l
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/638e68a04c6f3169.
Report an issue: GitHub.