GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Fix npm overrides of git deps being refused (#490) by mikolalysenko · Pull Request #491 · SocketDev/socket-patch Conversation
|
| Issue path | Regression test | Without fix | With fix |
|---|---|---|---|
| classification | vendor::npm_origin::tests::issue_490_* (registry overrides of every supported shape, fresh and already-redirected locks; innermost wins; nested/scoped ancestors) |
4 FAILED | ok |
| classification (control) | issue_490_overrides_that_do_not_clearly_apply_keep_the_edge |
ok | ok |
| closest ancestor wins (Bugbot finding) | issue_490_the_closest_ancestor_rule_wins_whatever_the_key_order |
FAILED (old depth-only tie-break) | ok |
| equally close rules disagree (guard) | issue_490_equally_close_rules_that_disagree_keep_the_edge |
ok | ok |
* / empty overrides are no-ops (review P1) |
issue_490_wildcard_and_empty_overrides_leave_the_raw_spec |
FAILED on c657128 | ok |
| range selectors that may apply (review P1) | issue_490_range_selectors_that_may_apply_keep_the_edge |
FAILED on c657128 | ok |
| build-metadata selectors (follow-up review P1) | issue_490_exact_selectors_compare_without_build_metadata |
FAILED on fa440ae | ok |
review probes through the hosted rewriter (*, pkga@^1, [email protected]+build.1) |
patch::redirect::tests::issue_490_unclear_overrides_leave_a_url_dependency_unredirected |
— | ok |
| hosted rewriter | patch::redirect::tests::issue_490_a_git_edge_overridden_to_the_registry_is_redirected |
FAILED | ok |
| hosted engine read (memory + disk; symlinked/unreadable manifest not refused) | hosted::engine::tests::issue_490_the_root_manifest_overrides_reach_the_npm_rewriter |
n/a (new read) | ok |
| vendored | vendor::npm_lock::tests::issue_490_a_git_edge_overridden_to_the_registry_is_vendored |
FAILED (vendor_lock_entry_not_rewritable) |
ok |
| vex | vex::discover::npm::tests::issue_490_a_git_edge_overridden_to_the_registry_is_attested (hosted + vendored wiring) |
FAILED (0 refs) | ok |
| real npm e2e | e2e_redirect_npm_build::npm_redirect_overridden_git_dependency_installs_patched_bytes |
— | see below |
The existing #326 tests (npm_non_registry_entries_are_skipped_with_loud_warning, non_registry_only_instances_refuse_and_write_nothing, entries_npm_installs_from_a_non_registry_spec_are_not_attested, the golden indexed_npm_lock_rewrite_matches_golden) still pass unchanged.
Real-npm e2e. The new test reuses the hosted capstone fixture with a real npm install of the #490 project shape. Each run checks four things:
scan --mode hosted --vex reports redirected: 1, writes the lock pin and emits one in-run VEX statement;npm ci installs the patched bytes byte for byte;vex attests them;rollback restores the lock.CI's npm compatibility matrix runs it end to end on npm 9.9.4, 10.9.9, 11.20.0, 12.0.0 and 12.1.0. It is N/A, not a skip (skip() fails the pinned REQUIRED legs), in two cases:
overrides;Invalid comparator: github:… when an override covers a git spec.CI on 3ef00ef. All 11 workflows pass: CI, npm, pnpm, Bun, vlt, Poetry, PDM, Pipenv, Go, Composer and the GHA audit. Bugbot found no issues on this commit. The first attempt of Poetry 1.1.15 failed one case (direct vendored, rescanIdempotent). This PR doesn't touch Poetry code, the case passed on fa440ae and on main, and the one re-run passed.
Local runs (on 3ef00ef):
cargo clippy --workspace --all-features -- -D warnings: exit 0.npm_origin, npm_lock, VEX npm discovery, redirect).cargo test --workspace --all-features --no-fail-fast passed except 12 chmod/read-only "write failure" tests, which can't fail under uid 0 in this sandbox (the same set as other branches; see Fix berry mode takeover reverting before gates (#468, #369) #470).🤖 Generated with Claude Code
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Assisted-by: Claude Code:claude-opus-5-5
When a dependency declares another package from git, a URL or file:, and the project's package.json "overrides" pins it back to a registry version, npm installs the registry release. socket-patch still treated that copy as installed from git: hosted scan skipped it and exited 0 with the package unpatched, vendored scan failed, and vex refused to attest a correctly patched install. The check that decides which lock entries come from the registry now reads the root package.json overrides (top-level rules, rules nested under the dependent or its ancestors, "." values and $name refs). An override that clearly sends the edge to a registry spec makes the copy patchable again in hosted mode, vendored mode and vex. Anything less clear keeps the old, cautious behavior. Fixes #490 Assisted-by: Claude Code:claude-opus-5-5
871c293 to
fbaea5b
Compare
The hosted capstone suite gains the #490 project shape: a local package depends on left-pad from git and the project's overrides pin it to the registry release. The test checks that scan redirects it, that a fresh npm ci installs the patched bytes, that vex verifies them, and that rollback restores the lock. It skips on npm older than 8.3, which has no overrides. Refs #490 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
npm 9.0.0 can't install the #490 project at all: it dies with "Invalid comparator: github:..." when an override covers a git spec. The case doesn't exist on that npm, so the e2e returns instead of failing CI's pinned 9.0.0 leg. npm 9.9 and later run it fully. Refs #490 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Two override rules scoped to different ancestors at the same nesting depth tied, and the one later in key order won. npm uses the rule of the closest ancestor, so a farther registry rule could clear an edge that a closer git or file: rule keeps on that source. socket-patch could then patch or attest a copy npm still installs from the spec. Rules are now ranked by how close their ancestor is to the dependent, then by depth. Equally ranked rules that disagree count as unclear, so the copy stays reported as unpatched. Refs #490 Assisted-by: Claude Code:claude-opus-5-5
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Burn-down agent: ready for review at
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Reviewed
Validation: 17 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Two override shapes still let socket-patch treat a git or URL dependency as a registry install while npm ci kept fetching the original spec: - A "*" or empty override is a no-op in npm, which keeps the dependent's raw spec, but socket-patch read "*" as a registry range and patched the entry. - A rule nested under a range selector such as "pkga@^1" was ignored, so a broader top-level registry rule cleared the entry even though npm uses the narrower rule. A winning "*", empty or nested-only rule now leaves the raw spec in effect. A range selector that may apply, or a target selector other than the edge's own spec, makes the result unclear, so the copy stays reported as unpatched. Refs #490 Assisted-by: Claude Code:claude-opus-5-5
The previous commit used bool::then with a closure where then_some is enough, which fails the CI clippy gate (-D warnings). Refs #490 Assisted-by: Claude Code:claude-opus-5-5
|
[agent] Both findings confirmed and fixed in 5dff221. fa440ae is a follow-up clippy fix.
The two classification tests fail on c657128 and pass now. Locally: 369 related core tests pass (npm_origin, npm_lock, VEX npm discovery, redirect), and Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
The reason will be displayed to describe this comment to others. Learn more.
Stale Bugbot comment from a previous run.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Follow-up review of P1: build-qualified ancestor selectors can still bypass the source guard ( At this exact head, the three independent public-rewriter probes produced 2 passed, 1 failed, confirming that remaining case. The same fixture was independently checked with npm 10.9.4 / Node 24.21.0: fresh-cache The 20 |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
An override scoped to "[email protected]+build.1" applies to an installed pkga 1.0.0, because semver ignores build metadata. socket-patch compared the selector to the version as raw text, skipped the rule, and let a broader registry override patch a dependency that npm ci still fetches from its URL. Exact-version selectors now compare without build metadata: equal versions apply the nested rules, and different ones (prereleases included) still can't. Refs #490 Assisted-by: Claude Code:claude-opus-5-5
|
[agent] Confirmed and fixed in 3ef00ef. An exact-version enclosing selector is now compared to the ancestor's version under semver equality, with build metadata stripped on both sides.
Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
BugBot review Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was a problem 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 3ef00ef. Configure here.
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
[agent] CI note on 3ef00ef: I don't believe this failure comes from this PR:
I'll re-run the failed job once when the workflow finishes; GitHub refuses a re-run while it's still running. If it fails again, I'll treat it as real and investigate. Generated by Claude Code |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
|
Second-pass verification of I reran all three original independent public-rewriter probes at this exact head: 3 passed (wildcard no-op, uncertain range, and build-qualified ancestor). No further code change was needed. This supersedes my earlier changes-needed recommendation; this PR had already merged before this verification. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Main now reads the root package.json for the npm lock rewriter as advisory input (#490/#491). Beside a berry yarn.lock the manifest is still read strictly, since the berry pin writes it; otherwise the advisory read applies. The berry-only memory selection rule is dropped because main always fetches package.json. Assisted-by: Claude Code:claude-opus-5-5
The npm/hosted bench drifted +15% wall / +12% CPU over a week of main (2463257..9c43dfc). The new npm lock passes from #345, #491, #646 and #799 each added a walk of the 3000-entry package-lock.json, on top of two costs that scale badly with every extra walk: - Every hosted scan ran a full second lockfile discovery after the rewrite (`hosted_state_from_lockfiles`) only to classify a hosted vs vendored takeover, even with no vendored ledger to overlap, and then a THIRD one inside `classify_overlap_takeover_with` when there was one. The classifier now discovers once, and not at all when the vendored ledger has no entries (the hosted common case). - `Discovery::resolved_elsewhere` deduped with `Vec::contains` on every call, so recording a lock's registry entries was quadratic in its size. `finalize` already sorts and dedups the list and every earlier reader only asks whether some entry matches, so the per-call check is gone. Also trimmed per-entry allocations on the new passes: the npm extractor builds each entry's purl once (it was built for `mention` and again for `unwired`), `resolved_is_non_registry` no longer formats a prefix per entry, and `npm_spec_is_registry` no longer lowercases every edge spec. Instructions retired for `scan --json --dry-run` on the bench's npm fixture (median of 9, macOS): base 2463257 2.647G, branch head 2.755G (+4.1%), this commit 2.353G (-11.1% vs base, -14.6% vs head). Scan output is byte-identical to before. Regression test: `takeover_classifier_discovers_at_most_once` counts discoveries (test-only counter in `discover_wiring`); new unit tests pin the rewritten registry/tarball predicates. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
npm hosted and vendored modes refuse a registry-installed package when its dependent's git spec is replaced by anoverrides entry (regression from #345)
There was an error while loading. Please reload this page.