paperclipai/paperclip · error
Daytona syncOut refusing tarball with an unparseable entry…
Error message
Daytona syncOut refusing tarball with an unparseable entry listing: ${line} What it means
Fail-closed parser check in assertTarballEntriesConfined: a line of `tar -tvf` verbose output produced by the (untrusted) sandbox could not be parsed by parseTarVerboseListingLine. Because member names and link targets cannot be verified for an unparseable line, the whole syncOut extraction is refused rather than risk extracting an uninspected entry.
Solutions
- Re-create the tarball with a standard tar so entry listings parse; inspect the reported line.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:240 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18).
Data as JSON: /api/errors/e29267493cfbb247.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:244
* once. The sandbox controls both halves, so a field with zero or multiple
* delimiter occurrences is unresolvable: a link name that itself contains the
* delimiter shifts the split point, and taking the first (or last) occurrence
* would let a crafted name or target hide an escaping link target from the
* confinement check. Returns null so callers fail closed.
*/
export function splitLinkEntryOnce(field: string, delimiter: string): { name: string; target: string } | null {
const first = field.indexOf(delimiter);
if (first === -1) return null;
if (field.indexOf(delimiter, first + delimiter.length) !== -1) return null;
return { name: field.slice(0, first), target: field.slice(first + delimiter.length) };
}
/**
* Reject a sandbox-authored tarball before extraction if any member would land
* outside the extraction dir. The archive is produced by the (untrusted) sandbox,
* so `tar -xf` on the host must never be handed an archive whose entries carry
* absolute paths or `../` traversal, nor a symlink/hardlink member whose target
* escapes the tree — the latter would let a follow-up member be written through
* the link to an arbitrary host path. Legitimate in-tree relative links (targets
* that resolve back inside the archive, e.g. `shortcut -> nested/data.txt`) are
* preserved. Parses the `-tvf` verbose listing so both member names and link
* targets are inspected; any unparseable line fails closed.
*/
async function assertTarballEntriesConfined(archivePath: string): Promise<void> {
const { stdout } = await execFileAsync("tar", ["-tvf", archivePath], {
env: { ...process.env, COPYFILE_DISABLE: "1" },
maxBuffer: 32 * 1024 * 1024,
});
const lines = stdout.split("\n").filter((line) => line.trim().length > 0);
for (const line of lines) {
const parsed = parseTarVerboseListingLine(line);
if (!parsed) {
throw new Error(`Daytona syncOut refusing tarball with an unparseable entry listing: ${line}`);
}
const typeFlag = parsed.typeFlag;
let name = parsed.rest;View on GitHub (pinned to 3f1d897a7c)