{"record":{"id":"537127881c641d47","repo":"paperclipai/paperclip","slug":"acpx-private-snapshot-digest-mismatch","errorCode":null,"errorMessage":"ACPX private snapshot digest mismatch","messagePattern":"ACPX private snapshot digest mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"critical","filePath":"packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts","lineNumber":1680,"sourceCode":"  return [\n    'const fs = require(\"node:fs\");',\n    'const { isBuiltin, registerHooks } = require(\"node:module\");',\n    'const { dirname, extname, join, normalize, relative, resolve } = require(\"node:path\");',\n    'const { fileURLToPath, pathToFileURL } = require(\"node:url\");',\n    \"const commandDirectory = process.argv[1];\",\n    \"const commandName = process.argv[2];\",\n    \"const dependencyAncestorCount = Number.parseInt(process.argv[3], 10);\",\n    \"const serverDependencyAncestorCount = Number.parseInt(process.argv[4], 10);\",\n    \"const serverPackageFormat = process.argv[5];\",\n    \"const dependencyAncestorFormats = JSON.parse(process.argv[6]);\",\n    \"const providerRuntimeExecutableCount = Number.parseInt(process.argv[7], 10);\",\n    `const providerRuntimeEnvironmentVariable = process.env.${VERIFIED_PROVIDER_RUNTIME_TARGET_ENV};`,\n    `delete process.env.${VERIFIED_PROVIDER_RUNTIME_TARGET_ENV};`,\n    `const snapshotHandoff = process.platform === \"darwin\" ? JSON.parse(process.env.${ACPX_PRIVATE_SNAPSHOT_ENV} || \"null\") : null;`,\n    'let privateSnapshot = null; if (snapshotHandoff) { const manifest = fs.readFileSync(snapshotHandoff.path); if (require(\"node:crypto\").createHash(\"sha256\").update(manifest).digest(\"hex\") !== snapshotHandoff.digest) throw new Error(\"ACPX snapshot manifest digest mismatch\"); privateSnapshot = JSON.parse(manifest); }',\n    `delete process.env.${ACPX_PRIVATE_SNAPSHOT_ENV};`,\n    'if (process.platform !== \"linux\" && !(process.platform === \"darwin\" && privateSnapshot && Array.isArray(privateSnapshot.roots) && privateSnapshot.roots.length === dependencyAncestorCount + 1)) throw new Error(\"ACPX provider requires verified package snapshots\");',\n    'const verifySnapshotBytes = (path, bytes) => { if (privateSnapshot && require(\"node:crypto\").createHash(\"sha256\").update(bytes).digest(\"hex\") !== privateSnapshot.digests[path]) throw new Error(\"ACPX private snapshot digest mismatch\"); };',\n    'if (privateSnapshot && providerRuntimeExecutableCount === 1) verifySnapshotBytes(privateSnapshot.executable, fs.readFileSync(privateSnapshot.executable));',\n    `if (!Number.isSafeInteger(dependencyAncestorCount) || dependencyAncestorCount < 0 || dependencyAncestorCount > ${MAX_DEPENDENCY_ANCESTORS}) throw new Error(\"ACPX provider dependency ancestry is invalid\");`,\n    'if (!Number.isSafeInteger(serverDependencyAncestorCount) || serverDependencyAncestorCount < 0 || serverDependencyAncestorCount > dependencyAncestorCount) throw new Error(\"ACPX provider package ancestry is invalid\");',\n    'if ((serverPackageFormat !== \"module\" && serverPackageFormat !== \"commonjs\") || !Array.isArray(dependencyAncestorFormats) || dependencyAncestorFormats.length !== dependencyAncestorCount || dependencyAncestorFormats.some((value) => value !== \"module\" && value !== \"commonjs\")) throw new Error(\"ACPX provider package formats are invalid\");',\n    'if (providerRuntimeExecutableCount !== 0 && providerRuntimeExecutableCount !== 1) throw new Error(\"ACPX provider runtime executable count is invalid\");',\n    `const providerRuntimeExecutableFd = ${DEPENDENCY_ANCESTOR_FD_START} + dependencyAncestorCount;`,\n    'if (providerRuntimeExecutableCount === 1) { if (providerRuntimeEnvironmentVariable !== \"CODEX_PATH\" && providerRuntimeEnvironmentVariable !== \"CLAUDE_CODE_EXECUTABLE\") throw new Error(\"ACPX provider runtime environment target is invalid\"); fs.fstatSync(providerRuntimeExecutableFd); process.env[providerRuntimeEnvironmentVariable] = privateSnapshot ? privateSnapshot.executable : \"/proc/\" + process.pid + \"/fd/\" + providerRuntimeExecutableFd; } else if (providerRuntimeEnvironmentVariable !== undefined) throw new Error(\"ACPX provider runtime environment target is unexpected\");',\n    ...(guarded\n      ? [\n          `const guardianFd = ${DEPENDENCY_ANCESTOR_FD_START} + dependencyAncestorCount + providerRuntimeExecutableCount;`,\n          'const guardian = fs.createReadStream(\"\", { fd: guardianFd, autoClose: false });',\n          `const reapCurrentProviderProcessGroup = ${reapCurrentProviderProcessGroup.toString()};`,\n          \"const killProviderProcess = process.kill.bind(process);\",\n          \"const providerProcessId = process.pid;\",\n          \"const exitProviderProcess = process.exit.bind(process);\",\n          \"let guardianLost = false;\",\n          \"const reapOnGuardianLoss = () => { if (guardianLost) return; guardianLost = true; reapCurrentProviderProcessGroup(killProviderProcess, providerProcessId, exitProviderProcess); };\",\n          'guardian.once(\"end\", reapOnGuardianLoss);',","sourceCodeStart":1662,"sourceCodeEnd":1698,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/packages/paperclip-runner/src/drivers/acpx/installation-integrity.ts#L1662-L1698","documentation":"Thrown by the verifySnapshotBytes helper in the child-process bootstrap. When a private snapshot exists and a provider runtime executable is in use (providerRuntimeExecutableCount === 1), the executable bytes are read and sha256-hashed and compared to the digest recorded in the privateSnapshot manifest at privateSnapshot.digests[path]. A mismatch means the executable file's contents differ from what was verified at snapshot creation — a tamper/corruption guard on the provider binary itself.","triggerScenarios":"On darwin (or any platform using private snapshots) spawning a provider with providerRuntimeExecutableCount === 1 where sha256(fs.readFileSync(privateSnapshot.executable)) !== privateSnapshot.digests[privateSnapshot.executable].","commonSituations":"The provider binary (e.g. codex or claude-code executable) was updated/upgraded after the snapshot was built; npm/pnpm reinstalled or hoisted a different version; a cache or antivirus modified the file; the snapshot manifest is stale relative to node_modules.","solutions":["Re-run the ACPX installation-verification step to rebuild the snapshot digests against the current executable.","Pin the provider package version so installs don't silently swap the binary after snapshot creation.","Delete node_modules/snapshot artifacts and reinstall to rule out a corrupted or partially-written executable.","Investigate unexpected writers (antivirus, sync tools) if the binary keeps changing under the snapshot."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import { createHash } from \"node:crypto\";\nconst bytes = fs.readFileSync(privateSnapshot.executable);\nconst digest = createHash(\"sha256\").update(bytes).digest(\"hex\");\nif (digest !== privateSnapshot.digests[privateSnapshot.executable]) {\n  throw new Error(\"provider executable changed; rebuild snapshot before spawn\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Re-run installation verification after upgrading provider packages (codex/claude-code)","Pin provider package versions to avoid silent binary swaps","Exclude snapshot/node_modules paths from antivirus and sync tools","Rebuild snapshots rather than hand-editing their manifests"],"tags":["integrity","checksum","security","process-spawn"],"backgroundTag":"checksum-mismatch","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"}