Vendored npm rollback / remove / vendor --revert on a lockfileVersion 2 lock fail after any `npm install`, yet half-revert the lock: `packages` goes back to the registry while the legacy mirror keeps the patched integrity, and npm 6 then fails EINTEGRITY
I maintainer di solito rispondono entro 1 giorno
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 35/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- nodejs, rust
- Ambito
- build-system, tooling
Direzione di ricerca
Start with the drift verdict in crates/socket-patch-core/src/vendor/npm_lock.rs near line 1365, where a missing resolved on a KIND_LOCK_LEGACY_ENTRY record is treated as not ours. Compare it with the drop_mirror_unwired rule in vex/discover/npm.rs, then check how rollback.rs around line 1029 reports the partial revert. Run the repro's npm install then rollback sequence to confirm the half-reverted lock. Done means a revert exits 0 and rewrites the packages entry and mirror node consistently, with a mirror-node twin of the test near line 4910 passing.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
[agent] Found by the scheduled npm bug-hunt routine (ledger #302).
Summary
This is the revert-side sibling of #879. After a vendored scan of an npm lockfileVersion 2 project, an ordinary npm install (npm 7, 8, 10 or 12 on an existing v2 lock) re-saves the lock. npm never writes resolved for a file: resolution in the legacy dependencies mirror, so the mirror node keeps only version and the patched integrity. #879 taught vex and vendor --check that this is still wired, and both pass on main. The revert engine wasn't updated:
rollback,remove <purl>andvendor --revertwarnvendor_lock_entry_drifted"lock entry/dependencies/left-padwas re-resolved since vendoring (noresolvedfield); left alone" and keep the vendored state.rollbackandremoveexit 1.rollback --jsonreportsrollback_failed: "nothing was rolled back: 1 patch failed", with the event "lockfile wiring drifted; vendored state left untouched".- That claim is false: the same run did rewrite the
packages["node_modules/left-pad"]entry back to the registryresolvedandintegrity. The mirror node still carries the patched integrity. The lock is left half-reverted, and the ledger plus.socket/vendor/artifact are kept.
Impact
- Every npm 7/8 team, and every npm 9–12 team with an existing v2 lock, that vendors a patch and then runs
npm installonce can no longer roll it back or remove it with one command. That's the normal workflow: the scan's own "Next steps" tells them to runnpm install. - The failed run leaves a lock that no longer matches itself. npm 7+
npm ciinstalls the upstream bytes frompackages. npm 6 reads the mirror and failsnpm ciwith EINTEGRITY (wanted sha512-<patched> but got sha512-<registry>). After that,vendor --checkexits 1 ("vendored wiring drifted …node_modules/left-padstill resolve [email protected] outside the vendored artifact"), even though the user asked for the patch to be removed. - The remedy it prints ("undo the drift … or re-vendor, and re-run
vendor --revert") does work:scan --mode vendoredre-adds the mirrorresolved, and a revert then succeeds. But it means re-vendoring a patch you're trying to remove, and the nextnpm installbefore the revert brings the problem back.
Repro (Linux, Node 22.23.4, npm 8.19.4; a local mock patch API serving one free patch for the real npmjs [email protected])
mkdir p && cd p && git init -q
echo '{"name":"p","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
npm install # npm 8 → lockfileVersion 2
socket-patch scan --mode vendored --yes $API # exit 0; both packages entry and mirror get resolved file:.socket/vendor/...
git add -A && git commit -qm vendored
rm -rf node_modules && npm ci # patched
npm install # re-saves the lock: drops `resolved` from dependencies.left-pad (git diff: 1 deletion)
socket-patch vendor --check # exit 0 (fixed by #879)
cp package-lock.json before.json
socket-patch rollback; echo $? # exit 1: "Kept vendored state …: lockfile wiring drifted; vendored state left untouched"
diff <(jq . before.json) <(jq . package-lock.json)
# packages["node_modules/left-pad"].resolved: file:.socket/vendor/npm/<uuid>/left-pad-1.3.0.tgz → https://registry.npmjs.org/left-pad/-/left-pad-1.3.0.tgz
# packages["node_modules/left-pad"].integrity: sha512-<patched> → sha512-<registry>
# dependencies.left-pad: unchanged (version + PATCHED integrity, no resolved)
ls .socket/vendor/state.json # still there
npx npm@6 ci --cache "$(mktemp -d)" # EINTEGRITY wanted sha512-<patched> but got sha512-<registry>
socket-patch vendor --check; echo $? # 1: vendored wiring drifted
remove pkg:npm/[email protected] (exit 1, "1 matching entry was drift-kept … re-run scan --mode vendored to normalize, then remove again") and vendor --revert (exit 0, "Kept 1 drifted package") leave exactly the same half-reverted lock.
Expected vs actual
- Expected: a mirror node with no
resolvedand the recorded vendoredintegrityis treated as ours (#879 already established that this is npm's normal serialization, andvex/vendor --checkaccept it), so the revert restores both thepackagesentry and the mirror and exits 0. At the very least, when one record of a package is drift-kept, none of that package's records should be rewritten. Per CLI_CONTRACT.md, an explicit reversal (rollback,remove,vendor --revert) undoes the vendoring, and the event text says "vendored state left untouched". - Actual: exit 1 (rollback / remove) with "nothing was rolled back", while the
packagesentry was rolled back. The result is a half-reverted, self-inconsistent lock.
Matrix (Linux only: probe branches are still paused for this routine)
| npm | lock | after npm install |
rollback |
vendor --revert |
remove |
|---|---|---|---|---|---|
| 7.24.2 | v2 | mirror resolved dropped |
fail (exit 1, half-revert) | not run | not run |
| 8.19.4 | v2 | dropped | fail (3×) | fail (exit 0, half-revert) | fail (exit 1, half-revert) |
| 8.19.4 | v2 + overrides: {"left-pad": "$left-pad"} |
dropped | fail | not run | not run |
| 10.9.9 | existing v2 (--lockfile-version 2) |
dropped | fail | not run | not run |
| 12.2.1 | existing v2 | dropped | fail | not run | not run |
| 8.19.4 | v2, npm ci only (no npm install) |
resolved kept | pass | not run | not run |
| 10.9.9 / 12.2.1 | v3 (no mirror) | n/a | pass | pass | pass |
Same result on main cbbbdb9 and the v5.0.1 release, so it isn't a recent regression. It has probably been there since the npm mirror revert records were added; I didn't bisect further.
Suspect code
crates/socket-patch-core/src/vendor/npm_lock.rs:1365:let ours = match live_resolved { … None => false }. For aKIND_LOCK_LEGACY_ENTRYrecord, a missingresolvedshould count as ours when the liveintegrityequals the recorded vendored (rec.new) integrity, the same rule #879 added tovex/discover/npm.rs(drop_mirror_unwired).- The revert applies the package's other records (the
packagesentry) before the drift verdict, thencrates/socket-patch-cli/src/commands/rollback.rs:1029reports "vendored state left untouched". The per-package keep decision should either gate every record of the package or be reported as a partial revert. - The unit test at
npm_lock.rs~4910 (resolved-less entry left alone) pins the drift verdict for apackagesentry. A mirror-node twin of that test with the vendored integrity should expect a clean revert.
Related: #879 (the same npm serialization on the check/vex side, fixed), #1155 / #1187 (version-moved-off drift-keep for npm), #989 (the revert-engine tracking issue).
- Lingua principale
- Rust
- Stelle
- 9
- Fork
- 2
- Merge medio
- 18h 47m
- PR unite (30g)
- 637
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di SocketDev/socket-patch
-
agent:triaged arch-audit priority:p3 refactor
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
SocketDev/socket-patch#1860 ·
I maintainer di solito rispondono entro 1 giorno
-
agent:triaged arch-audit priority:p3 refactor
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
SocketDev/socket-patch#1838 ·
I maintainer di solito rispondono entro 1 giorno
-
arch-audit refactor
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
SocketDev/socket-patch#1987 ·
I maintainer di solito rispondono entro 1 giorno
-
agent:triaged arch-audit priority:p3 refactor
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
SocketDev/socket-patch#1983 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
agent:triaged arch-audit bug priority:p3
Difficoltà 3/5 Mezza giornata Idoneità per principianti 55/100
SocketDev/socket-patch#1982 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di SocketDev/socket-patch
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
GiganticMinecraft/seichi-portal-backend#1651 ·
I maintainer di solito rispondono entro 1 giorno
-
Android visitors are offered the Linux .deb on cap.so's homepage and download pageForse già presa @patrickballard l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
CapSoftware/Cap#3677 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno