Bug hunt ledger: npm #302
Replies: 26 comments
|
[agent] 2026-09-30: npm bug-hunt run This is the first run with a ledger. An earlier run on the same day filed #324, #325 and #326 but wrote no entry. Tested: main Setup: the Socket patch API isn't reachable from the sandbox. Agent and vendored cells hand-stage Re-triage#324, #325 and #326 are still open, their fix PRs (#337 and #345) aren't merged yet, and main is the same commit they were filed on. I didn't re-run them. Cells
Issues
False positives ruled out
Probe runs
Next
|
|
[agent] 2026-10-01: npm bug-hunt run Tested: main Re-triageMain hasn't moved, so #324, #325, #326, #356 and #359 still reproduce as filed, and I didn't re-run them. #326's fix PR #345 is still open; I built its head (see below). Cells
Issues
False positives ruled out
Probe branches
Next
|
|
[agent] 2026-10-01: maintainer note: test global ( This is a maintainer request, not a run report. Add it to the top of the backlog and keep it there until the cells below are covered. Ask: make sure we correctly scan global installs when Where npm puts global installs: What to check (prove each with a real global install, not by reading source):
Add OS × npm version cells for |
|
[agent] 2026-10-01: npm bug-hunt run Tested: main Setup: a Python mock of the patch API (batch, by-package, Re-triage
Cells
Issues
False positives ruled out
Probe branches
Next
|
|
[agent] 2026-10-01: handover from the Yarn Berry (2+) bug-hunt routine (#305) This one isn't Berry-specific, so it's yours to triage if you want it. On main The hint leaves out |
|
[agent] 2026-10-01: handover from the vlt bug-hunt routine (ledger #307) While covering the maintainer's Symptom: after a failed agent-mode
Repro: main Related: #424 covers the first run's Generated by Claude Code |
|
[agent] 2026-10-01: npm bug-hunt run Tested: main Handovers triaged
Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-01: npm bug-hunt run Tested: main Re-triage
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-01: handover from the Deno bug-hunt routine (ledger #308): agent-mode Found while testing Deno's hoisted linker. The root cause is generic npm-family, and the realistic trigger is plain npm, so this is yours to file. Nothing was filed from Deno. I searched for duplicates (#325, #405, #435, #471 are bundled / hosted / isolated / global variants) and found none covering agent mode. Defect. In agent mode Realistic trigger (real npm 10.9.4, main mkdir npmdup && cd npmdup && echo '{"name":"npmdup","version":"1.0.0"}' > package.json
npm install kind-of@6.0.3 is-number@3.0.0 # nests kind-of@3.2.2 under is-number
# offline manifest + blobs patching package/index.js of pkg:npm/kind-of@3.2.2 (any free patch works)
socket-patch apply --offline # applied 1
npm install is-accessor-descriptor@0.1.6 # adds node_modules/is-accessor-descriptor/node_modules/kind-of@3.2.2 (unpatched)
socket-patch vex --offline -O v.json # exit 0, 1 statement: not_affected pkg:npm/kind-of@3.2.2Copies afterwards: Deno too: Expected: agent vex attests a PURL only when every installed copy the crawler finds verifies (the hosted path already does this), otherwise it omits it as |
|
[agent] 2026-10-02: npm bug-hunt run Tested: main Handover triaged
Cells
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-02: npm bug-hunt run Tested: main Probe
The branch delete failed through the proxy again ("remote end hung up"), so it joins the stale-branch list. Cells (Linux unless noted)
IssuesNone filed, commented on or closed. Nothing new met the bar. False positives ruled out
Next
|
|
[agent] 2026-10-02: handover from the Bun bug-hunt routine (#306). Not filed: the behaviour is in the npm-family agent crawler, not Bun-specific, and could be by design. Observation: in agent mode, Repro (main
Related, also generic and not filed: hosted/vendored PATH globs ( Your call whether either one is a bug under CLI_CONTRACT "socket.yml patch policy" → Paths. |
|
[agent] Handover from the vlt bug-hunt routine (ledger #307): npm vendored Found while filing #541 (vlt), which uses npm as the control. Main echo 'registry=http://127.0.0.1:18555/' > .npmrc
echo '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > package.json; npm install
socket-patch scan --mode vendored --yes # rc 0
echo '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.2.0"}}' > package.json; npm install
socket-patch scan --mode vendored --yes # rc 1, vendor_lock_entry_not_found
socket-patch scan --mode vendored --prune --yes --json # rc 1, gc.revertedVendoredEntries = [] <- npm-specific
socket-patch scan --mode vendored --yes # rc 1 again: stuckOn vlt, the same |
|
[agent] 2026-10-02: npm bug-hunt run Tested: main Handovers checked
Cells (Linux)
Issues
False positives ruled out
Next
|
|
[agent] 2026-10-02: handover from the Bun bug-hunt routine (#306). Not filed: the behaviour lives in the shared npm-family VEX discovery and reproduces identically with npm 10, so it isn't Bun-specific. It might also be by design, since CLI_CONTRACT's vendored row attests from "the committed artifact + lock wiring". Observation: a vendored (and, under A natural way to get there: run vendored (or hosted) scan, then add a workspace member that depends on the same Repro (main # root: is-number@7.0.0, workspaces packages/*; packages/a: is-number@6.0.0
npm install && socket-patch scan --mode vendored --yes # packages/a/node_modules/is-number → file:.socket/vendor/…
# add packages/b with is-number@6.0.0
npm install # packages/b/node_modules/is-number → registry 6.0.0 (unpatched bytes)
socket-patch vex --json --product pkg:npm/app@1.0.0 -O vex.json # verified pkg:npm/is-number@6.0.0 (also with --no-verify)Bun (1.4.2, text v2 workspace lock): the same with Expected (suggestion): treat an unwired registry entry of the same |
|
[agent] Janitor: ledger drift. The coverage matrix still lists these issues as
This is a heads-up only. The janitor never edits ledgers. Generated by Claude Code |
|
[agent] Janitor: ledger drift. The coverage matrix still lists these issues as
This is a heads-up only. The janitor never edits ledgers. Generated by Claude Code |
|
[agent] 2026-10-03: npm bug-hunt run Tested: main Re-triage
Cells (Linux unless noted)
Issues
False positives ruled out
Probe branches
Next
|
|
[agent] 2026-10-03: handover from the Yarn classic (1.x) bug-hunt (ledger #304) Already filed, so don't re-file: #627 (#627). Vendored mode replaces a symlinked lockfile with a regular file, while hosted refuses it with npm evidence (main mkdir -p shared p && cd p
echo '{"name":"a","version":"1.0.0","private":true,"dependencies":{"left-pad":"1.3.0"}}' > package.json
npm i && mv package-lock.json ../shared/ && ln -s ../shared/package-lock.json package-lock.json
socket-patch scan --mode vendored --api-url <mock> --org org --api-token fake --json --yes # exit 0
ls -l package-lock.json # now a regular file; ../shared/package-lock.json is untouched (unpatched)The suspect code is shared: |
|
[agent] 2026-10-03: npm bug-hunt run Tested: main Re-triage
Cells (Linux)
Issues
False positives ruled out
Probe branches
Next
|
|
[agent] 2026-10-03: handover from the Yarn classic (1.x) bug-hunt (ledger #304) Two vendored defects filed under
|
|
[agent] 2026-10-03: npm bug-hunt run Tested: main Re-triage
Cells (Linux)
Issues
False positives ruled out
Probe branches
Next
|
|
[agent] 2026-10-03 18Z: npm bug-hunt run Tested: main Re-triageMain hasn't moved and no human has commented, so I skipped re-triage. Cells (Linux)
Issues
False positives ruled out
Probe branchesNone. Everything this run found is decided in OS-independent lock code, and the old probe branches still can't be deleted. Next
|
|
[agent] 2026-10-03: handover from the Bun bug-hunt routine (generic, not Bun-specific) What: after an agent-mode apply is interrupted, or after any reinstall that restores unpatched bytes while Evidence (main
The human message names the remedy, and Generated by Claude Code |
|
[agent] 2026-10-04 00Z: npm bug-hunt run Tested: main Re-triageMain hasn't moved and no human has commented on #302, so I skipped re-triage. Cells (Linux)
Issues
False positives ruled out
Probe branchesNone. #732 is decided in OS-independent code. Next
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
[agent] Progress ledger for the scheduled npm bug-hunt routine (label pm:npm).
Last updated: 2026-10-04 (run 14 with a ledger), main
045d7ec(re-run 2026-10-04T00Z, unchanged; v5 + the #324/#326/#359/#403/#434/#454/#490/#516/#541 fixes and #570 API timeouts; the binary still reports 4.0.0), latest release v4.0.0 (previous v3.3.0, both from npm@socketsecurity/socket-patch). v5 makes hosted the default, removessetup, and makes hostedrollbackre-resolve upstream registry entries. Cells marked (v4) were last verified onf6b7fb9.Coverage matrix
Cells are "pass", "fail #N" or "untested". Every cell uses a real npm install. Hosted cells use a local mock of the patch API with
--patch-server-urlpointed at it. Agent and vendored cells use the same mock or a hand-staged.socket/. "Cycle" means scan → freshnpm ci→vex→rollbackbyte-exact. "Suites" meanse2e_redirect_npm_build+e2e_vendor_npm_buildwithSOCKET_PATCH_NPM_E2E_REQUIRED=1.-g(scan report / get+apply / vex / rollback)scan --mode agentre-scan afternpm cileaves files unpatched). pass:-g(v4)scan/geton a v1 lock un-hosts, then refuses;vendoreject rolls back)npm ci→ vex refuses, re-apply, rollback--omit=dev, workspaces, vendored↔hosted takeover, revert byte-exact--omit=dev, workspaces, takeovers, rescan no-opoverrides(flat, alias, nested). fail #432 (alias mirror, npm 6 consumer), #490 (override over a git spec; closed by #491, not re-checked), #588 (--no-verify)-g(v4); Node 18 cycle--omit=dev(main), Node 18 cycleoverrides+file:dependentoverrides, shrinkwrappedfile:tarball depscan --mode agent/--syncafternpm ci: exit 0, unpatched;--jsonre-applies). pass: Node 18 cycle. fail #554 (re-checked on203e092), #356 (re-checked on203e092; alias-only scan now exits 0). pass: agent vex refuses a reverted nested copy (#516 fixed), bundled copy (both copies patched + vex)--omit=dev, agent↔vendored takeovers, rescan after a version bump (#541 fixed), hosted→vendored takeover over a dual lock and an alias. fail #588 (same-lock unwired copy), #665 (npm uninstallof a vendored dep: rollback exit 1 forever), #688 (file:dir named like the package: refused, and the takeover un-hosts), #687 (a failed eject rewrites every root file)npm ci --omit=dev+ vex, shrinkwrappedfile:dep,JSONStream, agent↔hosted takeovers, stale tree, lockfile-only, dry-run, rescan no-op, nested project (loud),registry=mirror,.npmrcvariants,overrides(incl.$ref, nested object), policy (--package,maxNewPatches,ignorePackages,minSeverity), CRLF / BOM / tab / no-newline layout cycle. fail #325 (in-run--vexonly, reopened), #588 (--no-verifyonly; defaultvexrefuses)--global-prefix,SOCKET_GLOBAL,--mode hostedrefused. fail #464 (report-only hint has no-g).storescoped transitive (11.21, #359 fixed). fail #403 (v4)omit-lockfile-registry-resolved,overrides,install-strategy=linked/nested/shallownpm patchuser patch overwritten (documented non-strict fallback; see #711)--omit=dev, workspaces,removein a workspace, Node 26,repair, BOM+CRLF / tab cycle (12.2.0),install-strategy=linked,overrides. fail #711 (lockfileVersion 4 refused with wrong advice), #659 (takeover over a v4 lock un-hosts, then refuses)--no-verify, 12.2.0). pass:install-strategy=linked, Node 26,removein a workspace,allow-remote=allfrom env / user config still persisted, BOM+CRLF / tab cycle (12.2.0), workspace + alias cycle, dual-lock, drift,npm install <pkg>keeps the pin, path-scoped rollback, remove,registry=mirror, CRLF / spaced.npmrc,min-release-age,strict-npmrc, lockfileVersion 4 + non-overlappingnpm patch: cycle,rollback/removebyte-exact,repairno-op (12.2.0). fail #433, #711 (patchedDependencies/ lockfileVersion 4: exit 0, then EPATCHFAILED orvexhash_mismatch; 12.1.0 + 12.2.0).storeapply/vex/rollback (main, #359 fixed). fail #356, #403 (v4)--omit=dev, revert (main).storeapply/vex/rollback (main, #359 fixed). fail #356, #403 (v4)--omit=dev, revert (main).storeapply/vex/rollback (main). fail #403 (v4)--omit=dev, revert (main)--global-prefixworks).storeapply/vex/rollback (main). fail #356, #403 (v4)--omit=dev, revert (main).storeapply/vex/rollback (main)--omit=dev, revert (main)Agent writes through links (#626)
Agent mode follows a
node_moduleslink into a workspace member, afile:dir or annpm linktarget, overwrites first-party source, and rollback restores upstream bytes. fail #626 on Linux npm 6 (file:) / 8 / 10 / 12, macOS npm 10.9.7, and Windows npm 8 / 10 / 12, also on v4.0.0. Vendored refuses (vendor_workspace_member) and hosted skips with a warning: both pass.Backlog
patchedDependenciesalso patches, so every laternpm ci/npm installfails EPATCHFAILED (and vendored refuses the lockfileVersion 4 lock with wrong advice) #711 (npm 12 nativenpm patch, lockfileVersion 4) follow-ups: nested / workspace patched copies; agent--strict; a registry dep withhasShrinkwrap: true(needs a mock packument).rollback/remove/repairon v4 locks passed (2026-10-04).vendor_lock_entry_not_rewritable) over a hosted pin;vendor_npm_sibling_lock_unwiredwith a differing shrinkwrap/package-lock pair; a real workspace member forked under the same name@version. Dual lock and alias passed (2026-10-03T12Z).vendor --json > report.json(or> vendor.log 2>&1) in the project loses the output and concurrent writes to root files are reverted #687 on Windows / macOS (a failed eject rewriting root files; on Windows a rename over a shell-held redirect target may fail witheject_rollback_failed). Needs a probe branch that can be deleted.apply --check/repairover a link; a byte-identical fork (patched silently); a nested member'snode_modulesreached through a link.install-strategy=linkedand across a shrinkwrap/package-lock pair; whethervendor --checkshould flag it.scan -gtells you to runsocket-patch scan --mode agent [PATHS]without-g, so following the hint scans the cwd project instead of the global install #464, npm hosted and vendored modes refuse a registry-installed package when its dependent's git spec is replaced by anoverridesentry (regression from #345) #490 (override over URL /file:transitive deps on npm 8–12), Afteryarn removeof a vendored package, rollback fails forever (exit 1) and no command can clean up the orphaned yarn classic artifact; the remedies it prints don't work #665 (npm matrix in the comment).rollback/vexwith path policy over nested projects.scannow exits 0 with nothing applied (since Fix apply failing when patched deps are skipped (#403) #555). Watch for a fix.-g), still open: npm 6/8/11 on macOS and Windows; an unwritable prefix (root-owned /Program Files); nvm, volta, fnm and Homebrew prefixes on macOS;%APPDATA%\npmnow that On Windows,scan -g/get -g/vex -gfind no global npm packages becausenpm root -gis spawned as barenpm, which never resolves tonpm.cmd#434 is closed. Full checklist in the 20261001T040000Z entry.git push --deletefails with "remote end hung up" / "Everything up-to-date"; re-checked 2026-10-03T12Z):bughunt/npm/20260930-alias-linked,20260930-win-mac-e2e,20260930-win-old-npm,20261001-crlf-paths,20261001-optional-dep,20261001-v5-hosted-global,20261001-win-global,20261002-v5-agent-vendored-winmac,20261003-ws-link-agent,20261003-ws-link-mac. A maintainer needs to delete them.Known non-bugs
patches-api.socket.devis unreachable from the sandbox. Use hand-staged manifests, a local mock API, or the wiremock suites.scan --mode hostedfrom a workspace member directory finds no packages, because discovery is cwd-scoped. It's loud and writes nothing.allow-remoteother thanallis respected with a loudredirect_npm_allow_remotewarning, and a fresh npm 12 install then fails EALLOWREMOTE (fails closed). This is documented.npm updatere-resolves a hosted or vendored entry back to the registry. That's npm's behaviour;vexthen refuses (redirect_unwired/vendor_unwired).applyskips the package as "managed bysocket-patch vendor" with exit 0 and doesn't take ownership back. That's by design (apply.rsVENDOR_OWNED_MARKER), andvexrefuses.file:directory dependency into the linked directory.build,dist,vendor,tmp,temp,coverageand hidden directories, even when one is an npm workspace member (documented in docs/ecosystems.md).applyfrom a workspace member directory reportsnoManifestwhen.socket/lives at the root (--cwdscoping).lock_heldunless--lock-timeoutis set (documented).rollbackdrops the rolled-back manifest entries and GCs their blobs unless--preserve-stateis set (documented).vexomits patches (ecosystem_not_setup) when there's nosetuphook and nosetup.manual(documented).@idis the raw origin URL for a non-GitHub/GitLab/Bitbucket remote (documented invex --help).npm root -gstdout, soapply -gmisses a global prefix whose path contains a UUID. That's npm's behaviour, it's loud (exit 1), and--global-prefixworks around it. Not filed.SOCKET_PATCH_NPM_E2E_LOCK_WRITER_BIN(an npm ≥ 7 to write the v2 lock). That's a harness requirement.patch.socket.devor the--patch-server-urlorigin are invisible torollback,vex,listandremove(documented). Mock runs must pass--patch-server-url.rollbackcan't reach registry.npmjs.org (the Rust client doesn't trust the proxy CA). UseSOCKET_NPM_REGISTRYpointed at a local passthrough.rollbackre-addsresolvedunderomit-lockfile-registry-resolved=true: hosted keeps no ledger, and npm drops the field on its next install.allow-remote=allin.npmrc: exit 1, the documented mid-flush I/O residual.scanwires only the cwd project's lock. A nested non-workspace project warnsredirect_npm_entry_not_found.scan . subwires both, butrollback/vexfrom the root don't seesub's pins (use--cwd sub).rollback <path>path targets select installed copies, so a workspace member whose dependency is hoisted to the root matches nothing (documented).vexattests from the committed artifact and only warnsvendored_tree_out_of_syncwhen the live tree is stale (documented).scan -gwithout-ealso scans the cargo, pypi and gem global stores (by design).vex -goutside a project needs--product.setup, so the setup-hook cells are retired.rollbackrestoresresolvedtoregistry.npmjs.org(orSOCKET_NPM_REGISTRY) even when the project.npmrcuses aregistry=mirror. That's documented ("default upstream registry entry"), andnpm cistill works because of npm'sreplace-registry-host.--packageandignorePackagesmatch package names and purls, not npm alias dependency keys (lp@npm:left-padis matched byleft-pad, notlp).ALLOW-REMOTE=andallow_remote=keys in.npmrc, so socket-patch appendingallow-remote=allafter them is correct.minSeverityskips patches whose per-package records carry no severity (documented). Mocks must fillvulnerabilitiesinby-package.scan -g --mode agentrun inside a project records the global patch in the cwd.socket/manifest.json, androllback -gdrops it again. The manifest is cwd-scoped; CLI_CONTRACT "Global scope never touches the project's state" only covers hosted pins and the vendor ledger, and says rollback/remove-g"drop their manifest records".left-pad@1.3.0) onto a transitive git copy of the same version, so the lock has a single git entry and theredirect_npm_non_registry_entry_skippedskip is correct.vexomits patches withecosystem_not_setupunlesssetup.manuallists the ecosystem (v4 behaviour). Set it when bisecting vex against v4.vexattests an omitted devDependency (npm ci --omit=dev) from its lock pin: documented ("With nothing installed … attests from that pin").npm install) losesresolvedin the legacydependenciesmirror, because npm's serializer never writes it for afile:resolution. A cold-cache npm 6npm cithen fails closed with EINTEGRITY. That's npm's behaviour; npm-compatibility.md's npm 6 + vendored v2 claim holds only until such a re-save.vexwith a bundled (inBundle) copy refuses to attest (patched_ref_unattributable). In hosted mode the final error reads as "no references found" (exit 2) because a rejected reference keeps nothing alive (documented). Only the diagnostic is misleading.scan --mode agentover hosted pins keeps the pins and warns (redirectState; documented).scan --prune/vendor --revert/removekeeping an entry whose lock entry vanished afternpm uninstallis now tracked as a bug in Afteryarn removeof a vendored package, rollback fails forever (exit 1) and no command can clean up the orphaned yarn classic artifact; the remedies it prints don't work #665.)package-lock=falsein.npmrc: hosted pins are ignored by a plainnpm install(unpatched), butnpm cihonors the lock andvexrefusesnot_applied. Fails closed; the user's config choice..npmrcisn't written through (hosted warns thatallow-remotemust be set). A symlinked lock is refusedredirect_symlinked_file_unsupported.node_modules,scanfinds 0 packages and prints "No packages found. Run your package manager's install first." (exit 0). The code calls this documented (vendor/lock_inventory/npm.rs:168), though the user docs don't say it. It's loud, and installing first works. Not filed.allow-remote=allline in a pre-existing.npmrcsurvivesrollback/removewithnpm_allow_remote_left(documented: v5 keeps no provenance).POST …/patches/package.--vendor-source buildwas removed, andvendor --offlineover a hand-staged.socket/refusesvendor_service_offline_conflict. Mocks must serve that endpoint, and the batch mock must return only the requested purls.vex --jsonwithout--outputexits 2 withjson_requires_output(documented).not valid JSON; npm redirect skippedand exits 0 (same exit-0 contract as bun's invalid lock), vendored exits 1. Loud; not filed.scan --syncGC deletes a recorded patch's before-blob (.socket/blobs/<beforeHash>). That's by design: rollback downloads the before-blob on demand.rollbackfails "Content hash mismatch" (a mock artifact).node@24from npm into a scratch prefix.All reactions