fix(vendor): match bun tuples on version, keep CRLF - #180
Open
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
Open
fix(vendor): match bun tuples on version, keep CRLF#180Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
Conversation
The bun backend's already-vendored classification matched on package name alone, never the vendored leaf's version. With patches for two versions of one package in the same bun.lock (a root instance plus a nested one), the second vendor pass classified the first pass's fresh tuple as its own stale edit and rewrote it to the OTHER version's tarball: bun then silently installed the wrong version everywhere, state.json claimed both patches applied, and a later revert left the entry pointing at a deleted tarball (frozen installs hard-fail with ENOENT). The same name-only match let the pre-flight accept a lock whose only same-name entries were vendored tuples of another version. The Ours arm now also requires the parsed vendor path's leaf to equal the target's uuid-independent `<name>-<version>.tgz` leaf, so other-version vendored tuples classify as foreign and are never touched; re-vendoring the same version under a new patch uuid still rewrites as before. Also preserve a trailing `\r` on rewritten entry lines: the grammar tolerantly trimmed it while parsing a CRLF bun.lock but the rebuilt line re-emitted LF only, leaving one mixed-ending line in an otherwise CRLF file (noisy diffs and autocrlf churn on Windows checkouts). Regression tests pin both: a two-version vendor + revert round-trip, a pre-flight refusal when only another version's vendored tuples exist, and a CRLF lock that stays CRLF through vendor, re-run, and revert. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Wenxin Jiang (Wenxin-Jiang)
approved these changes
Aug 14, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two findings from the 2026-08-13 vendored-bun audit (origin/main 4e5288e):
classify() Ours arm ignores version — vendoring two versions of one package cross-clobbers bun.lock entries (high). The already-vendored 3-tuple classification matched on package name alone, never the vendored leaf's version. With patches for two versions of one package in the same bun.lock (e.g. root
left-pad@1.2.0plus nestedhaspad/left-pad@1.3.0), the second vendor pass classified the first pass's fresh tuple as its own stale edit and rewrote it to the OTHER version's tarball. Both patches then reported applied with zero warnings whilebun install --frozen-lockfilesilently deduped everything to one version — the other patch was not in effect despite state.json claiming it was. A latervendor --revertrestored neither entry (the clobbering record'soriginalwas None), deleted both uuid dirs, and left the lock pointing at a deleted tarball: frozen installs hard-fail with ENOENT. The same name-only match let the pre-flighthas_matchgate accept a lock whose only same-name entries were vendored tuples of another version.CRLF bun.lock: rewritten entry lines silently drop the
\r(low).vendor_bunsplits on\n, the grammar tolerantly trims a trailing\rwhile parsing, but the rebuilt entry line re-emitted LF only — leaving one mixed-ending line in an otherwise-CRLF file (noisy diffs and autocrlf churn on Windows checkouts), in a module whose contract is byte-exact conservative surgery.Fix
classify()'s Ours arm now also requires the parsed vendor path's leaf to equal the target's uuid-independenttgz_rel_leaf(name, version)(<name>-<version>.tgz, scope-aware — the exact leafstage_patch_packproduces), so vendored tuples of another version of the same package classify as foreign and are never touched. This is the same single classification both the pre-flight gate and the rewrite loop consume, so both holes close together. Same-version re-vendoring under a new patch uuid still rewrites as before.\rdetected on the original line, so a CRLF lock stays uniformly CRLF through vendor, in-sync re-run, and revert.No skipped findings.
Testing
two_vendored_versions_of_one_package_do_not_cross_clobber— BN4C two-version vendor: each instance points at its own uuid/version tarball, the second pass records the true registry original, and a full revert byte-restores the lock with both uuid dirs removed.preflight_refuses_when_only_other_version_vendored_tuples_exist— lock whose only same-name entry is a vendored other-version tuple refusesvendor_lock_entry_not_foundand never rewrites.crlf_lock_keeps_crlf_on_rewritten_lines_and_reverts_byte_exact— CRLF lock stays CRLF through vendor, byte-stable in-sync re-run, and byte-exact revert.cargo test -p socket-patch-core --lib: 2078 passed, 0 failed.cargo test -p socket-patch-cli --test e2e_vendor_bun_build: 6 passed, 0 failed.cargo test -p socket-patch-cli --test e2e_redirect_bun_build: 7 passed, 0 failed (hosted bun rewriter untouched — it uses separate classification).🤖 Generated with Claude Code
Note
Medium Risk
Changes lockfile classification and line re-emission in the bun vendor path; incorrect matching could still break frozen installs or revert, but the change narrows matching logic to fix a known cross-clobber bug with targeted tests.
Overview
Fixes bun.lock vendoring so two patched versions of the same package can coexist without one vendor pass rewriting the other’s tuple, and so CRLF locks stay byte-consistent through edit and revert.
Version-aware classification:
classify()’s vendored (Ours) arm now requires the vendor tarball leaf to matchtgz_rel_leaf(name, version)(same<name>-<version>.tgzshape as staging), not just the package name. That applies to both the pre-flight “has a rewritable entry” check and the rewrite loop, so another version’s vendored tuple is treated as foreign—refused when there’s no registry match, never cross-clobbered when vendoring a second version.CRLF: Rewritten package entry lines re-emit a trailing
\rwhen the original line had one, so mixed LF/CRLF doesn’t appear after vendor or revert.Three regression tests cover dual-version vendoring/revert, pre-flight refusal when only other-version vendored tuples exist, and CRLF round-trip.
Reviewed by Cursor Bugbot for commit 02e4c37. Configure here.