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 天内回复
评估
调研方向
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
- 平均合并
- 16 小时 19 分钟
- 30 天内合并 PR
- 586
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
SocketDev/socket-patch 的其他 Issue
-
agent:triaged bug bughunt pm:pipenv priority:p1
难度 2/5 1-3 小时 新手友好度 78/100
SocketDev/socket-patch#1608 · 1 条评论 ·
维护者通常 1 天内回复
-
agent:triaged bug bughunt pm:vlt priority:p1
难度 2/5 1-3 小时 新手友好度 62/100
SocketDev/socket-patch#1601 · 2 条评论 ·
维护者通常 1 天内回复
-
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 于 5 天前认领。 未关闭agent:triaged bug bughunt pm:cargo priority:p2
难度 2/5 1-3 小时 新手友好度 84/100
SocketDev/socket-patch#651 · 3 条评论 ·
维护者通常 1 天内回复
查看 SocketDev/socket-patch 的全部 Issue
相似的 Issue
-
难度 1/5 1 小时以内 新手友好度 88/100
pop-os/cosmic-comp#2956 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
维护者通常 1 天内回复
-
area:release criticality:p3 documentation
难度 2/5 1-3 小时 新手友好度 68/100
registrystack/registry-stack#2085 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 85/100
libp2p/rust-libp2p#6694 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 78/100
EmbarkStudios/cargo-deny#910 ·