fix(gem): bundler vendored+hosted audit — 13 confirmed bugs fixed, tests hardened - #175
Conversation
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using high effort and found 2 potential issues.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: CRLF re-run nests Gemfile sources
- Changed regex pattern from
do\ntodo\r?\nto match both Unix and Windows line endings, preventing the idempotency guard from failing on CRLF files.
- Changed regex pattern from
Or push these changes by commenting:
@cursor push 8058d388a7
Preview (8058d388a7)
diff --git a/crates/socket-patch-core/src/patch/redirect/mod.rs b/crates/socket-patch-core/src/patch/redirect/mod.rs
--- a/crates/socket-patch-core/src/patch/redirect/mod.rs
+++ b/crates/socket-patch-core/src/patch/redirect/mod.rs
@@ -1786,7 +1786,7 @@
let block_re = Regex::new(
&(String::from(r#"(?m)^source "("#)
+ &url_pat
- + r#")" do\n gem ["']"#
+ + r#")" do\r?\n gem ["']"#
+ ®ex::escape(&dep.name)
+ r#"["']"#),
)You can send follow-ups to the cloud agent here.
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 10c0079. Configure here.
…ll scan arms Addresses both Bugbot findings on #175: - The grant-agnostic Gemfile idempotency guard required LF (`do\n`), so a core.autocrlf checkout of a previously-redirected Gemfile was not recognized and the indented gem line inside the block got wrapped in a second, nested source block on re-run. The recognizer now accepts `do\r?\n`; pinned by gemfile_rerun_on_crlf_checkout_never_nests (verified red without the fix). - The dry-run VEX skip only covered the vendor JSON arm; the interactive `scan --vendor --dry-run --vex` path (embed_vex_human) and the JSON `scan --apply --dry-run --vex` path (embed_vex_into_json at the apply fall-through) still generated the document — exiting 1 on a not-yet-vendored project or writing the attestation during --dry-run. The guard now lives at the top of both embed helpers, covering every scan arm; pinned by scan_vendor_dry_run_with_vex_interactive_* and scan_apply_json_dry_run_with_vex_* (both verified red without it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both Bugbot findings addressed in d063cb1:
Note: took the guard-relocation fix rather than the prepared one-line autofix so the interactive and JSON-apply arms are covered too. 🤖 Generated with Claude Code |
…sts hardened ULTRACODE review + full test matrix over the gem/bundler ecosystem (vendored and hosted modes, every configuration). 24 findings survived adversarial verification; the 13 well-scoped ones are fixed here, each pinned by a test that fails without its fix. Hosted redirect (patch/redirect/mod.rs, gem section): - splice the Gemfile edit by regex byte range: a commented-out duplicate of the gem line no longer gets rewritten instead of the live line - grant-agnostic idempotency guard: re-running scan --mode hosted with a rotated grant token refreshes the source URL in place instead of nesting a second source block (new edit kind redirect_gemfile_source_url) - fail closed on gem-level git:/github:/path:/source: options (they override the enclosing source block, making the redirect an attested no-op); warn redirect_gem_source_option and skip the dep - fail closed on platform-suffixed CHECKSUMS siblings (redirect_gem_platform_unsupported) instead of inserting a duplicate bare-coordinate pin - recognize paren/tab/multi-space gem declarations; gate the append-branch on the gem being genuinely undeclared (no more duplicate declarations bundler rejects) - never pin the lock CHECKSUMS when the Gemfile source redirect did not land (mixed state guaranteed a checksum failure) - warn that a redirected pair breaks frozen/deployment installs - record the upstream sha256 line as original on the CHECKSUMS edit so a future revert can restore it (golden fixture updated) Vendored backend (vendor/gem.rs): - insert new PATH sections at bundler's sorted position (identifier order, verified against real bundler 4.0.15 bundle lock) — two or more vendored gems no longer churn the committed lock - fail closed on platform-suffixed GEM-specs siblings on no-CHECKSUMS locks (mirrors the existing CHECKSUMS guard) - re-vendor on a patch UPDATE (new uuid, same purl): recognize our own path: wiring and rewire in place instead of refusing with gemfile_declaration_not_editable — the documented automatic re-vendor contract now actually works for gem Auto-fetch (vendor/registry_fetch.rs): - stage fetched gems into the canonical <name>-<version> leaf instead of a dir literally named "gem", which vendor_gem refused as platform_gem_unsupported — lockfile auto-fetch for gems was dead Crawler (crawlers/ruby_crawler.rs): - parse_dir_name_version prefers the last dotted-version boundary, so http-2-1.0.1 parses as (http-2, 1.0.1) instead of the ghost (http, 2) - vendor/bundle discovery enumerates engine dirs (jruby, truffleruby) instead of hardcoding ruby/ Scan/get plumbing: - run_nested_apply now threads --ecosystems: scan --ecosystems gem --sync no longer applies (or mutates) other ecosystems' patches - scan --vendor --dry-run --vex no longer writes the VEX file nor exits 1 on not-yet-vendored state Test hardening: - e2e_gem lifecycle harness: BUNDLE_PATH replaces bundle install --path (removed in bundler 3+; all 3 lifecycle tests green under 4.0.15) - e2e_hosted_production gem leg now asserts the CHECKSUMS digest CHANGED after redirect (client-verifiable today) and, in the success arm, verifies installed content against the published afterHashes — an inert gem patch can no longer stay green (the npm minimist blindspot) - docker_e2e_gem serves the true git-blob beforeHash so the chain exercises the default non-forced apply path, not just --force - setup_matrix_gem module doc: the with-setup Docker cases ARE still a baseline gap (bootstrap deadlock: plugin registration evaluates plugins.rb before any gems land; exit-semantics twin), doc corrected Verified: core 2460/0, cli lib 350/0, clippy+fmt clean; e2e_gem 11/11 (incl. live lifecycle under bundler 4.0.15), e2e_vendor_gem_build 6/6 (incl. real-bundler capstone), docker_e2e_gem 2/2, docker_e2e_vendor_gem 1/1, hosted production gem leg green (redirect verified; install still blocked by the known depscan#23630 compact-index 404 — server-side). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ll scan arms Addresses both Bugbot findings on #175: - The grant-agnostic Gemfile idempotency guard required LF (`do\n`), so a core.autocrlf checkout of a previously-redirected Gemfile was not recognized and the indented gem line inside the block got wrapped in a second, nested source block on re-run. The recognizer now accepts `do\r?\n`; pinned by gemfile_rerun_on_crlf_checkout_never_nests (verified red without the fix). - The dry-run VEX skip only covered the vendor JSON arm; the interactive `scan --vendor --dry-run --vex` path (embed_vex_human) and the JSON `scan --apply --dry-run --vex` path (embed_vex_into_json at the apply fall-through) still generated the document — exiting 1 on a not-yet-vendored project or writing the attestation during --dry-run. The guard now lives at the top of both embed helpers, covering every scan arm; pinned by scan_vendor_dry_run_with_vex_interactive_* and scan_apply_json_dry_run_with_vex_* (both verified red without it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
d063cb1 to
99f9cd0
Compare
|
Rebased Conflicts resolved (1):
Auto-merges verified semantically:
Verification (all green):
🤖 Generated with Claude Code |
1640912
into
main


Full ULTRACODE review + test matrix over the gem/bundler ecosystem (vendored and hosted modes, all configurations). 24 findings survived adversarial verification; the 13 well-scoped ones are fixed here, each pinned by a test that fails without its fix. Four follow-up PRs (plugin bootstrap, apply/rollback policy, vendor integrity, coverage hardening) will stack on this branch.
Hosted redirect (
patch/redirect/mod.rs, gem section)redirect_gemfile_source_url).git:/github:/path:/source:options survive into the Socket source block and override it in bundler's DSL — the redirect did nothing yet was confirmed and VEX-attested. Now fails closed withredirect_gem_source_option.redirect_gem_platform_unsupported) instead of inserting a duplicate bare-coordinate pin (P2).BUNDLE_FROZEN/--deploymentinstalls (pnpm-warning parity) (P2).originalso a future revert can restore it (golden fixture updated). Note: the depscan TS twin (registry-rewrite gem rewriter) may need the sameoriginalfield for cross-language contract parity (P2).Vendored backend (
vendor/gem.rs,registry_fetch.rs)bundle lockunder 4.0.15.gemfile_declaration_not_editable— the backend rejected its own wiring, breaking the documented automatic re-vendor. Now rewires in place (direct + transitive shapes).gem, which the platform guard refused asplatform_gem_unsupported. Now stages<name>-<version>(with a defense-in-depth coordinate re-check before any I/O).Crawler + plumbing
parse_dir_name_versionprefers the last dotted-version boundary:http-2-1.0.1parses ashttp-2@1.0.1, not the ghosthttp@2— real gems (http-2, http-2-next) were never discovered (P1). Known residual: ancient dotted platform suffixes (e.g.sparc-solaris-2.8) mis-split; modern platforms are unaffected.vendor/bundlediscovery enumerates engine dirs (jruby, truffleruby) instead of hardcodingruby/(P2).run_nested_applynow threads--ecosystems:scan --ecosystems gem --syncno longer applies (or mutates) other ecosystems' patches (P2).scan --vendor --dry-run --vexno longer writes the VEX file nor exits 1 on not-yet-vendored state (P2).Test hardening
e2e_gemlifecycle harness:BUNDLE_PATHreplacesbundle install --path(removed in bundler 3+); all 3 lifecycle tests green under host bundler 4.0.15.docker_e2e_gemserves the true git-blob beforeHash so the container chain exercises the default non-forced apply path, not just--force.setup_matrix_gemmodule doc corrected: the with-setup Docker cases ARE still a baseline gap (bootstrap deadlock; fix coming in the follow-up plugin PR).Verification
e2e_gem11/11 (incl. live lifecycle under bundler 4.0.15),e2e_vendor_gem_build6/6 (incl. real-bundler capstone),docker_e2e_gem2/2,docker_e2e_vendor_gem1/1 (fresh image)not_built) — server-side, re-verified 2026-08-13🤖 Generated with Claude Code
Note
Medium Risk
Changes touch gem redirect, vendored lock surgery, and nested apply scoping—high user impact for bundler workflows but bounded to gem ecosystem with extensive new regression tests; hosted redirect fail-closed paths may skip redirects users previously thought applied.
Overview
This PR tightens gem/bundler behavior across hosted registry redirects, vendored lock editing, discovery, and CLI plumbing, with tests that fail without each fix.
Hosted Gemfile/Gemfile.lock redirect now splices Gemfile edits by byte range (avoids corrupting commented duplicates), recognizes rotated grant tokens without nesting source blocks, and fails closed on
git:/path:/source:options, platform CHECKSUMS siblings, and lock pins without a matching Gemfile redirect. CHECKSUMS edits record upstreamsha256asoriginalfor revert; a new warning flags frozen/deployment breakage after redirect.Vendored gem backend inserts PATH sections in bundler’s sorted order, rewires in place on patch uuid updates (direct and transitive), and stages lockfile auto-fetch as
{name}-{version}instead of a genericgemdir. Platform-suffixed GEM specs fail closed on older locks without CHECKSUMS.Ruby crawler prefers the last dotted version boundary for names like
http-2, and discoversvendor/bundle/jruby/trufflerubyengine layouts—not onlyruby/.CLI: nested apply after download/scan forwards
--ecosystemsso scoped sync does not apply other ecosystems;scan --vendor --dry-run --vexskips VEX generation and returns a JSONskippedmarker instead of writing files or failing on not-yet-vendored projects.Tests:
BUNDLE_PATHfor bundler 4+, hosted gem leg asserts CHECKSUMS change and on-disk afterHashes; docker gem e2e uses realbeforeHashwithout--force; in-process tests cover ecosystem scoping and vendor dry-run VEX.Reviewed by Cursor Bugbot for commit 10c0079. Configure here.