paperclipai/paperclip · critical
sync operation ${label} path is not a confined absolute path
Error message
sync operation ${label} path is not a confined absolute path: ${candidate} What it means
Thrown by assertSyncOperationsConfined when a sync mapping's source or target path is not a safe absolute POSIX path. The guard rejects relative paths, the literal `..`, and any path containing `/../` segments or ending in `/..`. This is the first half of a two-stage confinement check performed at the orchestrator trust boundary before handing file/directory transfers to a provider.
Source
Thrown at packages/adapter-utils/src/sandbox-managed-runtime.ts:273
syncOut?(operations: SandboxSyncOperation[]): Promise<SandboxSyncResult>;
}
/**
* Host-side complete-mediation guard for native sync operations. The orchestrator
* authors every `targetPath`, but the native transport crosses the host↔sandbox
* trust boundary, so we canonicalize and confine each mapping's source and target
* to an orchestrator-owned root before handing the operation to a provider.
* Absolute escapes and `..` traversal are rejected fail-closed. Sandbox and host
* paths on the server are POSIX.
*/
export function assertSyncOperationsConfined(
operations: SandboxSyncOperation[],
roots: { sourceRoots: string[]; targetRoots: string[] },
): void {
const confine = (candidate: string, allowed: string[], label: string): void => {
const normalized = path.posix.normalize(candidate);
if (!path.posix.isAbsolute(normalized) || normalized === ".." || normalized.includes("/../") || normalized.endsWith("/..")) {
throw new Error(`sync operation ${label} path is not a confined absolute path: ${candidate}`);
}
const within = allowed.some((root) => {
const normalizedRoot = path.posix.normalize(root);
const prefix = normalizedRoot.endsWith("/") ? normalizedRoot : `${normalizedRoot}/`;
return normalized === normalizedRoot || normalized.startsWith(prefix);
});
if (!within) {
throw new Error(`sync operation ${label} path escapes its confinement root: ${candidate}`);
}
};
for (const operation of operations) {
for (const mapping of operation.files) {
confine(mapping.sourcePath, roots.sourceRoots, "source");
confine(mapping.targetPath, roots.targetRoots, "target");
}
}
}
View on GitHub (pinned to 67001ec6eb)
Solutions
- Ensure every sourcePath/targetPath passed to sync operations is absolute and normalize() it before submission (path.posix.resolve or path.resolve).
- Strip or reject `..` in any user-supplied filename before joining it into a target path.
- For additional sources, pass an absolute localPath (matches the error at line 1011) computed with path.resolve at the call site.
- Add a unit test feeding a `..`-bearing path and confirm it throws this exact message.
Example fix
// before
files: [{ sourcePath: relPath, targetPath: `${root}/../asset.tar`, ... }]
// after
const safeTarget = path.posix.join(runtimeRootDir, 'asset.tar');
files: [{ sourcePath: path.resolve(relPath), targetPath: safeTarget, ... }] Defensive patterns
Strategy: validation
Validate before calling
function assertConfinedAbsolute(candidate: string): void {
const n = path.posix.normalize(candidate);
if (!path.posix.isAbsolute(n) || n === '..' || n.includes('/../') || n.endsWith('/..')) {
throw new Error(`not a confined absolute path: ${candidate}`);
}
}
// run before assertSyncOperationsConfined:
for (const op of operations) for (const m of op.files) { assertConfinedAbsolute(m.sourcePath); assertConfinedAbsolute(m.targetPath); } Type guard
function isConfinedAbsolutePath(p: string): boolean {
const n = path.posix.normalize(p);
return path.posix.isAbsolute(n) && n !== '..' && !n.includes('/../') && !n.endsWith('/..');
} Prevention
- Always build sync paths with path.posix.resolve/join from trusted prefixes.
- Reject any user-supplied path segment containing '..' at the input boundary.
- Unit-test the confinement helper with traversal payloads.
When it happens
Trigger: Calling assertSyncOperationsConfined(operations, roots) where any operation.files[].sourcePath or targetPath is relative (no leading /), contains `..`, equals `..`, or has a trailing `/..`. Triggered during prepareSandboxManagedRuntime staging when asset or additional-source paths are assembled incorrectly.
Common situations: A caller builds a targetPath with a template that can yield `../`; an additionalSource localPath is passed as a workspace-relative string instead of absolute; a tar extraction target is computed with a missing prefix producing a relative path; portability bug where a Windows backslash path leaks into the POSIX check.
Related errors
- sync operation ${label} path escapes its confinement root: $
- provision stageFile.name must be a simple basename, got: ${s
- Daytona sync ${label} path is not a confined absolute path:
- Daytona sync ${label} path escapes the workspace remote dir:
- Refusing to write export file outside output directory: ${re
AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12).
Data as JSON: /api/errors/d84eb513dbeb1d79.
Report an issue: GitHub.