paperclipai/paperclip · error · Error

ACPX ${input.profile.agent} runtime executable escapes its p

Error message

ACPX ${input.profile.agent} runtime executable escapes its package

What it means

Before touching the filesystem for real, the verifier resolves qualification.relativeExecutable against the platform package directory and asserts the unresolved path stays inside that package (path-traversal guard on the literal path). If the qualified relativeExecutable value resolves outside the package directory, the qualification data or metadata is inconsistent/unsafe and verification stops.

Source

Thrown at packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts:896

    ),
  );
  const executablePackage = await readPackageJson(
    executablePackageJsonPath,
    qualification.packageName,
  );
  if (executablePackage.version !== qualification.packageVersion) {
    throw new Error(
      `ACPX ${input.profile.agent} runtime executable package version mismatch: expected ${qualification.packageVersion}, received ${executablePackage.version ?? "unknown"}`,
    );
  }

  const packageDirectory = dirname(executablePackageJsonPath);
  const unresolvedExecutablePath = resolve(
    packageDirectory,
    qualification.relativeExecutable,
  );
  if (!isInside(packageDirectory, unresolvedExecutablePath)) {
    throw new Error(
      `ACPX ${input.profile.agent} runtime executable escapes its package`,
    );
  }
  const executableDirectory = await realpath(dirname(unresolvedExecutablePath));
  if (!isInsideOrEqual(packageDirectory, executableDirectory)) {
    throw new Error(
      `ACPX ${input.profile.agent} runtime executable escapes its package`,
    );
  }
  const executablePath = resolve(
    executableDirectory,
    basename(unresolvedExecutablePath),
  );
  const verified = await openVerifiedRuntimeExecutable(
    executablePath,
    qualification.executableDigest,
    input.profile.agent,
  );

View on GitHub (pinned to 01ad858492)

Solutions

  1. Inspect the QUALIFIED_*_RUNTIME entry for the agent and fix relativeExecutable to a package-relative path like './bin/<name>' with no '../' or absolute prefix.
  2. Ensure the executable actually exists at that relative location inside the platform package's published layout.
  3. If a custom qualification was injected at runtime, remove the override and use the built-in qualified constants.
  4. Reinstall the affected package to rule out a modified local copy, then re-run verification.
  5. If intentionally relocating binaries, update both the qualification record and this containment check in the upstream repo together, keeping the path package-relative.

Example fix

// before (qualification entry)
relativeExecutable: "../shared/bin/acpx"
// after
relativeExecutable: "./bin/acpx"
Defensive patterns

Strategy: validation

Validate before calling

import { isInside } from "@paperclip/..."; // same helper family as the verifier
const rel = qualification.relativeExecutable;
const resolved = path.resolve(packageDir, rel);
if (!isInside(packageDir, resolved)) {
  throw new Error(`relativeExecutable '${rel}' escapes the package; use a package-relative path like './bin/acpx'`);
}

Type guard

function isPackageRelativeExecutable(packageDir: string, rel: string): boolean {
  const resolved = path.resolve(packageDir, rel);
  return resolved.startsWith(packageDir + path.sep);
}

Prevention

When it happens

Trigger: The qualification record's relativeExecutable contains traversal segments (../) or an absolute path such that resolve(packageDirectory, relativeExecutable) escapes packageDirectory; in practice this fires only with tampered qualification tables, a monkey-patched profile, or an incorrect custom QUALIFIED_* runtime entry.

Common situations: A developer adding a new qualified runtime entry who mistypes relativeExecutable (leading '/' or '../bin/...'); an attacker-modified build where pinned path constants were altered; symlink-free literal traversal introduced by a bad code patch.

Understand the failure class

Background: Path traversal blocked: "path escapes the workspace" and "outside site root" errors when a path will not stay inside its allowed directory — this error's family across 26 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/9f142321f871c115. Report an issue: GitHub.