Skip to content

Fix vendored npm VEX beside a file: dir copy (#1511) - #1513

Merged
Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-npm-vendored-file-dir-copy
Oct 14, 2026
Merged

Mikola Lysenko (mikolalysenko) merged 3 commits into
mainfrom
agent/fix-npm-vendored-file-dir-copy

Conversation

@mikolalysenko

@mikolalysenko Mikola Lysenko (mikolalysenko) commented Oct 14, 2026 •

Copy link
Copy Markdown
Collaborator

LLM Description written by Claude Code:claude-opus-5-5

Fixes #1511

Summary

In an npm workspace under install-strategy=nested, member a uses registry left-pad@1.3.0 and member b depends on a file: directory that holds the same release. A vendored scan --vex and a standalone vex both said not_affected, and vendor --check passed. But b's copy is a symlink to that directory, which no rewrite reaches, so it stays unpatched.

After this PR:

  • VEX: the vendored run's in-run --vex and a standalone vex attest nothing. They warn patched_ref_unattributable and name packages/b/node_modules/left-pad, as they already did for the file: tarball and URL shapes. Hosted mode has refused this shape since Fix npm file: copy attested by in-run VEX (#1481) #1482.
  • vendor --check: fails with copy unpatched: … naming that lock entry. Before this PR it passed. Without the second commit it would have failed with the false "wiring missing … re-run socket-patch vendor".

Root cause

vex::discover::npm::drop_non_registry_installs withholds a Socket-wired ref when a non-registry copy of the same name@version installs beside it. It read the copy's identity only from the entry's version. npm records a file: directory dependency as a versionless link entry ("resolved": "lpdir", "link": true), and only the directory's own entry carries the version. So the loop skipped it and the ref stayed attested. #1482 added that link → source lookup (npm_link_source_identity) to the hosted rewriter only. Discovery, which vendored VEX and vendor --check read, never got it.

Changes

  1. npm_link_source_identity moves from patch/redirect/mod.rs to vendor::npm_origin, next to npm_non_registry_entries. It now takes the link entry rather than a JSON pointer. The hosted rewriter and discovery both call it.
  2. Discovery resolves a versionless link entry that npm installs from a file: spec through that lookup. As in the hosted rewriter, only entries in npm_non_registry_entries qualify, so a plain workspace-member link is still first-party source.
  3. New Discovery::vendored_shadow: when a vendored claim died because its ref was moved to shadowed (an unpatched copy beside it), vendor --check quotes the diagnostic that names the copy. It no longer says nothing wires the artifact or tells the user to re-vendor. This also corrects the message for the existing bundled / git / url / file: tarball shapes. CLI_CONTRACT.md's vendor --check paragraph documents the new copy unpatched reason.

Tests (red → green)

Issue Test Without fix With fix
#1511 discovery (hosted and vendored wiring; named and folder-named source; controls for another version and a workspace-member namesake) socket-patch-core vex::discover::npm::tests::a_file_directory_link_copy_of_the_same_release_is_not_attested fails (1 ref attested) passes
#1511 vendored vendor --vex, standalone vex, vendor --check socket-patch-cli --test in_process_vendor vendor_npm_file_directory_copy_is_not_attested fails: exit 0, "vex":{"statements":1} (the issue's exact symptom) passes

Not changed (review notes)

Local verification (head 7b7f58c)

  • cargo fmt --all -- --check: clean. cargo clippy --workspace --all-features -- -D warnings: clean.
  • cargo test --workspace --all-features (run in chunks because of the sandbox's disk allowance): every suite passes except 10 write-failure tests that rely on read-only permissions (relax_loop_must_not_traverse_symlinked_root, an_unremovable_hidden_lock_keeps_every_store_entry, wire_write_failure_*, wire_failure_rolls_back_*, *_state_write_failure_*, partial_lockfile_write_failure_*, redirect_json_mode_write_failures_*, scan_redirect_vlt_heal_invalidation_failure_warns). The sandbox runs as root, which bypasses those permissions. The tests are unrelated to this diff, and CI runs them as a non-root user.
  • e2e_vendor_npm_build and e2e_redirect_npm_build with --include-ignored on real npm 10.9.4: 36 and 43 passed.
  • /code-review high ran on the diff. Fixed from it: the vendor --check false "wiring missing" diagnosis, the link lookup gated to file: entries, the vacuous in-run VEX assertion, the missing workspace-member control, and the split name derivation. Not fixed, with reasons under "Not changed".
  • No wrapper changes needed: npm/, pypi/ and gem/ only dispatch to the binary.

🤖 Generated with Claude Code


Generated by Claude Code

Assisted-by: Claude Code:claude-opus-5-5
Vendored `scan --vex`, a standalone `vex` and `vendor --check` read the
npm lock through discovery, which skipped a `file:` directory
dependency: npm records it as a link entry with no version, so
discovery never saw that it holds the patched release. VEX then said
`not_affected` while that workspace member loaded the unpatched
directory.

Discovery now resolves such a link to its source directory's entry,
as the hosted rewriter does since #1482, and withholds the reference
with `patched_ref_unattributable`. The lookup moves to
vendor::npm_origin so both readers share it.

Fixes #1511

Assisted-by: Claude Code:claude-opus-5-5
With the #1511 fix, `vendor --check` on a project whose vendored npm
package also installs from a `file:` directory failed with "wiring
missing: no lockfile or config references ... re-run socket-patch
vendor". The lock does reference the artifact, and re-vendoring cannot
reach that copy, so the advice looped. The same held for a bundled,
git, url or `file:` tarball copy.

The check now reports `copy unpatched:` with the lock entry that
installs the unpatched copy, and says to depend on the registry
release there instead.

Discovery's link lookup is also limited to entries npm installs from a
`file:` spec, as in the hosted rewriter, and the regression tests gain
a workspace-member control and assert the in-run VEX warning.

Refs #1511

Assisted-by: Claude Code:claude-opus-5-5
@mikolalysenko

Copy link
Copy Markdown
Collaborator Author

BugBot review


Generated by Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 7b7f58c. Configure here.

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

Labels

None yet

Projects

None yet

3 participants