[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
This is the vendored twin of #880. In a pnpm workspace with sharedWorkspaceLockfile: false, a member has its own pnpm-lock.yaml, so scan --mode vendored run from the member goes ahead. It wires the member's lock and writes the file:.socket/vendor/… override in two places:
packages/a/package.json pnpm.overrides, which pnpm 11+ ignores;
- a new nested
packages/a/pnpm-workspace.yaml (packages: ['.'] + overrides:), which pnpm ignores because packages/a is a project of the root workspace. pnpm reads settings only from the root pnpm-workspace.yaml.
So on pnpm 11 / 12, the override the lock records isn't in any config pnpm reads from the root:
pnpm install --frozen-lockfile from the root exits 1 with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH (pnpm also warns "The settings in packages/a/pnpm-workspace.yaml do not apply").
- A plain
pnpm install from the root exits 0. It re-resolves packages/a/pnpm-lock.yaml, drops every .socket/vendor reference, and installs the upstream left-pad. That's a silent unpatch.
The scan itself exits 0 with status: success, applied: 1.
Impact
On pnpm 11/12, this workspace layout gets no protection from vendored mode. CI (frozen) breaks. The everyday pnpm install a developer runs silently reverts the lock to the vulnerable upstream package with exit 0, and the commit that follows loses the patch.
Repro (Linux, Node 22, pnpm 12.8.1)
A local mock of the patch API grants a vendored left-pad@1.3.0 tarball (batch / by-package / view / patches/package routes, as in crates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs).
mkdir -p ws/packages/a && cd ws
echo '{"name":"root","private":true}' > package.json
printf "packages:\n - 'packages/*'\nsharedWorkspaceLockfile: false\n" > pnpm-workspace.yaml
echo '{"name":"a","version":"1.0.0","dependencies":{"left-pad":"1.3.0"}}' > packages/a/package.json
pnpm install # packages/a/pnpm-lock.yaml
(cd packages/a && socket-patch scan --mode vendored --json --yes --api-url $MOCK --org test-org --api-token fake)
# exit 0, status success, applied 1
cat packages/a/pnpm-workspace.yaml # NEW: packages: ['.'] + overrides: left-pad@1.3.0: file:.socket/vendor/…
rm -rf node_modules packages/a/node_modules
pnpm install --frozen-lockfile --store-dir "$(mktemp -d)"
# WARN The settings in packages/a/pnpm-workspace.yaml do not apply …
# ERR_PNPM_LOCKFILE_CONFIG_MISMATCH, exit 1
pnpm install --store-dir "$(mktemp -d)"
# exit 0; packages/a/pnpm-lock.yaml now has 0 `.socket/vendor` references; left-pad/index.js is the upstream file
Expected vs actual
- Expected: docs/ecosystems.md and CLI_CONTRACT.md describe vendored pnpm as wiring the override where pnpm reads it (
pnpm-workspace.yaml overrides: on pnpm >= 10.5 / 11). For a member, that's the workspace root's file. Vendored should either write the override there or refuse loudly before writing anything, as it already does with vendor_lockfile_missing for a member without its own lock.
- Actual: the override goes to two files pnpm ignores. The scan reports success, frozen installs fail, and non-frozen installs silently drop the patch.
OS × version (Linux, main 9c43dfc; each failing cell run twice)
| pnpm |
layout |
scan |
root install --frozen-lockfile |
root plain install |
| 9.15.9 |
shared-workspace-lockfile=false in .npmrc |
success |
pass (patched; pnpm 9 reads package.json pnpm.overrides) |
not run |
| 10.34.5 |
.npmrc |
success |
pass (patched) |
not run |
| 11.28.3 |
sharedWorkspaceLockfile: false in pnpm-workspace.yaml |
success |
fail ERR_PNPM_LOCKFILE_CONFIG_MISMATCH |
fail: exit 0, wiring dropped, upstream installed |
| 12.8.1 |
pnpm-workspace.yaml |
success |
fail ERR_PNPM_LOCKFILE_CONFIG_MISMATCH |
fail: exit 0, wiring dropped, upstream installed |
macOS and Windows weren't probed. The logic is path-only.
First bad release
Not a regression: release 4.0.0 does the same on pnpm 12.8.1 (frozen install ERR_PNPM_LOCKFILE_CONFIG_MISMATCH).
Suspect code
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
This is the vendored twin of #880. In a pnpm workspace with
sharedWorkspaceLockfile: false, a member has its ownpnpm-lock.yaml, soscan --mode vendoredrun from the member goes ahead. It wires the member's lock and writes thefile:.socket/vendor/…override in two places:packages/a/package.jsonpnpm.overrides, which pnpm 11+ ignores;packages/a/pnpm-workspace.yaml(packages: ['.']+overrides:), which pnpm ignores becausepackages/ais a project of the root workspace. pnpm reads settings only from the rootpnpm-workspace.yaml.So on pnpm 11 / 12, the override the lock records isn't in any config pnpm reads from the root:
pnpm install --frozen-lockfilefrom the root exits 1 withERR_PNPM_LOCKFILE_CONFIG_MISMATCH(pnpm also warns "The settings in packages/a/pnpm-workspace.yaml do not apply").pnpm installfrom the root exits 0. It re-resolvespackages/a/pnpm-lock.yaml, drops every.socket/vendorreference, and installs the upstreamleft-pad. That's a silent unpatch.The scan itself exits 0 with
status: success, applied: 1.Impact
On pnpm 11/12, this workspace layout gets no protection from vendored mode. CI (frozen) breaks. The everyday
pnpm installa developer runs silently reverts the lock to the vulnerable upstream package with exit 0, and the commit that follows loses the patch.Repro (Linux, Node 22, pnpm 12.8.1)
A local mock of the patch API grants a vendored
left-pad@1.3.0tarball (batch / by-package / view /patches/packageroutes, as incrates/socket-patch-cli/tests/e2e_redirect_pnpm_build.rs).Expected vs actual
pnpm-workspace.yamloverrides:on pnpm >= 10.5 / 11). For a member, that's the workspace root's file. Vendored should either write the override there or refuse loudly before writing anything, as it already does withvendor_lockfile_missingfor a member without its own lock.OS × version (Linux, main
9c43dfc; each failing cell run twice)install --frozen-lockfileinstallshared-workspace-lockfile=falsein.npmrcpackage.jsonpnpm.overrides).npmrcsharedWorkspaceLockfile: falseinpnpm-workspace.yamlERR_PNPM_LOCKFILE_CONFIG_MISMATCHpnpm-workspace.yamlERR_PNPM_LOCKFILE_CONFIG_MISMATCHmacOS and Windows weren't probed. The logic is path-only.
First bad release
Not a regression: release 4.0.0 does the same on pnpm 12.8.1 (frozen install
ERR_PNPM_LOCKFILE_CONFIG_MISMATCH).Suspect code
crates/socket-patch-core/src/vendor/pnpm_lock.rs:568: the project'sws_textis read only from<cwd>/pnpm-workspace.yaml. A missing file then takes the create path (a root-onlypackages: ['.']scaffold in the member), and nothing looks for the ancestor workspace root that governs pnpm settings.crates/socket-patch-core/src/hosted/governing_root.rs:54(the Hosted scan/get run from a pnpm workspace member (or withlockfile-dir=..) ignores the parent pnpm-lock.yaml and reports success while pinning nothing #590 member check, shared in spirit withvendor_lockfile_missing) lets a member with its own lock through, which is right for the lock but not for where config goes.trustLockfileplacement in Hosted scan from a pnpm 11/12 workspace member with its own lock writes trustLockfile into a nested member pnpm-workspace.yaml that pnpm ignores, so the root install fails with ERR_PNPM_TARBALL_URL_MISMATCH #880, but the vendored wiring is a separate code path, so it's filed separately. The pnpm 11+ part of the duplicatepackage.jsonpnpm.overridescopy is the known noise in the ledger.