[agent] Found by the scheduled Bun bug-hunt routine (ledger #306).
Summary
Bun has its own patching feature, bun patch <pkg> + bun patch --commit. It records "patchedDependencies": { "left-pad@1.3.0": "patches/left-pad@1.3.0.patch" } in package.json and bun.lock, and applies the patch on every install. When socket-patch rewires that same package (scan --mode hosted, which writes a URL 3-tuple, or scan --mode vendored, which writes a .socket/vendor/... local tarball tuple), Bun stops applying the user's patch. The name@version key no longer matches the non-registry resolution. The command reports success with no warning, the next bun install --frozen-lockfile exits 0, and the installed package carries Socket's patch but not the project's own committed patch.
socket-patch has no handling for patchedDependencies at all: grep -rn patchedDependencies over crates/ and docs/ returns nothing. It doesn't refuse, warn or preserve.
Impact
A project-authored fix, which may be a security fix or a functional one, silently disappears from every fresh install and from CI. Nothing in the envelope, the lock or the install output signals it. Only rollback brings it back: I verified that after rollback --yes a fresh frozen install re-applies the user patch.
Repro (Linux, bun 1.4.2, main f6b7fb9)
mkdir bp && cd bp
printf '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}\n' > package.json
bun install
bun patch left-pad
echo "// USER-BUN-PATCH" >> node_modules/left-pad/index.js
bun patch --commit node_modules/left-pad # writes patches/left-pad@1.3.0.patch + patchedDependencies
# control: a fresh frozen install keeps the user patch
# -> node_modules/left-pad/index.js ends with "// USER-BUN-PATCH"
socket-patch scan --mode hosted --json --yes --api-url <mock> --org test-org --api-token fake # or --mode vendored
# status "success", redirect.redirected 1, redirect.warnings []
mkdir ../fresh && cp -a package.json bun.lock patches .socket ../fresh/ && cd ../fresh
bun install --frozen-lockfile; echo $? # 0
grep -c SOCKET-PATCHED node_modules/left-pad/index.js # 1
grep -c USER-BUN-PATCH node_modules/left-pad/index.js # 0 <- user's patch gone
bun.lock after the rewrite still lists "patchedDependencies": { "left-pad@1.3.0": "patches/left-pad@1.3.0.patch" }, but the package entry is now ["left-pad@http://…/left-pad-1.3.0.tgz", {}, "sha512-…"] (hosted) or ["left-pad@.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz", {}, "sha512-…"] (vendored). Bun applies neither the patch nor an error.
Binary bun.lockb (saveTextLockfile = false) behaves the same in both modes.
Expected vs actual
- Expected: rewiring must not silently change what gets installed beyond Socket's patch. Either refuse loudly the way other unsupported lock shapes are refused (for comparison, pnpm's vendored backend refuses a target with
patchedDependencies as vendor_lock_entry_unsupported), or carry the user patch forward (re-key patchedDependencies, or fold the patch into the served/vendored tarball) and say so. docs/testing/bun-compatibility.md's claim that the rewrite keeps the meta object and version line verbatim doesn't cover this. It's an unmeasured shape.
- Actual:
success, no warning, user patch dropped on every fresh install.
OS × version (hosted and vendored, text lock)
| OS |
Bun 1.2.23 |
Bun 1.3.9 |
Bun 1.3.14 |
Bun 1.4.2 |
| Linux |
fail |
fail |
fail |
fail (also bun.lockb) |
| macOS (macos-latest) |
fail |
— |
fail |
fail |
| Windows (windows-latest) |
fail |
— |
fail |
fail |
Releases: 4.0.0 and 3.3.0 behave the same, so it isn't a regression.
Suspect code
crates/socket-patch-core/src/patch/redirect/mod.rs:4329 (rewrite_bun_lock) and patch/redirect/bun_binary.rs:19 (rewrite_bun_binary) rewrite the package entry without consulting patchedDependencies.
- The vendored bun backend under
crates/socket-patch-core/src/vendor/bun_lock.rs (classify, check_workspace_compatibility) has no gate for it either.
Probe run (3 OS × bun 1.2.23 / 1.3.14 / 1.4.2, main built on each runner; cases bunpatch-hosted / bunpatch-vendored): https://github.com/SocketDev/socket-patch/actions/runs/36765789215
[agent] Found by the scheduled Bun bug-hunt routine (ledger #306).
Summary
Bun has its own patching feature,
bun patch <pkg>+bun patch --commit. It records"patchedDependencies": { "left-pad@1.3.0": "patches/left-pad@1.3.0.patch" }inpackage.jsonandbun.lock, and applies the patch on every install. When socket-patch rewires that same package (scan --mode hosted, which writes a URL 3-tuple, orscan --mode vendored, which writes a.socket/vendor/...local tarball tuple), Bun stops applying the user's patch. Thename@versionkey no longer matches the non-registry resolution. The command reportssuccesswith no warning, the nextbun install --frozen-lockfileexits 0, and the installed package carries Socket's patch but not the project's own committed patch.socket-patch has no handling for
patchedDependenciesat all:grep -rn patchedDependenciesovercrates/anddocs/returns nothing. It doesn't refuse, warn or preserve.Impact
A project-authored fix, which may be a security fix or a functional one, silently disappears from every fresh install and from CI. Nothing in the envelope, the lock or the install output signals it. Only
rollbackbrings it back: I verified that afterrollback --yesa fresh frozen install re-applies the user patch.Repro (Linux, bun 1.4.2, main
f6b7fb9)bun.lockafter the rewrite still lists"patchedDependencies": { "left-pad@1.3.0": "patches/left-pad@1.3.0.patch" }, but the package entry is now["left-pad@http://…/left-pad-1.3.0.tgz", {}, "sha512-…"](hosted) or["left-pad@.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz", {}, "sha512-…"](vendored). Bun applies neither the patch nor an error.Binary
bun.lockb(saveTextLockfile = false) behaves the same in both modes.Expected vs actual
patchedDependenciesasvendor_lock_entry_unsupported), or carry the user patch forward (re-keypatchedDependencies, or fold the patch into the served/vendored tarball) and say so. docs/testing/bun-compatibility.md's claim that the rewrite keeps the meta object and version line verbatim doesn't cover this. It's an unmeasured shape.success, no warning, user patch dropped on every fresh install.OS × version (hosted and vendored, text lock)
bun.lockb)Releases: 4.0.0 and 3.3.0 behave the same, so it isn't a regression.
Suspect code
crates/socket-patch-core/src/patch/redirect/mod.rs:4329(rewrite_bun_lock) andpatch/redirect/bun_binary.rs:19(rewrite_bun_binary) rewrite the package entry without consultingpatchedDependencies.crates/socket-patch-core/src/vendor/bun_lock.rs(classify,check_workspace_compatibility) has no gate for it either.Probe run (3 OS × bun 1.2.23 / 1.3.14 / 1.4.2, main built on each runner; cases
bunpatch-hosted/bunpatch-vendored): https://github.com/SocketDev/socket-patch/actions/runs/36765789215