Repository navigation
Bun hosted and vendored modes skip a URL or file: tarball copy of the patched package without warning, and vendored vex attests not_affected (the #326 fix covers npm locks only) #497
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:bunBunBun
on Oct 1, 2026 - added a commit that references this issue
on Oct 1, 2026 mikolalysenko commented
on Oct 1, 2026 CollaboratorAuthorMore actions[agent] Triaged as
priority:p1(Bun). This is closely related to #469 / #471, which open PR #472 is fixing: that PR adds the bundled-copy contest to the Bun/vlt rewriters and to VEX discovery (vex/discover/bun.rs). This issue covers a different tuple shape, URL/file:non-registry tuples (the Bun counterpart of #326/#345). #472 doesn't cover it. It should be fixed at the same Bun contest boundary once #472 lands, ideally on top of it, to avoid conflicting edits. Not a duplicate.
Generated by Claude Code
mikolalysenko commented
on Oct 2, 2026 CollaboratorAuthorMore actions[agent] New information: the binary
bun.lockbpath has the same defect (reproduced 2/2 on main61cfb9b, Linux).Shape: Bun 1.1.45
bun installwritesbun.lockbfor{"is-number": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz", "is-odd": "3.0.1"}. The lock has a root URL copy ofis-number@6.0.0and a nested registry copy underis-odd.scan --mode hosted:success,redirected: 2,warnings: [],skipped: []. Only the nested registry record is rewired.scan --mode vendored:success, no warnings.- After a cold-cache
bun install --frozen-lockfileon 1.1.45, 1.2.23 and 1.4.2 (all reading the same lockb),node_modules/is-odd/node_modules/is-number/index.jsis patched, but the rootnode_modules/is-number/index.jsthat the apprequires is not. vex: vendored (default and--no-verify) and hosted--no-verifyattestnot_affectedforpkg:npm/is-number@6.0.0. Hosted defaultvexcorrectly omits it (partialFailure).
So the fix at the Bun contest boundary needs to cover the lockb codec's tuple walk as well as the text-lock one.
Generated by Claude Code
mikolalysenko commented
on Oct 5, 2026 CollaboratorAuthorMore actions[agent] New information: still reproduces on main
6811b4e(Linux, Bun 1.4.2 text v2). In a lockfile-only checkout, the default hostedvexnow gives a falsenot_affectedtoo.Shape:
{"left-pad": "https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz", "dep": "file:./dep"}, wheredepdepends onleft-pad@1.3.0(a nested registry copy).scan --mode hosted:success,redirected: 1,warnings: []. Onlydep/left-padis pinned.- A fresh
bun install --frozen-lockfileleaves the rootnode_modules/left-padunpatched. The nested copy is patched. vexwithnode_modulespresent (default): correctly omits the purl (not_applied), as noted above.vexin a checkout with onlypackage.json,bun.lockanddep/(the usual "attest in CI before install" flow): exit 0,not_affectedforpkg:npm/left-pad@1.3.0, with and without--no-verify. Reproduced 2/2.
There's no 4.0.0 baseline, because it has no manifest-less vex (
Manifest not found). Lockfile-only discovery (lock_inventory/bun.rs, extended by #722) now also lists the URL tuple asleft-pad@1.3.0, but VEX attests from the hosted pin without contesting the unwired URL copy.
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actionsClaim-ID: agent/fix-bun-open-issues. Draft fix PR: #1009 (it covers all open
pm:bunissues).- added 8 commits that reference this issue
on Oct 7, 2026
[agent] Found by the scheduled Bun bug-hunt routine (ledger #306).
Summary
A Bun project can depend on a package by remote tarball URL (
"is-number": "https://registry.npmjs.org/is-number/-/is-number-6.0.0.tgz") or byfile:tarball. If a registry copy of the samename@versionis also inbun.lock(here, nested under a dependent), hosted and vendored scans rewire only the registry tuple.file:tuple is left alone. That's correct in itself, since Bun installs it from its spec.status: success,redirect.warnings: [], no vendor warning event.vex(default and--no-verify) then attestsnot_affectedfor thatname@version, even though the root copy the app loads (require('is-number')) is still the original bytes after a coldbun install --frozen-lockfile.vexcorrectly refuses (not_applied), butvex --no-verifyalso attests.#326 / #345 fixed exactly this for
package-lock.json: aredirect_npm_non_registry_entry_skipped/vendor_non_registry_entry_skippedwarning, andvexattests nothing while a non-registry copy is in the lock. The Bun rewriters and the Bun VEX discovery never got the equivalent. It's the same class as #469 (bundled) and #471 (vlt bundled).Impact
A false VEX attestation, plus a silent "success" that leaves the copy the application actually loads unpatched.
Repro (Bun 1.4.2, Linux)
The patch data came from a local mock of the patch API: batch, by-package,
patches/package,viewand the hosted tarball route. The patch prepends/* SOCKET-PATCHED */toindex.js.Expected vs actual
vexrow: "derived from … the hosted / vendored patch references the project's lockfiles wire"): when a non-registry copy of the patchedname@versionstays installed, both modes emit a stays-UNPATCHED warning andvexattests nothing for thatname@version, as it already does for npm.vex(and--no-verifyin either mode) attestsnot_affected.Controls:
vendor_lock_entry_not_foundand hosted warnsredirect_bun_entry_not_found, both correctly.vex→not_appliedforis-number, which is correct.Matrix (Linux; main
61cfb9b; each cell run twice on 1.3.14 / 1.4.2)vexvexvex --no-verifynot_applied✓not_applied✓not_applied✓not_applied✓file:./is-number-6.0.0.tgzRelease 4.0.0 behaves the same on 1.4.2 (vendored attests, no warnings). It isn't a regression. macOS and Windows weren't probed, because this is lock-parsing logic, not OS-specific code.
Suspect code
crates/socket-patch-core/src/vex/discover/bun.rs:249: a non-Socket tuple only counts asresolved_elsewherewhen it has a recorded or digit-leading version. Aname@https://…/name-6.0.0.tgzorname@./x.tgztuple has neither, so it never contests the vendored/hosted ref for the samename@version. Comparedrop_non_registry_installsinvex/discover/npm.rs:202.crates/socket-patch-core/src/patch/redirect/mod.rs:3773(rewrite_bun_lock): warns only when no tuple matched (!matched_any). There's no stays-unpatched warning when a non-registry tuple of the samename@versionis skipped beside a rewired one.crates/socket-patch-core/src/vendor/bun_lock.rs:679(preflight_package/classify): same, on the vendored side.