paperclipai/paperclip · critical

Daytona sync ${label} path is not a confined absolute path:

Error message

Daytona sync ${label} path is not a confined absolute path: ${candidate}

What it means

Thrown by `assertConfinedSandboxPath` (file-sync.ts:117) — a fail-closed security guard — when a candidate sandbox path is not POSIX-absolute, or normalizes to `..`, contains `/../`, or ends with `/..`. Every inbound (sync target) and outbound (sync source) path MUST canonicalize inside the workspace remote dir before any bytes move; this is the first check rejecting non-absolute or traversing paths.

Source

Thrown at packages/plugins/sandbox-providers/daytona/src/file-sync.ts:117

}

/**
 * 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}`);
  }
}

async function withHostTempDir<T>(fn: (dir: string) => Promise<T>): Promise<T> {
  const dir = await fs.mkdtemp(path.join(os.tmpdir(), "paperclip-daytona-sync-"));
  try {
    return await fn(dir);
  } finally {
    await fs.rm(dir, { recursive: true, force: true }).catch(() => undefined);
  }
}

/**
 * Build a host-side tarball of a directory, mirroring the runtime's own

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Ensure every sync `targetPath`/`sourcePath` and command `cwd` is POSIX-absolute (leading `/`) and resolved under the workspace `remoteDir`.
  2. Use `path.posix.resolve(remoteDir, relativeInput)` to absolutize, then pass the result.
  3. Reject `..` components in untrusted path input before constructing the mapping.

Example fix

// before
mapping: { sourcePath: localFile, targetPath: "repo/file.txt", kind: "file" }
// after
mapping: { sourcePath: localFile, targetPath: `${remoteDir}/repo/file.txt`, kind: "file" }
Defensive patterns

Strategy: validation

Validate before calling

import path from "node:path";
function assertConfined(remoteDir, candidate) {
  const n = path.posix.normalize(candidate);
  if (!path.posix.isAbsolute(n) || n === ".." || n.includes("/../") || n.endsWith("/..")) {
    throw new Error(`path not a confined absolute path: ${candidate}`);
  }
  return n;
}
// call assertConfined(remoteDir, targetPath) BEFORE building the sync mapping

Type guard

function isConfinedAbsolutePath(remoteDir: string, candidate: string): boolean {
  const n = path.posix.normalize(candidate);
  if (!path.posix.isAbsolute(n) || n === ".." || n.includes("/../") || n.endsWith("/..")) return false;
  const prefix = remoteDir.endsWith("/") ? remoteDir : `${remoteDir}/`;
  return n === remoteDir || n.startsWith(prefix);
}

Prevention

When it happens

Trigger: A sync file mapping supplies a `targetPath`/`sourcePath` that is relative (`"foo"`), dot-relative (`"./x"`, `"../x"`), or contains `..` segments after POSIX normalization. Also fires for a post-upload command `cwd` that is not absolute. The guard runs host-side before any sandbox round trip.

Common situations: A plugin/mapping builder constructs paths with `path.join` on a Windows host (backslashes), passes a relative repo path by mistake, or accepts untrusted user input as a sync target without absolutizing it under the remote dir.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/9d38630e6db9f49b. Report an issue: GitHub.