Global agent mode on pnpm 12 (and 11 without the global virtual store) patches only one of the per-install copies of a package, reports success, and VEX attests not_affected
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 68/100
Línea de trabajo
Start with crates/socket-patch-core/src/crawlers/npm_crawler.rs, especially resolve_pending_targets at line 922, get_global_node_modules_paths at 1135/1148, and find_store_peer_variant_copies at 1913. Reproduce the two pnpm global installs on /dev/shm using the issue's mock API setup, then compare the crawler with the project-mode layout and the e2e patterns in crates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs. Done means every physical copy is patched and get, apply, and vex no longer report success or not_affected while a copy remains unpatched.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
pnpm 11+ isolates global installs. Each pnpm add -g … command gets its own install directory, $PNPM_HOME/global/v11/<hash>/, with its own node_modules and, on pnpm 12 (or pnpm 11 with enableGlobalVirtualStore: false), its own node_modules/.pnpm virtual store. pnpm root -g returns the parent global/v11, and socket-patch uses that one directory as the global root.
When two global install groups both contain [email protected] (a direct pnpm add -g [email protected], plus a global tool that depends on left-pad), get -g / apply -g / scan -g --mode agent patch only one of the two physical copies. The tool keeps loading the unpatched copy. The run exits 0 with status: success, applied: 1, a re-run of apply -g says already_patched, and vex -g attests not_affected.
Which copy is missed depends on directory-listing order. When the group holding the direct left-pad link is listed first, the other group's .pnpm/[email protected] store entry is never probed. On ext4 that's about half of fresh setups; on tmpfs it's deterministic (see the repro).
Impact
A globally installed tool (any CLI installed with pnpm add -g) keeps running a vulnerable dependency while socket-patch reports it patched and emits a VEX statement saying the vulnerability isn't exploitable. Nothing in the JSON or on stderr shows that a copy was skipped.
Repro (Linux, pnpm 12.8.2, Node 22)
Uses /dev/shm so the listing order is deterministic. A local mock of the patch API serves a patch for pkg:npm/[email protected] that prepends /*SOCKET_PATCHED*/ to index.js (batch / by-package / view routes with inline blob content, as in crates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs).
# a global "tool" that depends on left-pad 1.3.0
mkdir wrap && cd wrap
echo '{"name":"lp-wrapper","version":"1.0.0","bin":{"lpw":"cli.js"},"dependencies":{"left-pad":"1.3.0"}}' > package.json
printf '#!/usr/bin/env node\nconsole.log(require("fs").readFileSync(require.resolve("left-pad"),"utf8").slice(0,18))\n' > cli.js
npm pack && cd ..
base=/dev/shm/g; mkdir -p $base/home/bin
export PNPM_HOME=$base/home HOME=$base PATH=$base/home/bin:$PATH
pnpm add -g ./wrap/lp-wrapper-1.0.0.tgz # group 1: left-pad is transitive (only in its .pnpm)
pnpm add -g [email protected] # group 2: left-pad is a direct global package
pnpm root -g # $base/home/global/v11
find $base/home -path '*left-pad/index.js' # two copies, one per global/v11/<hash>/node_modules/.pnpm
mkdir w && cd w
socket-patch get pkg:npm/[email protected] -g --yes --json --api-url $MOCK --org test-org --api-token fake
# exit 0, "status": "success", "applied": 1
lpw # "/* This program is" <- the tool still loads the original bytes
socket-patch apply -g --json --offline # success, left-pad: skipped / already_patched
socket-patch vex -g --offline --product pkg:npm/[email protected] --output v.json
# exit 0, one statement: not_affected, subcomponent pkg:npm/[email protected]
If you install the two groups in the opposite order, both copies are patched.
Expected vs actual
- Expected: agent mode patches every physical copy of a
name@version.find_by_purlsdocuments this ("Returns every physical copy … patching only one leaves a live, vulnerable copy while reporting success (a silent partial)"), as do docs/ecosystems.md (npm row: "any install layout … every store copy") and the agent-mode notes ("applyandrollbackpatch every store copy of aname@version"). VEX should not attest a patch that a loaded copy doesn't carry. - Actual: one copy is patched, the other stays original, and every command reports success.
OS × version (Linux, Node 22, main 2463257)
| pnpm | global layout | copies of [email protected] | result |
|---|---|---|---|
| 10.34.5 | single global/5, shared .pnpm |
1 | pass |
| 11.0.0 / 11.28.3 (default) | per-install dirs, global virtual store (store/v11/links) |
1 shared copy | pass here (the shared-store write is #361's problem) |
11.28.3, enableGlobalVirtualStore: false |
per-install .pnpm |
2 | fail (2 of 3 ext4 runs) |
| 12.4.2 | per-install .pnpm |
2 | fail |
| 12.8.1 | per-install .pnpm |
2 | fail (1 of 3 ext4 runs; order-dependent) |
| 12.8.2 | per-install .pnpm |
2 | fail: tmpfs 4/4 in the order above; on a fixed ext4 layout, 3/3 re-runs fail |
| 12.8.2, groups installed in the opposite order | per-install .pnpm |
2 | pass |
macOS and Windows weren't probed (no probe branch this run; see the ledger). The walk order there is filesystem-dependent too, so the miss should be possible there as well.
First bad commit
This is a regression. On the same ext4 layout, release 4.0.0 patched both copies in 3/3 clean runs, and main missed one in 3/3. Bisected on the deterministic tmpfs layout:
0b4e645(b32711f^): passb32711f"Support vlt in hosted, vendored and agent modes (#269)": first bad (reproduced twice)f6b7fb9,2463257(main): fail. Draft PR #365's head80f4a71also fails.
Suspect code
crates/socket-patch-core/src/crawlers/npm_crawler.rs:922: inresolve_pending_targets,unmatched_namesis computed walk-wide. Once any importer tree has matchedleft-pad(group 2's direct link), every later pnpm store's entries for that name are filtered out, including a different install's own.pnpmthat holds a separate physical copy.npm_crawler.rs:972: since b32711f, inside a store entry only a real directory matches (is_real_package_dir_sync). Before that, group 1's.pnpm/lp-wrapper…/node_modules/left-padlink probably matched, which is how 4.0.0 reached the second copy.find_store_peer_variant_copies(npm_crawler.rs:1913) only fans out within the found copy's own virtual store, so it can't recover the other install's copy.get_global_node_modules_paths(npm_crawler.rs:1135,:1148) passes pnpm 11+'sglobal/v11as one root. Treating eachglobal/v11/<hash>/node_modulesas its own root (as for separate projects) would also avoid the cross-install filter. The analogous project-mode layout (asharedWorkspaceLockfile: falseworkspace, where each package has its own.pnpm) patches both copies correctly on pnpm 10.34.5 and 12.8.2, because those are separate roots.
- Lenguaje dominante
- Rust
- Estrellas
- 8
- Forks
- 0
- Merge medio
- 1 d 1 h
- PR fusionados (30 d)
- 211
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Sin plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de SocketDev/socket-patch
-
arch-audit refactor
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
SocketDev/socket-patch#1011 ·
Los mantenedores suelen responder en 1 día
-
agent:triaged arch-audit bug priority:p3
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
SocketDev/socket-patch#982 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Hosted yarn classic pins give no berry-migration warning, so a yarn 2+ install silently drops them (vendored warns about the same trap)Posiblemente ocupada @mikolalysenko la tomó hace 1 día. Abiertoagent:claimed agent:triaged bug bughunt pm:yarn-classic priority:p1
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
SocketDev/socket-patch#907 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
agent:triaged bug bughunt pm:bundler priority:p1
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
SocketDev/socket-patch#896 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
SocketDev/socket-patch#783 · 1 comentario ·
Los mantenedores suelen responder en 1 día
Todos los issues de SocketDev/socket-patch
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
bmander/geomsolver#118 ·
Los mantenedores suelen responder en 1 día
-
Three Windows builds are keyed on a later release than their layoutPosiblemente ocupada @ero-qt la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 2 días
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 95/100
Los mantenedores suelen responder en 1 día
-
Markdown Preview Fonts Don't Show Selected OptionPosiblemente ocupada @RadhiRasho la tomó hoy. Abiertostate:needs triage
Dificultad 2/5 1-3 horas Aptitud para principiantes 61/100
zed-industries/zed#65300 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 73/100
Los mantenedores suelen responder en 1 día