Skip to content

Commit c63beb7

Browse files
committed
bundler: run 65 ledger
1 parent 20039e9 commit c63beb7

2 files changed

Lines changed: 44 additions & 4 deletions

File tree

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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` (not committed), mock upstream + patch registry on 127.0.0.1, real `gem build` fixtures, real `bundle` commands and frozen fresh installs. After the hosted lock converged, the mock upstream started serving newer `tiny-dep 1.0.1` and `vuln-gem 1.0.1` (the original 1.0.0 bytes were served back unchanged).
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 items 4 and 5). Each cell: the command → Gemfile byte-identical, lock keeps the patch-registry GEM remote → re-scan exit 0, Gemfile unchanged → frozen fresh install PATCHED, lock byte-identical → `vex` attests `(redirected)` → `rollback` → frozen install of the restored pair exit 0, lock byte-identical.
11+
12+
| Command over a converged hosted lock | Lock / upstream spelling | 2.6.9 | 4.0.23 | 4.1.0.beta3 |
13+
| --- | --- | --- | --- | --- |
14+
| `bundle update --all` (tiny-dep → 1.0.1, vuln-gem stays 1.0.0 on the exact pin) | no CHECKSUMS, 127.0.0.1 | pass | pass | pass |
15+
| `bundle update --all` | no CHECKSUMS, rubygems.org + mirror | pass | pass | pass |
16+
| `bundle update --all` | CHECKSUMS, rubygems.org + mirror | pass | pass | pass |
17+
| `bundle lock --update vuln-gem` | CHECKSUMS, rubygems.org + mirror | pass | pass | pass |
18+
| `bundle lock --patch` | CHECKSUMS, rubygems.org + mirror | pass (no-op) | pass (no-op) | pass (no-op) |
19+
| `bundle lock --update tiny-dep` | no CHECKSUMS, 127.0.0.1 | pass | pass | pass |
20+
| The three CHECKSUMS commands, 127.0.0.1 upstream | CHECKSUMS, 127.0.0.1 | pass up to `rollback`, which refuses `hosted_restore_refused` (documented) | same | same |
21+
22+
After `rollback`, the restored CHECKSUMS lines carry the fresh upstream sha for whatever version the update chose (tiny-dep 1.0.1), and a frozen install accepts the pair.
23+
24+
**Filed:** nothing. **Commented / closed:** nothing.
25+
26+
**Ruled out:**
27+
- An exit-37 mismatched-checksums failure in my first attempt. My harness rebuilt `tiny-dep 1.0.0` with `gem build`, which changed its sha. Serving the original bytes fixed it, so it was a harness artifact (now under Known non-bugs).
28+
- `bundle lock --patch` without `--update` changes nothing. That's Bundler behavior.
29+
- `rollback` refusing on a CHECKSUMS lock with a 127.0.0.1 upstream is the documented `hosted_restore_refused`.
30+
31+
**Probes:** none (leftover `bughunt/bundler/*` branches still block; see backlog).
32+
33+
**Next**
34+
1. Re-check #1831 when #1841 merges, then the 2.6.9 / 4.0.23 CRLF Gemfile hosted unwind.
35+
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.
36+
3. `bundle add` of a gem that resolves from the patch registry's source (a second gem inside the Socket block).
37+
4. Vendored stub-vs-lock runtime-dependency drift, if the service stub can diverge.

‎state/bundler.md‎

Lines changed: 7 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-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`).
3+
Last updated: 2026-11-02 (run 65), 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 65 covered `bundle update --all`, `bundle lock --update vuln-gem`, `bundle lock --update tiny-dep` and `bundle lock --patch` over a converged hosted lock after newer upstream `tiny-dep 1.0.1` / `vuln-gem 1.0.1` were published, with and without CHECKSUMS, on the 127.0.0.1 spelling and the rubygems.org spelling + `BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/`, then re-scan, frozen fresh install PATCHED, `vex`, `rollback` and a frozen install of the restored pair, on 2.6.9, 4.0.23 and 4.1.0.beta3 (all pass; see the run-65 entry). 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,19 @@ 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 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.
629+
1. Re-check #1831 once fixed (PR #1841, not merged as of run 65): 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. `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).
632+
4. `bundle add` of a second gem that resolves from the patch registry source (inside the Socket block). (`bundle update --all` is done, run 65.)
633+
5. A superseding patch generation for `vuln-gem 1.0.1` after `bundle update vuln-gem` moved past a relaxed (`~>`) user pin, if the redirect ever keeps a non-exact requirement; today it pins the exact version, so the update can't move it (run 65).
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+
- `bundle lock --patch` on its own doesn't move any gem (it only sets the update level for `--update`), so over a converged hosted lock it leaves the lock unchanged. Bundler behavior, not socket-patch (run 65).
640+
- In scratch harnesses, rebuilding a fixture gem with `gem build` gives different bytes (timestamps), so re-serving a "same version" from the mock upstream trips Bundler's exit-37 mismatched-checksums refusal on a CHECKSUMS lock. Serve the original bytes back instead; this is a harness artifact (run 65).
641+
639642
- 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).
640643
- 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).
641644
- `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).

0 commit comments

Comments
 (0)