You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Vendored npm vex and vendor --check fail after any npm 7–10 npm install on a lockfileVersion 2 lock, because npm drops resolved from the legacy mirror and #813 treats that as an unpatched npm 6 install (regression) #879
[agent] Found by the scheduled npm bug-hunt routine (ledger #302).
Summary
After a vendored scan of an npm lockfileVersion 2 project, an ordinary npm install with npm 7, 8 or 10 re-saves the lock. npm's serializer never writes resolved for a file: resolution in the legacy dependencies mirror, so the mirror node keeps only version and the patched integrity. The packages half is still wired to .socket/vendor/…, and the installed tree is patched.
Since #813 (the #432 fix, f023506), drop_mirror_unwired reads a mirror node with no resolved as "resolves from a non-Socket source". So:
vex refuses the patch: vendor_unwired / patched_ref_unattributable ("… still resolves it to "no resolved url", so npm 6 installs the unpatched bytes"), exit 1.
vendor --check exits 1: vendor_check_failed "wiring missing: no lockfile or config references .socket/vendor/npm/ any more, so a fresh install gets the unpatched package".
Both claims are false. The packages entry still references the artifact, a fresh npm 7+ npm ci installs the patched bytes, and npm 6 doesn't install unpatched bytes from that mirror node either: the node keeps the patchedintegrity, so a cold-cache npm 6 npm ci fails closed with EINTEGRITY (ledger #302 already records this as npm behaviour). That's the same fail-closed outcome #813 accepts for a hosted alias mirror node (redirect_npm_legacy_alias_client), which vex still attests.
Impact
Every npm 7/8 team, and every npm 9–11 team with an existing v2 lock, that vendors a patch and then runs npm install for any reason gets a red vendor --check in CI and loses its VEX statement. The suggested remedy loops: re-running scan --mode vendored re-adds resolved (check passes), and the next npm install strips it again. Hosted mode isn't affected, because npm keeps an http(s) resolved in the mirror.
Repro (Linux, npm 8.19.4, Node 22; a local mock patch API serving one free left-pad patch)
The npm 6 claim, checked on the re-saved lock: npm6 ci --cache <empty> gives exit 1 with EINTEGRITY wanted sha512-<patched> but got sha512-<registry>.
Expected vs actual
Expected: a packages entry wired to the vendored artifact, plus a mirror node with the matching patched integrity and no resolved, counts as wired (or at worst gets an npm 6 caveat warning). That's what vendor --check and vex did before Fix npm 6 installing unpatched aliases (#432) #813. CLI_CONTRACT / vendor --check promise a failure only when "a fresh install gets the unpatched package", and none does here.
Actual: exit 1 from both, with a diagnosis saying no lockfile references the artifact.
Matrix (Linux)
npm
lock
npm install re-save
vendor --check
vex
7.24.2
v2
strips mirror resolved
fail
fail
8.19.4
v2 (plain dep and an lp@npm:left-pad alias)
strips
fail (3×)
fail
10.9.4
existing v2 (kept as v2)
strips
fail
fail
any
v3 (no mirror)
n/a
pass
pass
hosted, 8.19.4
v2
keeps http resolved
n/a
pass
macOS and Windows weren't probed (probe branches are paused), but the logic is OS-independent.
Bisect
1714299 (parent of f023506): vendor --check exit 0, vex exit 0 on the same re-saved locks.
crates/socket-patch-core/src/vex/discover/npm.rs:289-301 (drop_mirror_unwired): node.resolved.map_or_else(Located::default, …) turns a missing resolved into "neither vendored nor hosted", then into resolved_elsewhere plus unwired. A mirror node with no resolved whose integrity equals the wired packages entry's (patched) integrity should contest nothing. The vendor --check wiring verdict seems to come from the same discovery, given the identical exit and timing.
[agent] Found by the scheduled npm bug-hunt routine (ledger #302).
Summary
After a vendored scan of an npm lockfileVersion 2 project, an ordinary
npm installwith npm 7, 8 or 10 re-saves the lock. npm's serializer never writesresolvedfor afile:resolution in the legacydependenciesmirror, so the mirror node keeps onlyversionand the patchedintegrity. Thepackageshalf is still wired to.socket/vendor/…, and the installed tree is patched.Since #813 (the #432 fix, f023506),
drop_mirror_unwiredreads a mirror node with noresolvedas "resolves from a non-Socket source". So:vexrefuses the patch:vendor_unwired/patched_ref_unattributable("… still resolves it to "noresolvedurl", so npm 6 installs the unpatched bytes"), exit 1.vendor --checkexits 1:vendor_check_failed"wiring missing: no lockfile or config references .socket/vendor/npm/ any more, so a fresh install gets the unpatched package".Both claims are false. The
packagesentry still references the artifact, a fresh npm 7+npm ciinstalls the patched bytes, and npm 6 doesn't install unpatched bytes from that mirror node either: the node keeps the patchedintegrity, so a cold-cache npm 6npm cifails closed with EINTEGRITY (ledger #302 already records this as npm behaviour). That's the same fail-closed outcome #813 accepts for a hosted alias mirror node (redirect_npm_legacy_alias_client), whichvexstill attests.Impact
Every npm 7/8 team, and every npm 9–11 team with an existing v2 lock, that vendors a patch and then runs
npm installfor any reason gets a redvendor --checkin CI and loses its VEX statement. The suggested remedy loops: re-runningscan --mode vendoredre-addsresolved(check passes), and the nextnpm installstrips it again. Hosted mode isn't affected, because npm keeps an http(s)resolvedin the mirror.Repro (Linux, npm 8.19.4, Node 22; a local mock patch API serving one free left-pad patch)
The npm 6 claim, checked on the re-saved lock:
npm6 ci --cache <empty>gives exit 1 withEINTEGRITY wanted sha512-<patched> but got sha512-<registry>.Expected vs actual
packagesentry wired to the vendored artifact, plus a mirror node with the matching patchedintegrityand noresolved, counts as wired (or at worst gets an npm 6 caveat warning). That's whatvendor --checkandvexdid before Fix npm 6 installing unpatched aliases (#432) #813. CLI_CONTRACT /vendor --checkpromise a failure only when "a fresh install gets the unpatched package", and none does here.Matrix (Linux)
npm installre-savevendor --checkvexresolvedlp@npm:left-padalias)resolvedmacOS and Windows weren't probed (probe branches are paused), but the logic is OS-independent.
Bisect
1714299(parent of f023506):vendor --checkexit 0,vexexit 0 on the same re-saved locks.f023506(Fix npm 6 installing unpatched aliases (#432) #813) throughc644ab0(current main): both exit 1. First bad commit: f023506.Suspect code
crates/socket-patch-core/src/vex/discover/npm.rs:289-301(drop_mirror_unwired):node.resolved.map_or_else(Located::default, …)turns a missingresolvedinto "neither vendored nor hosted", then intoresolved_elsewhereplusunwired. A mirror node with noresolvedwhoseintegrityequals the wiredpackagesentry's (patched) integrity should contest nothing. Thevendor --checkwiring verdict seems to come from the same discovery, given the identical exit and timing.