{"record":{"id":"b778728f11a22885","repo":"paperclipai/paperclip","slug":"verified-runtime-executable-descriptor-is-invalid","errorCode":null,"errorMessage":"Verified runtime executable descriptor is invalid","messagePattern":"Verified runtime executable descriptor is invalid","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/drivers/acpx/verified-runtime-executable.ts","lineNumber":29,"sourceCode":"\n/**\n * Recover the runner-authenticated executable inherited by a descriptor-loaded\n * sidecar. Linux descendants must explicitly inherit this descriptor: Node\n * resolves process.execPath and /proc/self/exe to a deleted memfd alias that a\n * later exec cannot reopen.\n */\nexport function verifiedRuntimeExecutable(\n  environment: NodeJS.ProcessEnv = process.env,\n  platform: NodeJS.Platform = process.platform,\n  _currentPid: number = process.pid,\n  fallback: string = process.execPath,\n): string {\n  const configured = environment[VERIFIED_RUNTIME_EXECUTABLE_ENV];\n  if (configured === undefined) return fallback;\n\n  if (platform === \"linux\") {\n    if (/^\\/proc\\/self\\/fd\\/[0-9]+$/.test(configured)) return configured;\n    throw new Error(\"Verified runtime executable descriptor is invalid\");\n  }\n\n  if (platform === \"darwin\") {\n    if (\n      !isAbsolute(fallback) ||\n      resolve(fallback) !== fallback ||\n      configured !== fallback\n    ) {\n      throw new Error(\"Verified runtime executable path is invalid\");\n    }\n    // The Rust supervisor materializes the authenticated runtime as a private,\n    // read-only executable and starts this process from that exact pathname.\n    // Descendants may inherit the handoff variable, but they cannot nominate a\n    // different absolute path and have it treated as verified.\n    return fallback;\n  }\n\n  throw new Error(","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/verified-runtime-executable.ts#L11-L47","documentation":"verifiedRuntimeExecutable() reads the PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE handoff env var to recover the runner-authenticated executable in a descriptor-loaded sidecar. On Linux the value must be a /proc/self/fd/<n> descriptor path; anything else is rejected so an unverified path can never be treated as the verified runtime.","triggerScenarios":"Calling verifiedRuntimeExecutable() (directly or via executable) on Linux when the env var is set to a non-descriptor value, e.g. a filesystem path, relative path, or /proc/self/exe, or when the env var was set manually/corrupted by a wrapper script.","commonSituations":"Manually exporting PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE when launching the runner outside the Rust supervisor; a shell wrapper rewriting the env value; spawning a Linux child without the fd-passing table the value expects.","solutions":["Remove PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE so the fallback (process.execPath) is used when no descriptor handoff occurred","Let the supervisor perform the handoff properly: inherit the fd and set the value to /proc/self/fd/<n>","Do not run the runner under wrappers/scripts that rewrite or re-export the env var","Ensure the source fd referenced by the value actually exists in the child's fd table"],"exampleFix":"// before\nenv.PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE = \"/usr/local/bin/paperclip-runner\"; // linux\n// after\ndelete env.PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE; // use process.execPath fallback","handlingStrategy":"validation","validationCode":"const v = process.env.PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE;\nif (v !== undefined && process.platform === \"linux\" &&\n    !/^\\/proc\\/self\\/fd\\/[0-9]+$/.test(v)) {\n  delete process.env.PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE; // or fix the value\n}","typeGuard":"function isValidLinuxDescriptor(v) {\n  return typeof v === \"string\" && /^\\/proc\\/self\\/fd\\/[0-9]+$/.test(v);\n}","tryCatchPattern":"try {\n  const exe = verifiedRuntimeExecutable();\n} catch (err) {\n  if (err.message === \"Verified runtime executable descriptor is invalid\") {\n    const { [VERIFIED_RUNTIME_EXECUTABLE_ENV]: _omit, ...clean } = process.env;\n    return verifiedRuntimeExecutable(clean);\n  }\n  throw err;\n}","preventionTips":["Never hand-set PAPERCLIP_VERIFIED_RUNTIME_EXECUTABLE; only the supervisor should","Use env -i or a scrubbed env when launching the runner manually","Keep fd-passing (stdio entries) intact when the env var is present","Avoid wrapper scripts that rewrite inherited env values"],"tags":["linux","env-var","fd-handoff","security"],"backgroundTag":"invalid-env-var-value","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}