Repository navigation
pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover #853
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 5, 2026 mikolalysenko commented
on Oct 5, 2026 CollaboratorAuthorMore actions[agent] Triage: priority:p1. pnpm (npm-family). Same shape as gem #775 (fix in open PR #776) and the yarn berry takeover preflight: vendor_records_reusing restores the hosted pin before the ecosystem's vendored refusals run. The pnpm side needs its own preflight. One trigger (workspace exact-pin override) is also #854.
Generated by Claude Code
mikolalysenko commented
on Oct 6, 2026 CollaboratorAuthorMore actions[agent] Shares root cause with #944: the hosted → vendored takeover in
crates/socket-patch-cli/src/commands/vendor.rsrestores the hosted pin (restore_upstream) before the target backend's vendored refusals run, and the pre-restore preflight only has gem and npm/berry cases (no pnpm, no PyPI). Will be fixed together.
Generated by Claude Code
mikolalysenko commented
on Oct 6, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue (with #944; shared root cause: the hosted → vendored takeover in
vendor.rscommits the upstream restore before the target vendored backend's refusals run). Branch: agent/fix-takeover-vendored-preflight. Claim-ID: 2026-10-06T20:21:01Z-4b53a1
Generated by Claude Code
mikolalysenko commented
on Oct 6, 2026 CollaboratorAuthorMore actions- added 2 commits that reference this issue
on Oct 6, 2026 mikolalysenko commented
on Oct 6, 2026 CollaboratorAuthorMore actions[agent] #963 is ready for review and fixes the data loss. When the vendored backend refuses a hosted pnpm purl (catalog, CRLF lock, workspace override, or any other refusal), the takeover's upstream restore is now rolled back inside the run's group commit, so the hosted pin stays byte-for-byte and the purl fails with the backend's own code.
vendor --dry-runalso previews that refusal now.This issue stays open (the PR says
Refs, notFixes) for one remaining piece: thescan/get --mode vendored --dry-runpreview is an offline ledger-only classification that doesn't model the takeover, so it still sayswould_vendorfor these shapes. That will be a follow-up slice after #963.
Generated by Claude Code
- added 2 commits that reference this issue
on Oct 6, 2026 2 remaining items
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions[agent] #963 is merged. A refused hosted → vendored takeover now keeps the hosted pnpm pin byte-for-byte, and
vendor --dry-runpreviews the refusal.This issue stays open for one remaining piece:
scan/get --mode vendored --dry-runstill previewwould_vendorfor the catalog, CRLF and workspace-override shapes. I've released theagent:claimedlabel so a later run can take that follow-up slice.
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions[agent] Re-verified on main
1c6c509with real pnpm (pnpm bug-hunt run 29, ledger #303). The part fixed by #963 holds:pnpm shape scan --mode vendoredhosted pin after refusal fresh --frozen-lockfile(dead registry, empty store)12.10.1 CRLF lock (2 hosted pkgs) exit 1, vendor_lockfile_crlf_unsupported×2lock + workspace file byte-identical both packages patched 9.15.9 catalog:entry forleft-pad, plainmsexit 1, left-pad→vendor_lock_entry_unsupported,msvendored (vendor_takeover_reverted_redirect)left-padkeeps its hosted pinleft-pad(hosted) andms(vendored) patched11.28.5 workspace overrides: {left-pad: 1.3.0}exit 1, left-pad→vendor_override_conflict,msvendoredleft-padkeeps its hosted pinboth patched The remaining piece still reproduces as described:
scan --mode vendored --dry-runreportswould_vendorfor both packages in the catalog and override cells (exit 0), although the real run refusesleft-pad.
Generated by Claude Code
mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions[agent] Claiming this issue as part of the pnpm open-issue sweep in draft PR #1007. Branch: agent/fix-pnpm-open-issues. Claim-ID: 2026-10-07T12:44:29Z-pnpm07
- added 6 commits that reference this issue
on Oct 7, 2026 mikolalysenko commented
on Oct 7, 2026 CollaboratorAuthorMore actions- changed the title
[-]pnpm hosted → vendored takeover un-hosts the package before pnpm's vendored refusals run, so a catalog entry, a CRLF lock or a workspace exact-pin override leaves it unpatched in both modes[/-][+]pnpm hosted-to-vendored scan/get dry-run previews success for a refused takeover[/+]on Oct 8, 2026
[agent] Found by the scheduled pnpm bug-hunt routine (ledger #303).
Summary
scan --mode vendoredover a hosted pnpm pin restores the pin to its upstream registry entry first, and only then runs the pnpm vendored backend. When the backend then refuses the package for a project-level or lock-shape reason that hosted mode handles fine, the package ends up in neither mode. The hosted pin is gone frompnpm-lock.yaml, nothing is vendored, and the next install gets the unpatched registry bytes.Three ordinary shapes trigger it, and they're all documented vendored refusals:
"left-pad": "catalog:") →vendor_lock_entry_unsupportedpnpm-lock.yaml(acore.autocrlfcheckout; hosted mode handles CRLF) →vendor_lockfile_crlf_unsupportedpnpm-workspace.yaml(overrides: { left-pad: 1.3.0 }) →vendor_override_conflictThe run does exit 1 /
partial_failure, but the restore has already been written, so the project has lost its patch.Impact
A project that is correctly hosted-patched and asks to switch to vendored loses its patch. Its committed lock now installs the vulnerable upstream release. Re-running hosted mode recovers, but nothing in the output says the package was un-hosted. The only hint is the
vendor_takeover_reverted_redirectadvisory next to the failure.Repro (Linux, Node 22, main
4646693)I used a local mock patch API that serves
left-pad@1.3.0with a marker prepended toindex.js(hosted tarball, vendor grant, view,/registrymirror;SOCKET_PATCH_SERVER_URL/SOCKET_NPM_REGISTRYpoint at it).For the CRLF variant, use a plain
"left-pad": "1.3.0"dependency and runsed -i 's/$/\r/' pnpm-lock.yamlafter the hosted scan. For the override variant, use a plain dependency plusoverrides:\n left-pad: 1.3.0inpnpm-workspace.yaml.Expected vs actual
failed <code>with the hosted wiring and active … lock byte-untouched (exit 1 /partial_failure): the package stays hosted-patched instead of being un-hosted and then refused". That's implemented for Bun (bun_preflight), yarn berry and npm package-lock (npm lockfileVersion 1: scan/get --mode vendored un-host a hosted patch and then refuse to vendor it, so the project silently goes back to unpatched (vendor eject rolls back correctly) #659).--dry-runshould preview the samefailed <code>.--dry-runpredictswould_vendor, exit 0.Matrix (scan exit / hosted pins left in the lock / fresh
pnpm install --frozen-lockfile)Every failing cell was reproduced at least twice (12.8.1 and 10.34.5 three times). I tested Linux only. The ordering is OS-independent, and the CRLF variant is the one Windows
autocrlfusers would hit.Not a regression: release 4.0.0 behaves the same (catalog variant, pnpm 12.8.1: exit 1,
vendor_lock_entry_unsupportedaftervendor_takeover_reverted_redirect, hosted pin gone).Suspect code
crates/socket-patch-cli/src/commands/vendor.rs:2517-2576: forpkg:npm/candidates the pre-restore gate runs onlyyarn_berry_vendor_preflight,npm_lock_vendor_preflightandyarn_berry_vendor_target_preflight, and then callsrestore_upstream(:2576). There is no pnpm equivalent for the pnpm backend's project and entry refusals: the CRLF lock / workspace check, the catalog and peer-suffixedvendor_lock_entry_unsupported, thevendor_override_conflictchecks incrates/socket-patch-core/src/vendor/pnpm_lock.rs:617-625(classify_pkg_override/check_lock_override/check_workspace_override), and the legacy-lockvendor_lockfile_version_unsupported.vendor_workspace_member) and Gem hosted → vendored takeover un-hosts a gem declared inside agroupblock and then refuses to vendor it (gemfile_declaration_not_editable), so the project silently goes back to unpatched #775 (gem).Backlog review — 2026-10-08
Priority: P1 → P3. The failed-takeover state loss was fixed by #963; the remaining scan/get preview mismatch is low priority. Keep the active #1007 follow-up.
The title now describes the remaining scope after the partial fixes. The original report is preserved above for historical context.