Skip to content

Commit d1be1ef

Browse files
committed
bundler bughunt run 64
1 parent 07907a9 commit d1be1ef

2 files changed

Lines changed: 46 additions & 4 deletions

File tree

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
[agent] 2026-11-02: Bundler (RubyGems) bug-hunt run
2+
3+
**Tested:** main `cbbbdb9` (unchanged since run 60; no gem code changes since `b291caa`), release v5.0.1. Linux only: Ruby 3.3.6 with Bundler 2.6.9, 4.0.23 and 4.1.0.beta3 (still the newest per `gem search -r --pre`). Harness: scratch tests in `e2e_redirect_gem_build.rs` and `e2e_redirect_gem_stale_install.rs` (not committed), mock upstream + patch registry on 127.0.0.1, real `gem build` fixtures, real `bundle` commands and frozen fresh installs.
4+
5+
**Re-triage**
6+
- #1831: still open; PR #1841 still open and unmerged, so no comment.
7+
- #1109: still open (`agent:needs-human`); no gem code changes, so no comment.
8+
- No human replies on #316.
9+
10+
**Cells** (backlog item 5)
11+
12+
| Cell | 2.6.9 | 4.0.23 | 4.1.0.beta3 |
13+
| --- | --- | --- | --- |
14+
| Converged CHECKSUMS-less redirect → `bundle outdated` exit 0 → `bundle update vuln-gem --conservative` exit 0, lock byte-identical → frozen fresh install PATCHED → re-scan exit 0, lock byte-identical | pass | pass | pass |
15+
| Then `bundle add tiny-dep --version "~> 1.0"` (appended after the Socket `source … do` block) → re-scan exit 0, Gemfile and lock byte-identical → frozen fresh install PATCHED | pass | pass | pass |
16+
| Then `rollback` / `remove <purl>`: exit 0, Socket block gone, the added `gem "tiny-dep"` line and its DEPENDENCIES entry kept → frozen fresh install exit 0, lock byte-identical | pass | pass | pass |
17+
| Same with a CHECKSUMS lock (4.0.23): outdated / update --conservative / add / re-scan / frozen install PATCHED pass; `rollback` refuses `hosted_restore_refused` (127.0.0.1 upstream, documented) | n/a | pass | n/a |
18+
19+
**Cells** (backlog item 4, stale-install guard, OS/version-independent unit-level harness with a fake `gem env gemdir`)
20+
21+
| Hosted decl in `group :development`, unpatched copy in the system gem home | Result |
22+
| --- | --- |
23+
| `BUNDLE_WITHOUT=development` (env) | warns `redirect_gem_stale_install` (shared-home flavor), purl not attested, exit 1 |
24+
| `BUNDLE_WITHOUT: development` in `.bundle/config` | same |
25+
| `BUNDLE_ONLY=default` | same |
26+
| `BUNDLE_WITHOUT` + `BUNDLE_PATH: vendor/bundle` | quiet, attests, exit 0 (#1001 rule) |
27+
| No exclusion (control) | warns, exit 1 |
28+
29+
All consistent with CLI_CONTRACT.md's Gem stale-install guard: group exclusion isn't part of the judgment, so the guard stays conservative (the shared copy is what `bundle install --with development` would reuse) and never attests a stale purl. Recorded as a known non-bug.
30+
31+
**Filed:** nothing. **Commented / closed:** nothing.
32+
33+
**Ruled out:** the excluded-group warning above (conservative, no false attestation); `rollback` refusing on a CHECKSUMS lock with a 127.0.0.1 upstream (documented `hosted_restore_refused`).
34+
35+
**Probes:** none (leftover `bughunt/bundler/*` branches still block; see backlog).
36+
37+
**Next**
38+
1. Re-check #1831 when #1841 merges, then the 2.6.9 / 4.0.23 CRLF Gemfile hosted unwind.
39+
2. 4.1.0 final when it ships; 2.2 / 2.4 legs (Ruby 3.1.6) on the next main that touches gem code.
40+
3. `bundle add` of a gem that resolves from the patch registry's source (a second gem inside the Socket block), and `bundle update --all` over a converged hosted lock.
41+
4. `bundle lock --update vuln-gem` / `bundle lock --patch` over a converged CHECKSUMS lock with the rubygems.org spelling + mirror (run-60 setup).

‎state/bundler.md‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[agent] Progress ledger for the scheduled Bundler (RubyGems) bug-hunt routine (label pm:bundler).
22

3-
Last updated: 2026-11-01 (run 63), main `cbbbdb9` (unchanged since run 60; no gem code changes since `b291caa`), latest release v5.0.1 (npm; no git tags). Newest Bundler: 4.0.23 stable, 4.1.0.beta3. Run 63 covered `bundle lock --remove-platform` / `--normalize-platforms` over a converged CHECKSUMS redirect, `bundle remove` of the hosted gem followed by `rollback` / `remove`, and `BUNDLE_ONLY` / `BUNDLE_WITHOUT` on 2.6.9, 4.0.23 and 4.1.0.beta3 (all pass; see the run-63 table). Run 62 covered `bundle lock --add-platform` after a converged CHECKSUMS redirect, a superseding generation over a user-checksummed lock on 4.1.0.beta3 and 2.6.9 (backlog item 5), and `BUNDLE_WITHOUT` excluding the hosted gem (all pass; see the run-62 table). Run 61 covered `bundle lock --add-checksums` on an unconverged redirect, a superseding patch generation over a user-checksummed lock, and the transitive unwind with a trailing blank line (all pass; see the run-61 table). Run 60 covered the hosted lifecycle when a user adds CHECKSUMS after a converged redirect (`bundle lock --add-checksums`), on 2.6.9, 4.0.23 and 4.1.0.beta3, via a scratch test in `e2e_redirect_gem_build.rs` (upstream respelled `https://rubygems.org` in the pair after the scan, `BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/=<mock>/upstream/` for Bundler, `SOCKET_RUBYGEMS_URL=<mock>/upstream` for socket-patch). Run 59 closed backlog item 4 (Bundler 4.0.23 phantom platform lock entry: re-scan, remedy, re-converge, `vex`, `rollback` / `remove`) and the 2.6.9 hosted-unwind direct-dep and `group` cells. Run 59 used a standalone harness instead of a scratch Rust test: a Python mock (upstream compact index with ruby + `x86_64-linux` variants, patch registry, patches API) plus real `gem build` fixtures. Pass `--patch-server-url <mock>` to `rollback` / `remove` / `vex`, or a 127.0.0.1 pin isn't treated as hosted and the commands report `manifest_not_found`. Ruby 3.1.6 is in the sandbox (`/opt/rbenv/versions/3.1.6/bin`); `gem install bundler -v 1.17.3` / `2.1.4` there and export `BUNDLER_VERSION` + `SOCKET_PATCH_BUNDLER_E2E_VERSION`. A fresh container's Ruby 3.3.6 only has 2.5.22 / 4.0.18, so `gem install bundler -v 2.6.9` / `4.0.23` / `4.1.0.beta3` first and export `BUNDLER_VERSION`. Bundler 2.6 has no `install -q` (use `--quiet`).
3+
Last updated: 2026-11-02 (run 64), main `cbbbdb9` (unchanged since run 60; no gem code changes since `b291caa`), latest release v5.0.1 (npm; no git tags). Newest Bundler: 4.0.23 stable, 4.1.0.beta3. Run 64 covered `bundle outdated` / `bundle update --conservative` / `bundle add` over a converged hosted lock followed by re-scan, frozen install and `rollback` / `remove` on 2.6.9, 4.0.23 and 4.1.0.beta3 (all pass), and the stale-install guard with an excluded group plus a system-home copy (conservative warning, documented; see Known non-bugs). Run 63 covered `bundle lock --remove-platform` / `--normalize-platforms` over a converged CHECKSUMS redirect, `bundle remove` of the hosted gem followed by `rollback` / `remove`, and `BUNDLE_ONLY` / `BUNDLE_WITHOUT` on 2.6.9, 4.0.23 and 4.1.0.beta3 (all pass; see the run-63 table). Run 62 covered `bundle lock --add-platform` after a converged CHECKSUMS redirect, a superseding generation over a user-checksummed lock on 4.1.0.beta3 and 2.6.9 (backlog item 5), and `BUNDLE_WITHOUT` excluding the hosted gem (all pass; see the run-62 table). Run 61 covered `bundle lock --add-checksums` on an unconverged redirect, a superseding patch generation over a user-checksummed lock, and the transitive unwind with a trailing blank line (all pass; see the run-61 table). Run 60 covered the hosted lifecycle when a user adds CHECKSUMS after a converged redirect (`bundle lock --add-checksums`), on 2.6.9, 4.0.23 and 4.1.0.beta3, via a scratch test in `e2e_redirect_gem_build.rs` (upstream respelled `https://rubygems.org` in the pair after the scan, `BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/=<mock>/upstream/` for Bundler, `SOCKET_RUBYGEMS_URL=<mock>/upstream` for socket-patch). Run 59 closed backlog item 4 (Bundler 4.0.23 phantom platform lock entry: re-scan, remedy, re-converge, `vex`, `rollback` / `remove`) and the 2.6.9 hosted-unwind direct-dep and `group` cells. Run 59 used a standalone harness instead of a scratch Rust test: a Python mock (upstream compact index with ruby + `x86_64-linux` variants, patch registry, patches API) plus real `gem build` fixtures. Pass `--patch-server-url <mock>` to `rollback` / `remove` / `vex`, or a 127.0.0.1 pin isn't treated as hosted and the commands report `manifest_not_found`. Ruby 3.1.6 is in the sandbox (`/opt/rbenv/versions/3.1.6/bin`); `gem install bundler -v 1.17.3` / `2.1.4` there and export `BUNDLER_VERSION` + `SOCKET_PATCH_BUNDLER_E2E_VERSION`. A fresh container's Ruby 3.3.6 only has 2.5.22 / 4.0.18, so `gem install bundler -v 2.6.9` / `4.0.23` / `4.1.0.beta3` first and export `BUNDLER_VERSION`. Bundler 2.6 has no `install -q` (use `--quiet`).
44

55
## Coverage matrix
66

@@ -626,16 +626,17 @@ Also on 4.0.17: BOM `Gemfile` passes; symlinked `Gemfile` / lock is refused (pas
626626

627627
## Backlog
628628

629-
1. Re-check #1831 once fixed (PR #1841, not merged as of run 63): hosted redirect on a CRLF Gemfile keeps CRLF in the in-place and the append (transitive) arms; `rollback` / `remove` still byte-exact; an autocrlf re-checkout of a redirected LF Gemfile re-scans as a no-op. Then the 2.6.9 / 4.0.23 CRLF Gemfile hosted unwind.
629+
1. Re-check #1831 once fixed (PR #1841, not merged as of run 64): hosted redirect on a CRLF Gemfile keeps CRLF in the in-place and the append (transitive) arms; `rollback` / `remove` still byte-exact; an autocrlf re-checkout of a redirected LF Gemfile re-scans as a no-op. Then the 2.6.9 / 4.0.23 CRLF Gemfile hosted unwind.
630630
2. Re-run #1109 (`agent:needs-human`) when it's fixed.
631631
3. The gem suites on 4.1.0 final when it ships; a 2.2 / 2.4 leg (Ruby 3.1.6) on the next main that touches gem code.
632-
4. The stale-install guard with an excluded group plus an unpatched system-gem copy.
633-
5. `bundle update vuln-gem --conservative` / `bundle outdated` over a converged hosted lock; `bundle add` of a second gem next to the Socket source block.
632+
4. `bundle add` of a second gem that resolves from the patch registry source (inside the Socket block), and `bundle update --all` over a converged hosted lock.
633+
5. `bundle lock --update vuln-gem` / `bundle lock --patch` over a converged CHECKSUMS lock with the rubygems.org spelling + mirror (run-60 setup).
634634
6. Vendored stub-vs-lock runtime-dependency drift, only if the service `gem-stub-gemspec` can declare other deps than the lifted GEM spec block (a file patch can't).
635635
7. macOS / Windows probes stay blocked until a maintainer deletes the leftover `bughunt/bundler/*` branches and push-triggered runs work again (none has triggered since 2026-10-05).
636636

637637
## Known non-bugs
638638

639+
- The hosted stale-install guard ignores group exclusion: with the hosted gem in `group :development`, `BUNDLE_WITHOUT=development` (env or `.bundle/config`) or `BUNDLE_ONLY=default`, and an unpatched copy in a system gem home Bundler uses, `scan --mode hosted --vex` still warns `redirect_gem_stale_install` (shared-home flavor) and omits the purl (exit 1 when nothing else attests). That is conservative, matches the contract (groups aren't part of the judgment), and the copy is what `bundle install --with development` would reuse. With a `BUNDLE_PATH` it stays quiet per #1001 (run 64).
639640
- After the user runs `bundle remove` on a hosted gem (Bundler drops the whole Socket `source … do` block), `rollback` / `remove` exit 1 with `manifest_not_found` and write nothing; there's nothing left to unwind. A re-scan then skips with `redirect_gem_version_not_locked` because `bundle remove` leaves the installed copy in `vendor/bundle` (run 63).
640641
- `vex` attests a hosted gem `not_affected` `(redirected)` from the lock pin when its group is excluded by `BUNDLE_WITHOUT` and nothing is installed. That is the documented "With nothing installed, a discovered reference whose lock pins the artifact attests from that pin" rule (CLI_CONTRACT.md VEX evidence table, hosted row) (run 62).
641642

0 commit comments

Comments
 (0)