{"record":{"id":"638e68a04c6f3169","repo":"paperclipai/paperclip","slug":"daytona-syncout-refusing-tarball-member-that-escap","errorCode":null,"errorMessage":"Daytona syncOut refusing tarball member that escapes the extraction dir: ${name}","messagePattern":"Daytona syncOut refusing tarball member that escapes the extraction dir: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/plugins/sandbox-providers/daytona/src/file-sync.ts","lineNumber":262,"sourceCode":" * escapes the tree — the latter would let a follow-up member be written through\n * the link to an arbitrary host path. Legitimate in-tree relative links (targets\n * that resolve back inside the archive, e.g. `shortcut -> nested/data.txt`) are\n * preserved. Parses the `-tvf` verbose listing so both member names and link\n * targets are inspected; any unparseable line fails closed.\n */\nasync function assertTarballEntriesConfined(archivePath: string): Promise<void> {\n  const { stdout } = await execFileAsync(\"tar\", [\"-tvf\", archivePath], {\n    env: { ...process.env, COPYFILE_DISABLE: \"1\" },\n    maxBuffer: 32 * 1024 * 1024,\n  });\n  const lines = stdout.split(\"\\n\").filter((line) => line.trim().length > 0);\n  for (const line of lines) {\n    const parsed = parseTarVerboseListingLine(line);\n    if (!parsed) {\n      throw new Error(`Daytona syncOut refusing tarball with an unparseable entry listing: ${line}`);\n    }\n    const typeFlag = parsed.typeFlag;\n    let name = parsed.rest;\n    let linkTarget: string | null = null;\n    if (typeFlag === \"l\") {\n      const split = splitLinkEntryOnce(name, \" -> \");\n      if (!split) throw new Error(`Daytona syncOut refusing unparseable or ambiguous symlink entry: ${line}`);\n      name = split.name;\n      linkTarget = split.target;\n    } else if (typeFlag === \"h\") {\n      const split = splitLinkEntryOnce(name, \" link to \");\n      if (!split) throw new Error(`Daytona syncOut refusing unparseable or ambiguous hardlink entry: ${line}`);\n      name = split.name;\n      linkTarget = split.target;\n    }\n    const cleanName = name.replace(/\\/+$/, \"\");\n    if (cleanName.length > 0 && posixPathEscapes(cleanName)) {\n      throw new Error(`Daytona syncOut refusing tarball member that escapes the extraction dir: ${name}`);\n    }\n    if (linkTarget !== null) {\n      const resolved = path.posix.join(path.posix.dirname(cleanName), linkTarget);","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/plugins/sandbox-providers/daytona/src/file-sync.ts#L244-L280","documentation":"Confinement guard in assertTarballEntriesConfined: a tar member name (after stripping trailing slashes) resolves outside the extraction directory — e.g. an absolute path or '../' traversal. Because the archive comes from the untrusted sandbox, such a member would let `tar -xf` write to arbitrary host paths, so extraction is refused.","triggerScenarios":"Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:258 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Remove path-traversal entries from the tarball; all members must extract inside the target dir."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-08-18T22:49:45.177Z","contentChangedAt":"2026-08-18T22:49:45.177Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}