Repository navigation
Vendored pnpm 9+ misses the aliased-importer refusal for a scoped npm alias (sl: npm:@scope/pkg@x), so it leaves a dangling quoted importer reference: scan says success, frozen installs fail, and VEX attests not_affected #957
Description
Activity
- addedbugSomething isn't workingSomething isn't workingbughuntFound by a scheduled package-manager bug-hunt agentFound by a scheduled package-manager bug-hunt agentpm:pnpmpnpmpnpm
on Oct 6, 2026 - added a commit that references this issue
on Oct 6, 2026 mikolalysenko commented
on Oct 6, 2026 CollaboratorAuthorMore actions[agent] Triaged as priority:p1 (pnpm). Confirmed on
main(9c43dfc): the "aliased importer version" refusals atcrates/socket-patch-core/src/vendor/pnpm_lock.rs:1589and:1644still compare the raw (possibly quoted) YAML value against the unquoted registry key. Not a duplicate; no open PR covers it.
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions[agent] New information from the pnpm bug-hunt routine (ledger #303): the same quoting gap also affects the snapshot path, not just the importer path. A fix for the importer checks alone won't cover it.
Shape: a dependency (here a local
file:tarballhost@1.0.0) declares"sl": "npm:@isaacs/string-locale-compare@1.1.0". pnpm 9+ writes the reference in the dependent's snapshot as a quoted value:snapshots: host@file:host-1.0.0.tgz: dependencies: sl: '@isaacs/string-locale-compare@1.1.0'
PnpmLockIndexstores the raw value, quotes included, infirst_snapshot_rest(crates/socket-patch-core/src/vendor/pnpm_lock.rs:2760). The "aliased snapshot reference" refusal then compares it against the unquotedreg_key(:1576, and:1618in the non-indexed path), so it never fires.Result on main
9c43dfc:socket-patch vendorexits 0 withsuccessand rewrites thepackages:/snapshots:keys to@isaacs/string-locale-compare@file:.socket/vendor/…, but it leavessl: '@isaacs/string-locale-compare@1.1.0'dangling. A freshpnpm install --frozen-lockfilethen fails withERR_PNPM_LOCKFILE_MISSING_DEPENDENCY: Broken lockfile: no entry for '@isaacs/string-locale-compare@1.1.0', and standalonevexattestsnot_affected.pnpm scoped alias in a transitive snapshot unscoped alias lp: npm:left-pad@1.3.0(control)8.15.9 (lock 6.0) pass (refused: aliased dependency reference, lock untouched)— 9.15.9 fail (2/2 runs) pass (refused: aliased snapshot reference, lock untouched)12.8.1 fail pass (refused) Repro (Linux, Node 22):
mkdir host && cd host echo '{"name":"host","version":"1.0.0","dependencies":{"sl":"npm:@isaacs/string-locale-compare@1.1.0"}}' > package.json echo 'module.exports=require("sl")' > index.js && npm pack --pack-destination .. && cd .. mkdir proj && cd proj && cp ../host-1.0.0.tgz . echo '{"name":"proj","version":"0.0.0","private":true,"dependencies":{"host":"file:./host-1.0.0.tgz"}}' > package.json pnpm install # stage .socket/manifest.json + blobs for pkg:npm/@isaacs/string-locale-compare@1.1.0, then: SOCKET_VENDOR_URL=<mock> socket-patch vendor --json # exit 0, success grep -n "sl:" pnpm-lock.yaml # sl: '@isaacs/string-locale-compare@1.1.0' (dangling) pnpm install --frozen-lockfile # ERR_PNPM_LOCKFILE_MISSING_DEPENDENCY socket-patch vex --output vex.json # not_affected
Suggested scope for the fix: unquote the value once when indexing (
first_snapshot_rest,first_snapshot_rest_paren,first_importer_ver*) and in both non-indexed loops, so the importer and snapshot checks share one normalisation.Not a regression: release 4.0.0 has the same check.
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue (shared root cause: pnpm vendored alias refusals compare the raw, possibly quoted YAML value against the unquoted registry key). Branch: agent/fix-pnpm-quoted-alias-refusal. Claim-ID: 2026-10-07T05:20:43Z-c792ae
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions- added 2 commits that reference this issue
on Oct 7, 2026
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
Vendored mode on a pnpm 9.0 lock is supposed to refuse a package that an
npm:alias references (vendor_lock_entry_unsupported: "references … through an aliased importer version … that the pair surgery cannot rewrite — vendoring would leave a dangling reference pnpm rejects"). For an unscoped alias (lp: npm:left-pad@1.3.0) it does. For a scoped alias it doesn't. pnpm writes the importer's version quoted:The guard compares the raw (still quoted) value against the unquoted registry key, so it never matches. The vendor surgery then renames the
packages:/snapshots:entries to'@isaacs/string-locale-compare@file:.socket/vendor/…'and leaves the importer'sversion: '@isaacs/string-locale-compare@1.1.0'pointing at an entry that no longer exists. That is exactly the dangling reference the refusal exists to prevent.Impact
scan --mode vendoredexits 0 withstatus: successandvendorreportsapplied.pnpm install --frozen-lockfilethen fails withERR_PNPM_LOCKFILE_MISSING_DEPENDENCY("Broken lockfile: no entry for '@isaacs/string-locale-compare@1.1.0' in pnpm-lock.yaml … probably caused by a badly resolved merge conflict").vexattestsnot_affectedforpkg:npm/%40isaacs/string-locale-compare@1.1.0, although nothing patched can be installed from this lock.vendor --revertrestores the lock byte for byte (pass).Repro
The patch API is mocked locally (batch, by-package, view, package grant and the tarball route); the patch prepends a marker to
index.js.Control:
{"lp": "npm:left-pad@1.3.0"}in the same project is refused correctly withvendor_lock_entry_unsupported("an aliased importer version (left-pad@1.3.0)"), and the run reportspartial_failure.Expected vs actual
aliased root dependency (/@isaacs/string-locale-compare@1.1.0)). CLI_CONTRACT and docs/ecosystems.md describe lock shapes vendoring can't handle as loud refusals that write nothing, not as a success that breaks frozen installs.Matrix (Linux, Node 22, main
9c43dfc)npm:@isaacs/string-locale-compare@1.1.0npm:left-pad@1.3.0(control)aliased root dependency)pnpm 10 and 11 use the same 9.0 lock grammar and weren't run separately. macOS and Windows weren't probed (this is string matching, independent of OS).
First bad version
Not a regression: release 4.0.0 behaves the same on pnpm 12.8.1 (success, broken frozen install,
not_affected).Suspect code
crates/socket-patch-core/src/vendor/pnpm_lock.rs:1588(index path) and:1643(fallback scan):vis the raw YAML value ('@isaacs/string-locale-compare@1.1.0', quoted because it starts with@), andreg_keyis unquoted. The same comparison on snapshot body references (rest == reg_key, around:1576/:1617) probably misses a scoped alias inside a transitive dependency's snapshot in the same way. Unquoting (unquote_value) before comparing, as the catalog branch right below already does for the specifier, should cover all four sites.importer_ref_candidatesmay also need to look up by the unquoted value.