[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
In a Rush monorepo whose rush.json pins pnpm 11 or 12, socket-patch scan --mode hosted repoints common/config/rush/pnpm-lock.yaml at the hosted patch server and reports success. The next rush install from a clean clone then either fails or quietly installs the vulnerable upstream package:
- pnpm 11.28.3 / 12.8.1:
rush install fails with ERR_PNPM_TARBALL_URL_MISMATCH. pnpm needs trustLockfile to accept the hosted URL, but the engine skips the trust config for Rush locks on purpose (crates/socket-patch-core/src/hosted/engine.rs:1019, "rush runs pnpm in common/temp, which never reads the repo-root pnpm-workspace.yaml"). The only guidance users get is the generic redirect_pnpm_trust_lockfile text: "Install with pnpm install --trust-lockfile, or commit trustLockfile: true in pnpm-workspace.yaml". Neither works in a Rush repo. Rush generates common/temp/pnpm-workspace.yaml itself, and common/config/rush/pnpm-config.json has no trustLockfile key.
- pnpm 11.0.0:
rush install exits 0, but the installed left-pad is the upstream copy. rush install runs pnpm install --no-prefer-frozen-lockfile, and pnpm 11 re-resolves the hosted entry back to the registry with that flag (common/temp/pnpm-lock.yaml ends up holding the upstream integrity). The committed lock still shows the hosted pin, so nothing looks wrong. vex is honest here (not_applied).
- The obvious workaround,
pnpm_config_trust_lockfile=true rush install, works on 12.8.1. On 11.28.3 it also exits 0 and silently installs upstream, for the same --no-prefer-frozen-lockfile reason.
Plain pnpm shows the same pnpm 11 behaviour outside Rush. With trustLockfile: true, pnpm install --no-prefer-frozen-lockfile re-resolves the hosted pin to upstream on 11.28.3, while 9.15.9, 10.34.5 and 12.8.1 keep it. Rush is where it bites, because that flag is Rush's default.
Impact
On pnpm 11/12, hosted mode on a Rush repo reports success but can't be installed with Rush's normal flow. Users either hit a hard install failure with a remedy that doesn't apply, or (pnpm 11.0.0, or 11.x with the env workaround) keep shipping the vulnerable package while the lock in git claims it's patched. The pnpm 10 cells pass, so this starts at the pnpm 11 boundary.
Repro (Linux, Node 22, Rush 5.180.0)
Uses a local mock of the patch API (batch / package grant / view / hosted tarball) serving a left-pad@1.3.0 patch that prepends /* SOCKET-PATCHED */ to index.js. $API = --api-url http://127.0.0.1:8765 --org test-org --api-token tok.
V=11.28.3 # or 12.8.1 / 11.0.0
mkdir r && cd r && git init -q && rush init
# rush.json: "pnpmVersion": "$V", nodeSupportedVersionRange ">=22", one project apps/app
mkdir -p apps/app && echo '{"name":"app","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > apps/app/package.json
rush update && git add -A && git commit -qm init
socket-patch scan --mode hosted $API --json # status: success, redirected 1, rewrittenFiles [common/config/rush/pnpm-lock.yaml]
git commit -qam pin && git clone -q . ../fresh && cd ../fresh
rush install # 11.28.3 / 12.8.1: ERR_PNPM_TARBALL_URL_MISMATCH
# 11.0.0: exit 0
head -c 20 apps/app/node_modules/left-pad/index.js # 11.0.0: "/* This program is f" (upstream)
Workaround I verified on 11.x: set "usePnpmFrozenLockfileForRushInstall": true in common/config/rush/experiments.json and run pnpm_config_trust_lockfile=true rush install. That installs the patched bytes on 11.0.0 and 11.28.3. On 12.8.1 the env var alone is enough.
Expected vs actual
- Expected: docs/ecosystems.md "npm: Rush monorepos" lists Hosted ✅ ("discovers and repoints those locks in place") with no pnpm-version caveat.
crates/socket-patch-cli/CLI_CONTRACT.md:115 says the trust write "skips legacy locks and Rush repos", and that "the redirect_pnpm_trust_lockfile warning explains manual configuration when required". For Rush, the manual configuration it explains doesn't work, and nothing documents that pnpm 11 Rush installs drop the pin. So on Rush + pnpm ≥11, the CLI should either wire something Rush actually honours, or refuse (fail closed with a Rush-specific code), or at least warn with a remedy that works in Rush (the experiment plus env var above) instead of reporting a plain success.
- Actual:
status: success, exit 0, and only the generic redirect_pnpm_trust_lockfile plus redirect_rush_repo_state_stale warnings. Then rush install fails, or installs upstream.
Matrix (Linux, main 045d7ec; each cell run twice from scratch)
| pnpm (rush.json) |
scan |
clean-clone rush install |
installed bytes |
| 10.34.5 |
success |
exit 0 |
patched ✅ |
| 11.0.0 |
success |
exit 0 |
upstream ❌ |
| 11.28.3 |
success |
ERR_PNPM_TARBALL_URL_MISMATCH ❌ |
none |
11.28.3 + pnpm_config_trust_lockfile=true |
success |
exit 0 |
upstream ❌ |
| 12.0.0 |
n/a (pnpm 12.0.0 rejects Rush's --no-prefer-frozen-lockfile flag) |
|
|
| 12.8.1 |
success |
ERR_PNPM_TARBALL_URL_MISMATCH ❌ |
none |
12.8.1 + pnpm_config_trust_lockfile=true |
success |
exit 0 |
patched ✅ |
macOS / Windows: not tested (the logic is OS-independent).
Not a regression: release 4.0.0 behaves the same (11.28.3: success, then ERR_PNPM_TARBALL_URL_MISMATCH).
Suspect code
crates/socket-patch-core/src/hosted/engine.rs:1019: pnpm_trust excludes Rush locks from the trust config, with no replacement warning or refusal.
crates/socket-patch-core/src/hosted/guidance.rs:65: the redirect_pnpm_trust_lockfile remedy text is pnpm-only and not actionable under Rush.
crates/socket-patch-core/src/hosted/engine.rs:930: the Rush warning branch only covers repo-state.json.
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
In a Rush monorepo whose
rush.jsonpins pnpm 11 or 12,socket-patch scan --mode hostedrepointscommon/config/rush/pnpm-lock.yamlat the hosted patch server and reportssuccess. The nextrush installfrom a clean clone then either fails or quietly installs the vulnerable upstream package:rush installfails withERR_PNPM_TARBALL_URL_MISMATCH. pnpm needstrustLockfileto accept the hosted URL, but the engine skips the trust config for Rush locks on purpose (crates/socket-patch-core/src/hosted/engine.rs:1019, "rush runs pnpm in common/temp, which never reads the repo-root pnpm-workspace.yaml"). The only guidance users get is the genericredirect_pnpm_trust_lockfiletext: "Install withpnpm install --trust-lockfile, or committrustLockfile: truein pnpm-workspace.yaml". Neither works in a Rush repo. Rush generatescommon/temp/pnpm-workspace.yamlitself, andcommon/config/rush/pnpm-config.jsonhas notrustLockfilekey.rush installexits 0, but the installedleft-padis the upstream copy.rush installrunspnpm install --no-prefer-frozen-lockfile, and pnpm 11 re-resolves the hosted entry back to the registry with that flag (common/temp/pnpm-lock.yamlends up holding the upstream integrity). The committed lock still shows the hosted pin, so nothing looks wrong.vexis honest here (not_applied).pnpm_config_trust_lockfile=true rush install, works on 12.8.1. On 11.28.3 it also exits 0 and silently installs upstream, for the same--no-prefer-frozen-lockfilereason.Plain pnpm shows the same pnpm 11 behaviour outside Rush. With
trustLockfile: true,pnpm install --no-prefer-frozen-lockfilere-resolves the hosted pin to upstream on 11.28.3, while 9.15.9, 10.34.5 and 12.8.1 keep it. Rush is where it bites, because that flag is Rush's default.Impact
On pnpm 11/12, hosted mode on a Rush repo reports success but can't be installed with Rush's normal flow. Users either hit a hard install failure with a remedy that doesn't apply, or (pnpm 11.0.0, or 11.x with the env workaround) keep shipping the vulnerable package while the lock in git claims it's patched. The pnpm 10 cells pass, so this starts at the pnpm 11 boundary.
Repro (Linux, Node 22, Rush 5.180.0)
Uses a local mock of the patch API (batch / package grant / view / hosted tarball) serving a
left-pad@1.3.0patch that prepends/* SOCKET-PATCHED */toindex.js.$API=--api-url http://127.0.0.1:8765 --org test-org --api-token tok.Workaround I verified on 11.x: set
"usePnpmFrozenLockfileForRushInstall": trueincommon/config/rush/experiments.jsonand runpnpm_config_trust_lockfile=true rush install. That installs the patched bytes on 11.0.0 and 11.28.3. On 12.8.1 the env var alone is enough.Expected vs actual
crates/socket-patch-cli/CLI_CONTRACT.md:115says the trust write "skips legacy locks and Rush repos", and that "theredirect_pnpm_trust_lockfilewarning explains manual configuration when required". For Rush, the manual configuration it explains doesn't work, and nothing documents that pnpm 11 Rush installs drop the pin. So on Rush + pnpm ≥11, the CLI should either wire something Rush actually honours, or refuse (fail closed with a Rush-specific code), or at least warn with a remedy that works in Rush (the experiment plus env var above) instead of reporting a plain success.status: success, exit 0, and only the genericredirect_pnpm_trust_lockfileplusredirect_rush_repo_state_stalewarnings. Thenrush installfails, or installs upstream.Matrix (Linux, main
045d7ec; each cell run twice from scratch)rush installpnpm_config_trust_lockfile=true--no-prefer-frozen-lockfileflag)pnpm_config_trust_lockfile=truemacOS / Windows: not tested (the logic is OS-independent).
Not a regression: release 4.0.0 behaves the same (11.28.3: success, then
ERR_PNPM_TARBALL_URL_MISMATCH).Suspect code
crates/socket-patch-core/src/hosted/engine.rs:1019:pnpm_trustexcludes Rush locks from the trust config, with no replacement warning or refusal.crates/socket-patch-core/src/hosted/guidance.rs:65: theredirect_pnpm_trust_lockfileremedy text is pnpm-only and not actionable under Rush.crates/socket-patch-core/src/hosted/engine.rs:930: the Rush warning branch only coversrepo-state.json.