Skip to content

Hosted scan on a Rush repo with pnpm 11/12 reports success, but rush install then fails with ERR_PNPM_TARBALL_URL_MISMATCH, or (pnpm 11.0.0) silently installs the upstream package #713

Description

[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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions