Skip to content

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

Description

[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:

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):

# 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 manifest
printf '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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions