{"record":{"id":"54e79e76d5f06635","repo":"paperclipai/paperclip","slug":"acpx-agent-runtime-executable-must-be-a-real-re","errorCode":null,"errorMessage":"ACPX ${agent} runtime executable must be a real regular file","messagePattern":"ACPX (.+?) runtime executable must be a real regular file","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts","lineNumber":1026,"sourceCode":"  } finally {\n    await handle.close();\n  }\n}\n\nasync function openVerifiedRuntimeExecutable(\n  executablePath: string,\n  expectedDigest: string,\n  agent: string,\n): Promise<{ handle: FileHandle; identity: VerifiedAcpxCommandIdentity }> {\n  const lexicalBefore = await lstat(executablePath, { bigint: true }).catch(\n    () => null,\n  );\n  if (\n    lexicalBefore === null ||\n    lexicalBefore.isSymbolicLink() ||\n    !lexicalBefore.isFile()\n  ) {\n    throw new Error(\n      `ACPX ${agent} runtime executable must be a real regular file`,\n    );\n  }\n\n  let handle: FileHandle;\n  try {\n    handle = await open(\n      executablePath,\n      verifiedExecutableOpenFlags(process.platform, constants.O_NOFOLLOW),\n    );\n  } catch {\n    throw new Error(\n      `ACPX ${agent} runtime executable could not be opened as a no-follow regular file`,\n    );\n  }\n\n  try {\n    const before = await handle.stat({ bigint: true });","sourceCodeStart":1008,"sourceCodeEnd":1044,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts#L1008-L1044","documentation":"`openVerifiedRuntimeExecutable` in packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts performs a TOCTOU-hardened verification of the ACPX runtime executable before executing it. Before opening the file, it `lstat`s the path and requires the entry to exist and be a real regular file (not a symlink, directory, fifo, etc.). If the lstat fails or the entry is anything other than a regular file, this error is thrown to refuse running a potentially attacker-controlled path.","triggerScenarios":"Calling openVerifiedRuntimeExecutable (via the ACPX runtime spawn path) when `lstat(executablePath)` returns null (path missing/unreadable), the entry is a symlink (common with npm-installed bins in node_modules/.bin), or the entry is a directory/device/fifo rather than a regular file.","commonSituations":"ACPX binary path misconfigured (points at a wrapper script dir or a symlinked global install); npm/pnpm 'bin' shims that are symlinks; binary not downloaded yet so the path does not exist; permissions on a parent directory deny stat; antivirus or cleanup tool removed the file mid-session.","solutions":["Verify the configured executable path exists and is a regular file, not a symlink: `lstat` it yourself before configuring the runtime","Replace symlinked bin paths with the resolved real binary path (`fs.realpathSync` then check `statSync(...).isFile()` and reject if still a symlink at lstat level)","Reinstall/repair the ACPX runtime so the binary is materialized on disk at the expected path","Check parent-directory permissions so the process can stat the path","Point the runtime at the canonical install location managed by the installer rather than a user-provided PATH lookup"],"exampleFix":"// before\nconst bin = '/usr/local/bin/acpx'; // symlink into node_modules\nawait spawnAcppRuntime({ executablePath: bin });\n// after\nimport { lstatSync } from 'node:fs';\nconst st = lstatSync('/usr/local/bin/acpx');\nif (st.isSymbolicLink() || !st.isFile()) {\n  throw new Error('configure the resolved real binary path, not a symlink');\n}\nawait spawnAcppRuntime({ executablePath: '/usr/local/lib/acpx/bin/acpx' });","handlingStrategy":"validation","validationCode":"import { lstatSync } from 'node:fs';\nfunction isRealRegularFile(p: string): boolean {\n  try {\n    const st = lstatSync(p);\n    return !st.isSymbolicLink() && st.isFile();\n  } catch {\n    return false;\n  }\n}\nif (!isRealRegularFile(executablePath)) {\n  throw new Error(`resolve acpx binary to a real file: ${executablePath}`);\n}","typeGuard":"function isRealRegularStat(st: { isFile(): boolean; isSymbolicLink(): boolean }): boolean {\n  return !st.isSymbolicLink() && st.isFile();\n}","tryCatchPattern":null,"preventionTips":["Always configure the realpath of the binary, never a symlinked PATH entry or .bin shim","Pre-flight check the executable path with lstat before starting runs","Reinstall the runtime if the path is missing instead of hand-placing files","Keep the install directory out of paths managed by aggressive cleanup/AV tools"],"tags":["filesystem","security","acpx","symlink"],"backgroundTag":"file-not-found","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}