paperclipai/paperclip · error
Daytona sync path escapes the workspace remote dir
Error message
Daytona sync ${label} path escapes the workspace remote dir: ${candidate} What it means
Traversal-escape guard in assertConfinedSandboxPath: the candidate path is absolute but path.posix.normalize places it outside the workspace remote dir root (e.g. via leading '..' segments). Rejecting it prevents an untrusted sandbox-side path from reading or writing host files outside the confined workspace tree during sync.
Solutions
- Keep the sync path inside the workspace remote dir; remove '..' or absolute escapes.
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:121 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/c0b3210d5055349a.
Report an issue: GitHub.
Appendix: source
Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:125
function shellQuote(value: string): string {
return `'${value.replace(/'/g, `'"'"'`)}'`;
}
/**
* Convert a POSIX numeric mode (e.g. `0o600`) to the octal string the Daytona
* SDK's `setFilePermissions` expects (e.g. `"600"`), masked to the permission
* bits so an accidental type flag never widens the mode.
*/
function toOctalModeString(mode: number): string {
return (mode & 0o7777).toString(8).padStart(3, "0");
}
/**
* Host-side complete-mediation guard applied as defense-in-depth below the
* orchestrator's own confinement. Every sandbox-side path (the sync target for
* inbound, the sync source for outbound) MUST canonicalize inside the workspace
* remote dir; absolute escapes and `..` traversal are rejected fail-closed before
* any bytes move. Sandbox paths on the server are POSIX.
*/
export function assertConfinedSandboxPath(remoteDir: string, candidate: string, label: string): void {
const normalizedRoot = path.posix.normalize(remoteDir);
const normalized = path.posix.normalize(candidate);
if (
!path.posix.isAbsolute(normalized) ||
normalized === ".." ||
normalized.includes("/../") ||
normalized.endsWith("/..")
) {
throw new Error(`Daytona sync ${label} path is not a confined absolute path: ${candidate}`);
}
const prefix = normalizedRoot.endsWith("/") ? normalizedRoot : `${normalizedRoot}/`;
if (normalized !== normalizedRoot && !normalized.startsWith(prefix)) {
throw new Error(`Daytona sync ${label} path escapes the workspace remote dir: ${candidate}`);
}
}
View on GitHub (pinned to 3f1d897a7c)