Commit fb7e518
fix(gem): crawl bundle-path roots in bundler precedence order, patch every coexisting copy, contain config-sourced roots (#222)
Post-merge audit follow-up on #218 (gem crawler flat-BUNDLE_PATH
discovery), mirroring the #216 npm multi-copy precedent (0433bcb).
1. MULTI-COPY (most severe): bundler's scoped `<engine>/<abi>/gems`
and flat `gems/` stores coexist under one root, each holding a REAL
physical copy of the same gem@version — exactly the state #218's
tests create. First-wins merging resolved the purl to ONE path, so
apply patched one store and reported success while the other
bundler loaded pristine (vulnerable) bytes. Fix mirrors #216:
`find_all_packages_for_purls` now routes the release-variant
ecosystems through an accumulating `merge_variant_copies` (reusing
`push_path`, base-PURL keyed, precedence order kept) and apply's
variant branch fans out per copy for gem — per-copy Applied events,
`summary.applied` counts each copy, a copy matching no variant
fails loudly. Rollback already carried every copy via
`merge_qualified` and its per-path grouping; the new in-process
suite pins both directions. PyPI/Maven deliberately keep the
one-representative contract (the nuget `already_patched`
double-patch regression from #216's second commit), as do all
collapsing consumers (vendor/vex/setup/get/repair-vendor).
scan --sync patches every copy too (it runs the real nested apply);
scan's inventory stays purl-level, byte-identical to npm's
crawl_all purl-dedup precedent.
2. PRECEDENCE: roots probed local-config > env > default vendor/bundle
(bundler's real precedence; the old order was inverted), so
first-representative consumers pick the copy bundler actually loads.
3. REGRESSION vs pre-#218: env/config roots no longer trip the
`gem env` fallback early-return — only the historic project-local
vendor/bundle probe keeps it. Default gems (rexml/json) live only
in the DEFAULT/system gem homes, so an env-BUNDLE_PATH project gets
those homes appended (deduped) again.
4. SECURITY: a config-sourced BUNDLE_PATH (committed .bundle/config =
attacker-authored input, and a scan/apply WRITE-target root) must
now, after ~ expansion and lexical normalization, stay contained in
the project root — otherwise the root is skipped with a
`gem_bundle_config_path_ignored` stderr warning naming the value.
Windows rooted forms (`\evil`, `C:evil`) take the strict branch.
Env-sourced BUNDLE_PATH stays trusted (user's own environment) but
is normalized for dedup. `normalize_lexically` is hoisted from the
composer crawler into utils::fs and shared.
5. `~` EXPANSION: a leading `~`/`~/...` in BUNDLE_PATH expands against
home (bundler File.expand_path), env-injectable via the _with_env
seams for hermetic tests.
6. BUNDLE_PATH__SYSTEM: `"true"` makes bundler ignore the recorded
path — the config entry now parses as unset and the fallback finds
the system gem homes.
7. TEST HERMETICITY: the six crawler_ruby_e2e tests that read ambient
BUNDLE_PATH/BUNDLE_APP_CONFIG now route through the new
`get_gem_paths_with_env` seam; a new e2e pins env-root + gem-env
fallback coexistence (finding 3).
8. CLI_CONTRACT.md: the stale "gem inspects only <cwd>/vendor/bundle"
claim replaced with the real root model, the containment policy,
and the multi-copy behavior.
TDD evidence (red -> green): dispatch-level
`find_all_packages_for_purls_carries_every_gem_store_copy`, crawler
`bundle_roots_probe_in_bundler_precedence_order`, and the new
`in_process_gem_multicopy.rs` (real binary apply/rollback over a
coexisting two-store tree) all failed on base — the flat copy stayed
byte-for-byte VULNERABLE while apply reported success — and pass now.
Live era-image proof (docker run --rm, socket-patch-test-gem-b1:gemx,
bundler 1.17.3): the baked pre-fix binary on a coexist fixture reports
status=success/applied=1 while the flat store's copy — loaded via real
GEM_HOME resolution in the container — still evaluates VULNERABLE; the
fixed binary reports applied=2 and both stores load FIXED.
Gates: touched files rustfmt-clean; cargo clippy --workspace
--all-features -D warnings clean; core --lib 2413 passed; cli --lib
430 passed; crawler_ruby_e2e 25, crawler_composer_e2e 32,
crawlers_empty_paths_e2e 13; e2e_gem hermetic 8; in-process gem+npm
multicopy suites; cli_gem_variant_mismatch_policy 6; docker_e2e_gem,
docker_e2e_vendor_gem, docker_e2e_pypi, docker_e2e_maven all green.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>1 parent a2f07e0 commit fb7e518
12 files changed
Lines changed: 2267 additions & 287 deletions
File tree
- crates
- socket-patch-cli
- src
- commands
- scan
- tests
- socket-patch-core
- src
- crawlers
- utils
- tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
278 | 278 | | |
279 | 279 | | |
280 | 280 | | |
281 | | - | |
| 281 | + | |
282 | 282 | | |
283 | 283 | | |
284 | 284 | | |
285 | 285 | | |
286 | 286 | | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
287 | 319 | | |
288 | 320 | | |
289 | 321 | | |
| |||
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
624 | 624 | | |
625 | 625 | | |
626 | 626 | | |
627 | | - | |
628 | | - | |
629 | | - | |
630 | | - | |
631 | | - | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
632 | 630 | | |
633 | 631 | | |
634 | 632 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
| 14 | + | |
| 15 | + | |
15 | 16 | | |
16 | 17 | | |
17 | 18 | | |
| |||
1451 | 1452 | | |
1452 | 1453 | | |
1453 | 1454 | | |
1454 | | - | |
| 1455 | + | |
| 1456 | + | |
| 1457 | + | |
| 1458 | + | |
| 1459 | + | |
| 1460 | + | |
| 1461 | + | |
| 1462 | + | |
| 1463 | + | |
| 1464 | + | |
| 1465 | + | |
| 1466 | + | |
| 1467 | + | |
| 1468 | + | |
| 1469 | + | |
| 1470 | + | |
| 1471 | + | |
| 1472 | + | |
| 1473 | + | |
| 1474 | + | |
| 1475 | + | |
| 1476 | + | |
| 1477 | + | |
| 1478 | + | |
| 1479 | + | |
| 1480 | + | |
| 1481 | + | |
1455 | 1482 | | |
1456 | 1483 | | |
1457 | 1484 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
153 | 153 | | |
154 | 154 | | |
155 | 155 | | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
156 | 180 | | |
157 | 181 | | |
158 | 182 | | |
| |||
382 | 406 | | |
383 | 407 | | |
384 | 408 | | |
385 | | - | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
386 | 417 | | |
387 | 418 | | |
388 | 419 | | |
| |||
535 | 566 | | |
536 | 567 | | |
537 | 568 | | |
538 | | - | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
539 | 573 | | |
540 | 574 | | |
541 | 575 | | |
| |||
545 | 579 | | |
546 | 580 | | |
547 | 581 | | |
548 | | - | |
549 | | - | |
550 | | - | |
| 582 | + | |
| 583 | + | |
| 584 | + | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
| 590 | + | |
| 591 | + | |
| 592 | + | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
551 | 596 | | |
552 | 597 | | |
553 | 598 | | |
| |||
588 | 633 | | |
589 | 634 | | |
590 | 635 | | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
591 | 670 | | |
592 | 671 | | |
593 | 672 | | |
| |||
758 | 837 | | |
759 | 838 | | |
760 | 839 | | |
761 | | - | |
| 840 | + | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
762 | 844 | | |
763 | 845 | | |
764 | 846 | | |
| |||
995 | 1077 | | |
996 | 1078 | | |
997 | 1079 | | |
998 | | - | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
999 | 1085 | | |
1000 | 1086 | | |
1001 | 1087 | | |
1002 | 1088 | | |
1003 | 1089 | | |
1004 | | - | |
1005 | | - | |
1006 | | - | |
1007 | | - | |
1008 | | - | |
1009 | | - | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
1010 | 1093 | | |
1011 | 1094 | | |
1012 | 1095 | | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
1013 | 1142 | | |
1014 | 1143 | | |
1015 | 1144 | | |
| |||
0 commit comments