{"record":{"id":"91d7e8d0f2c153ad","repo":"oven-sh/bun","slug":"size-mismatch","errorCode":null,"errorMessage":"size mismatch","messagePattern":"size mismatch","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"bench/copyfile/node.mitata.mjs","lineNumber":15,"sourceCode":"import { copyFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { bench, run } from \"../runner.mjs\";\n\nfunction runner(ready) {\n  for (let size of [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000]) {\n    const rand = new Int32Array(size);\n    for (let i = 0; i < size; i++) {\n      rand[i] = (Math.random() * 1024 * 1024) | 0;\n    }\n    const dest = `/tmp/fs-test-copy-file-${((Math.random() * 10000000 + 100) | 0).toString(32)}`;\n    const src = `/tmp/fs-test-copy-file-${((Math.random() * 10000000 + 100) | 0).toString(32)}`;\n    writeFileSync(src, Buffer.from(rand.buffer), { encoding: \"buffer\" });\n    const { size: fileSize } = statSync(src);\n    if (fileSize !== rand.byteLength) {\n      throw new Error(\"size mismatch\");\n    }\n    ready(src, dest, new Uint8Array(rand.buffer));\n  }\n}\nrunner((src, dest, rand) =>\n  bench(`copyFileSync(${rand.buffer.byteLength} bytes)`, () => {\n    copyFileSync(src, dest);\n    // const output = readFileSync(dest).buffer;\n\n    // for (let i = 0; i < output.length; i++) {\n    //   if (output[i] !== rand[i]) {\n    //     throw new Error(\n    //       \"Files are not equal\" + \" \" + output[i] + \" \" + rand[i] + \" \" + i\n    //     );\n    //   }\n    // }\n  }),\n);","sourceCodeStart":1,"sourceCodeEnd":33,"githubUrl":"https://github.com/oven-sh/bun/blob/8c5296ac459e8252d3cd702f3fbcbb0c249d95d5/bench/copyfile/node.mitata.mjs#L1-L33","documentation":"The integrity hash recorded for a package does not match the tarball bytes that were downloaded. Verification happens in ExtractTarball::run before extraction (src/install/extract_tarball.rs:47-58) and while streaming the download (src/install/TarballStream.rs:1121); for GitHub/URL/local tarballs Bun deliberately computes and pins the hash in the lockfile so a compromised server cannot silently swap content (comment at extract_tarball.rs:62-65).","triggerScenarios":"`bun install` with a lockfile whose pinned sha512/sha1 differs from the fetched artifact: registry mirror out of sync for the same version, a corrupted cache entry, a GitHub tarball re-generated for a moving ref (branch/HEAD) while the lockfile pins the old hash, or a yanked-and-republished package.","commonSituations":"Switching between registry mirrors that serve different bytes; using `github:owner/repo#main` style deps whose tarballs change; CI cache corruption; in rare cases actual supply-chain tampering.","solutions":["Clear the cache and reinstall: `bun pm cache rm && bun install`","For URL/GitHub tarballs pinned to a branch, re-record the hash: re-run `bun add <url-or-github-spec>` so the lockfile captures the current tarball","Compare hashes out-of-band: `npm view <pkg> dist.integrity` vs. curl the tarball and compute its sha512","If tampering is plausible, do NOT bypass the check: pin an exact version/commit and verify the artifact from the official registry"],"exampleFix":"// before (package.json): moving ref, hash drifts on every push\n\"ui-kit\": \"github:acme/ui-kit#main\"\n\n// after: immutable ref, lockfile hash stays valid\n\"ui-kit\": \"github:acme/ui-kit#1f0e3d8c2a7b94f6cc4e21c1d7f3a9b8\"","handlingStrategy":"validation","validationCode":"// Before promoting a URL/git tarball dep, confirm the bytes match what you will pin:\nconst res = Bun.spawnSync([\"npm\", \"view\", \"your-pkg\", \"dist.integrity\"], { stdout: \"pipe\" });\nconst pinned = Bun.file(\"bun.lock\").text(); // or your recorded hash\nconsole.log(\"registry integrity:\", res.stdout.toString().trim());","typeGuard":"const isValidSRI = (s) => /^sha(1|256|384|512)-[A-Za-z0-9+/=]+$/.test(s ?? \"\");","tryCatchPattern":null,"preventionTips":["Pin git/URL dependencies to immutable refs (commit SHA or tag), never branches","Use one registry consistently; do not switch mirrors between installs","Run CI with --frozen-lockfile so hashes are checked, not recomputed","Treat an unexpected IntegrityCheckFailed as a possible attack: verify out-of-band instead of deleting the check"],"tags":["install","integrity","security","cache","lockfile"],"backgroundTag":null,"analyzedSha":"8c5296ac459e8252d3cd702f3fbcbb0c249d95d5","analyzedAt":"2026-08-16T08:01:58.794Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}