Hosted gem scan ignores a Gemfile `lockfile "custom.lock"` DSL call (Bundler 4), so it pins the unused Gemfile.lock, leaves the real lock untouched, and every frozen install fails
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 35/100
調査の方向性
Start with crates/socket-patch-core/src/formats/gem/manifest.rs, especially LoadedManifest::with_lockfile and LoadedManifest::pair, and trace how the hosted engine reads Gemfile lockfile settings. Check crates/socket-patch-core/src/vendor/gem.rs and the existing Bundler 4 custom lockfile tests for the related vendored path. Add coverage for a Gemfile lockfile DSL call; done means hosted scans either refuse it without writing files or pin the lock Bundler actually uses, and frozen install succeeds.
索引モデルが issue の本文から書いたものです。
説明
[agent] Found by the scheduled Bundler (RubyGems) bug-hunt routine (ledger #316).
Summary
Bundler 4 has four ways to name a custom lockfile: BUNDLE_LOCKFILE in the env, the app config or the global config, plus a lockfile "<path>" call in the Gemfile itself. #768 (closing #749) refuses the three config/env spellings with redirect_gem_bundle_lockfile_unsupported. Nothing reads the Gemfile DSL spelling. With a Gemfile that starts with lockfile "custom.lock", scan --mode hosted:
- rewrites the
Gemfile(adds the patch-registrysource … doblock), - pins the leftover
Gemfile.lock, which Bundler no longer reads, - leaves
custom.lock, the lock Bundler actually reads, byte-untouched, - reports no
redirect_gem_bundle_lockfile_unsupported(or any lockfile) warning.
The next BUNDLE_FROZEN=true / deployment bundle install then fails: "The list of sources changed, but the lockfile can't be updated because frozen mode is set". The same project installs frozen without trouble before the scan.
The previous bug-hunt run posted this gap as a comment on the closed #749 (2026-10-08, main 823810a). It still reproduces on main 15c2c83, so this issue tracks it on its own.
Impact
CI and production installs (frozen or deployment) of a Bundler 4 project that uses the lockfile DSL break after a hosted scan. In the #749 comment's shape (no pre-existing install), the scan also exits 0 and the in-run --vex attests not_affected for a lock that was never pinned.
Repro
I used a scratch copy of crates/socket-patch-cli/tests/e2e_redirect_gem_build.rs, gem_hosted_bundler4_custom_lockfile_redirects_nothing. In the ScanVexCustomLockfile setup, I replaced bundle config set --local lockfile custom.lock with prepending lockfile "custom.lock"\n to the Gemfile. custom.lock is a copy of the pristine lock, and Gemfile.lock is left behind, exactly as in the existing test. I replaced the assertions with prints, then ran:
SOCKET_PATCH_BUNDLER_E2E_REQUIRED=1 cargo test -p socket-patch-cli --test <scratch copy> -- \
gem_hosted_bundler4_custom_lockfile_redirects_nothing --include-ignored --nocapture
- Pristine project with the DSL line:
BUNDLE_FROZEN=true bundle installexits 0. scan --mode hosted --json --vex …producessummary.applied: 1. Its warnings are onlyredirect_gem_stale_installandvex_omitted(this harness pre-installs intovendor/bundle), and there is noredirect_gem_bundle_lockfile_unsupported.GemfileandGemfile.lockare rewritten (Gemfile.locknow has the patch-registryGEMsection,vuln-gem (= 1.0.0)!and the patched sha256).custom.lockis unchanged (upstream remote,DEPENDENCIES vuln-gem, upstream sha256).- The frozen install afterwards fails:
The list of sources changed, but the lockfile can't be updated because frozen
mode is set
You have added to the Gemfile:
* vuln-gem (= 1.0.0)
You have deleted from the Gemfile:
* vuln-gem
You have changed in the Gemfile:
* vuln-gem from `no specified source` to `rubygems repository http://127.0.0.1:…/patch-registry/gem/…/`
Expected vs actual
- Expected: docs/ecosystems.md (RubyGems row) says "bundler 4's
BUNDLE_LOCKFILE… naming any other lock is refused withredirect_gem_bundle_lockfile_unsupported", and #749's contract is that the scan refuses, writes nothing and still installs frozen. Bundler'sDsl#to_definitionlets the Gemfilelockfilecall override the CLI/config lock (lockfile = @lockfile unless @lockfile.nil?, bundler 4.0.18lib/bundler/dsl.rb:193), so the DSL spelling should get the same refusal, or the scan should pin the lock it names. - Actual: the wrong lock is pinned with no warning, and frozen installs break.
Matrix (Linux, Ruby 3.3.6)
| Bundler | main | Lockfile spelling | Refused | custom.lock pinned |
Frozen install after scan |
|---|---|---|---|---|---|
| 4.0.22 | 15c2c83 |
Gemfile DSL lockfile "custom.lock" |
no (×2) | no | fails |
| 4.0.18 | 15c2c83 |
Gemfile DSL | no | no | fails |
| 4.0.18 | 823810a |
Gemfile DSL, no prior install (#749 comment) | no | no | fails, exit 16; in-run VEX attests |
| 4.0.x | 15c2c83 |
.bundle/config / env / global BUNDLE_LOCKFILE |
yes (existing test) | n/a | passes |
| < 4.0 | — | n/a (the DSL method doesn't exist) | — | — | — |
macOS and Windows weren't probed. The logic is OS-independent.
Suspect code
LoadedManifest::with_lockfile (crates/socket-patch-core/src/formats/gem/manifest.rs:183) only receives BUNDLE_LOCKFILE from env, app config and global config (manifest.rs:262 reads the config key). No gem reader parses a top-level lockfile call in the Gemfile / gems.rb, so the hosted engine falls through to the default Gemfile.lock pair (LoadedManifest::pair). The vendored path (crates/socket-patch-core/src/vendor/gem.rs, a_bundler4_custom_lockfile_is_refused) is probably affected the same way. I didn't verify it this run. lockfile false (Bundler writes no lock) is a related, untested shape.
- 主要言語
- Rust
- スター
- 8
- フォーク
- 1
- 平均マージ
- 17時間 5分
- マージ済み PR(30日)
- 557
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
SocketDev/socket-patch のほかの issue
-
agent:triaged bug bughunt pm:npm priority:p3 ux
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
SocketDev/socket-patch#1072 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
agent:triaged bug bughunt pm:yarn-berry priority:p1
難易度 2/5 1〜3時間 初心者へのやさしさ 73/100
SocketDev/socket-patch#783 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Vendored cargo warns cargo_multi_version_old_cargo ("declares no rust-version") when the root package inherits rust-version from [workspace.package]対応中かも @mikolalysenko が 2 日前に担当しました。 オープンagent:triaged bug bughunt pm:cargo priority:p2
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
SocketDev/socket-patch#651 · コメント 3 件 ·
メンテナーはふだん 1 日以内に返信
-
bug bughunt pm:npm
難易度 4/5 1〜2日 初心者へのやさしさ 45/100
SocketDev/socket-patch#1534 ·
メンテナーはふだん 1 日以内に返信
-
agent:triaged bug bughunt pm:bundler priority:p1
難易度 4/5 3〜5日 初心者へのやさしさ 35/100
SocketDev/socket-patch#1531 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
SocketDev/socket-patch の issue をすべて見る
似ている issue
-
RUSTSEC-2026-0348: Brotli certificate decompression can allocate up to 1 GiB before authenticationオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 60/100
-
難易度 1/5 1〜3時間 初心者へのやさしさ 62/100
-
core: Amount::from_str panics on values above 21M BTC instead of returning an error対応中かも @bhuvan-somisetty が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
メンテナーはふだん 1 日以内に返信
-
crate: spate-s3
難易度 2/5 半日 初心者へのやさしさ 62/100
メンテナーはふだん 1 日以内に返信
-
write_iceberg ignores the table's write.parquet.compression-codec property対応中かも @YuangGao が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
Eventual-Inc/Daft#7606 ·
メンテナーはふだん 1 日以内に返信