You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Gem settings resolution skips Bundler's global config (~/.bundle/config / BUNDLE_USER_CONFIG), so a global cache_path or gemfile gets no warning or refusal and VEX attests an unpatched install #577
[agent] Found by the scheduled Bundler (RubyGems) bug-hunt routine (ledger #316).
Summary
#532 (fixing #483 and #507) made socket-patch read Bundler settings "in Bundler::Settings priority", but it only reads two of the tiers Bundler consults: the local app config ($BUNDLE_APP_CONFIG/config, else .bundle/config) and the environment. Bundler's lookup is temporary → local → env → global → default. The global tier is ~/.bundle/config, or $BUNDLE_USER_CONFIG / $BUNDLE_USER_HOME/config, which is what bundle config set --global … writes. socket-patch never reads it, so the two settings that #532 just fixed regress whenever they are set globally:
The patch silently isn't applied, and the VEX document says it is. This is the same outcome #483 and #507 were filed for. Only the place the setting is stored differs, and per-user global config is common on CI images and developer machines.
Repro
Bundler side (real installs, Ruby 3.3.6):
# cache_path: Bundler installs from the globally configured cache dir
mkdir g1 &&cd g1 &&printf'source "https://rubygems.org"\ngem "rack", "3.1.8"\n'> Gemfile
export HOME=$PWD/../home && mkdir -p $HOME
bundle _2.4.22_ config set --global cache_path vendor/gems # lands in $HOME/.bundle/config
mkdir -p vendor/gems && cp /path/to/rack-3.1.8-with-marker.gem vendor/gems/rack-3.1.8.gem
BUNDLE_PATH=$PWD/../bp bundle _2.4.22_ install
grep -c BUGHUNT-MARKER ../bp/ruby/3.3.0/gems/rack-3.1.8/lib/rack.rb # 1: the cached bytes were installed# (control: without the global config the marker count is 0; on 4.0.17 the same setup exits on a CHECKSUMS mismatch, which proves it read vendor/gems)# gemfile: Bundler loads the globally configured manifestprintf'source "https://rubygems.org"\ngem "rack", "3.1.7"\n'> Gemfile.next
bundle _4.0.17_ config set --global gemfile Gemfile.next
bundle _4.0.17_ install # "Installing rack 3.1.7", writes Gemfile.next.lock
socket-patch side (a copy of the gem_hosted_stale_archive_at_configured_cache_path_warns_and_is_not_attested case in crates/socket-patch-cli/tests/e2e_redirect_gem_stale_install.rs, with no .bundle/config and the setting written to $HOME/.bundle/config, or to a BUNDLE_USER_CONFIG file, instead):
global cache_path (HOME/.bundle/config): code=0 redirect_gem_stale_install warnings=0 VEX attests pkg:gem/stale-probe-gem@1.0.0
global cache_path (BUNDLE_USER_CONFIG): code=0 warnings=0 VEX attests the purl
global gemfile=Gemfile.next: code=0, Gemfile rewritten into the patch-registry source block, no refusal
local gemfile=Gemfile.next (control): code=0, Gemfile untouched, redirect_gem_bundle_gemfile_unsupported
Each line reproduced twice.
Expected vs actual
Expected: CLI_CONTRACT.md's "Gem stale-install guard" says the cache dir is "resolved in Bundler::Settings priority", and docs/ecosystems.md says a configured manifest other than the project's Gemfile / gems.rb "is refused with redirect_gem_bundle_gemfile_unsupported". Bundler's priority includes the global config below the env var, so a global cache_path should move the probed cache dir, and a global gemfile should be refused.
Actual: both global settings are ignored. The probe stays on vendor/cache, Gemfile is rewired, and VEX attests.
Matrix
OS
Ruby
Bundler
Global cache_path
Global gemfile
Linux
3.3.6
2.4.22
fail (silent unpatched install)
Bundler honors it; the socket-patch side is version-independent
Linux
3.3.6
4.0.17
fail (no warning, VEX attests; install exits on CHECKSUMS mismatch)
fail
macOS / Windows
—
—
not run (pure settings/text layer, OS-independent)
not run
First bad: always. v4.0.0 and earlier ignored the local tier too, and #532 (cbf1f74) added the local tier but not the global one. Tested on main 1169ae6.
Suspect code
crates/socket-patch-core/src/crawlers/ruby_crawler.rs:984 (read_app_config) is the only config source used by bundler_app_cache_dir_with_env (:1040) and bundler_loaded_manifest_with_env (:962). There's no fallback to the global file after the env var.
crates/socket-patch-core/src/formats/gem/manifest.rs:27: "The user-level ~/.bundle/config is not consulted." That's an internal note, not in the user-facing contract, which promises Bundler's priority.
The same gap probably affects the agent crawler's BUNDLE_PATH discovery (discover_bundle_stores_with_env) for bundle config set --global path …. I haven't verified that end to end.
[agent] Found by the scheduled Bundler (RubyGems) bug-hunt routine (ledger #316).
Summary
#532 (fixing #483 and #507) made socket-patch read Bundler settings "in
Bundler::Settingspriority", but it only reads two of the tiers Bundler consults: the local app config ($BUNDLE_APP_CONFIG/config, else.bundle/config) and the environment. Bundler's lookup istemporary → local → env → global → default. The global tier is~/.bundle/config, or$BUNDLE_USER_CONFIG/$BUNDLE_USER_HOME/config, which is whatbundle config set --global …writes. socket-patch never reads it, so the two settings that #532 just fixed regress whenever they are set globally:cache_path(stale-install guard, Gem hosted stale-install guard only checksvendor/cache, so a committed cache at a configuredcache_pathgets no warning, the in-run VEX attests it, and Bundler 2.4 installs the unpatched gem #483's arm): withbundle config set --global cache_path vendor/gemsand a committed unpatchedvendor/gems/<gem>.gem, hostedscangives noredirect_gem_stale_installwarning, and the same run's--vexattests the gem asnot_affected. Bundler then installs the archive fromvendor/gems.gemfile(Gem manifest resolution lets theBUNDLE_GEMFILEenv var override.bundle/config, but Bundler does the reverse, so hosted mode wiresGemfilewhile bundler installsGemfile.nextunpatched and VEX attests it #507's arm): withbundle config set --global gemfile Gemfile.next, hostedscanrewiresGemfileand exits 0, while Bundler loadsGemfile.nextand installs the unpatched gem. With the same value in the local.bundle/config, the scan correctly refuses withredirect_gem_bundle_gemfile_unsupported.Impact
The patch silently isn't applied, and the VEX document says it is. This is the same outcome #483 and #507 were filed for. Only the place the setting is stored differs, and per-user global config is common on CI images and developer machines.
Repro
Bundler side (real installs, Ruby 3.3.6):
socket-patch side (a copy of the
gem_hosted_stale_archive_at_configured_cache_path_warns_and_is_not_attestedcase incrates/socket-patch-cli/tests/e2e_redirect_gem_stale_install.rs, with no.bundle/configand the setting written to$HOME/.bundle/config, or to aBUNDLE_USER_CONFIGfile, instead):Each line reproduced twice.
Expected vs actual
Bundler::Settingspriority", and docs/ecosystems.md says a configured manifest other than the project'sGemfile/gems.rb"is refused withredirect_gem_bundle_gemfile_unsupported". Bundler's priority includes the global config below the env var, so a globalcache_pathshould move the probed cache dir, and a globalgemfileshould be refused.vendor/cache,Gemfileis rewired, and VEX attests.Matrix
cache_pathgemfileFirst bad: always. v4.0.0 and earlier ignored the local tier too, and #532 (
cbf1f74) added the local tier but not the global one. Tested on main1169ae6.Suspect code
crates/socket-patch-core/src/crawlers/ruby_crawler.rs:984(read_app_config) is the only config source used bybundler_app_cache_dir_with_env(:1040) andbundler_loaded_manifest_with_env(:962). There's no fallback to the global file after the env var.crates/socket-patch-core/src/formats/gem/manifest.rs:27: "The user-level~/.bundle/configis not consulted." That's an internal note, not in the user-facing contract, which promises Bundler's priority.BUNDLE_PATHdiscovery (discover_bundle_stores_with_env) forbundle config set --global path …. I haven't verified that end to end.