Skip to content

Back to the catalog

Socket: RubyGems Bundler 4.0.13 Adds Opt-In Cooldown for Newly Published Gems
socket.devarticle

Socket: RubyGems Bundler 4.0.13 Adds Opt-In Cooldown for Newly Published Gems

RubyGems and Bundler 4.0.13 introduced an opt-in 'cooldown' feature that lets projects delay dependency resolution to newly published gem versions (e.g. source "https://rubygems.org", cooldown: 7), using per-version created_at timestamps from RubyGems.org's v2 compact index. The goal is to blunt fast-moving supply-chain attacks where a compromised maintainer account pushes a malicious release that CI/automated installs pick up within hours; it joins similar minimumReleaseAge controls already added by pnpm and npm, and gem.coop's earlier registry-side cooldown experiment. Bundler's cooldown is conservative (skips gems only when timestamp metadata proves they're too new, ignores older/private sources lacking it) and configurable via Gemfile, CLI flags, env var, or config, with a --cooldown 0 escape hatch for urgent fixes.

TL;DR Bundler 4.0.13 adds an opt-in cooldown setting that delays resolving to gem versions published within a configurable window, mirroring npm/pnpm minimumReleaseAge to slow fast-moving supply-chain attacks.
Document

What it is

The opt-in cooldown feature in RubyGems and Bundler 4.0.13. It makes Bundler skip gem versions published within a configured window (in days) during dependency resolution, so fresh releases aren't picked up by installs or CI before there's time to catch a malicious one.

How it works

Bundler compares each version's created_at timestamp against the configured cooldown and skips versions still inside the window. The timestamp comes from RubyGems.org's v2 compact index — not a new public API field, so general API consumers can't query it. The behavior is conservative: if Bundler can't prove a version is too new (older gem servers, historical pre-v2 entries, private registries that don't expose timestamps), it does not block it. Cooldown is unset by default.

What to do

Set a per-source cooldown in the Gemfile:

source "https://rubygems.org", cooldown: 7

Apply different policies per registry — e.g. delay RubyGems.org but resolve an internal server immediately:

source "https://rubygems.org", cooldown: 7
source "https://gems.internal.example.com", cooldown: 0 do
  gem "internal-tool"
end

Cooldown can also be set via project config, global config, the BUNDLE_COOLDOWN environment variable, and CLI flags on bundle install, bundle update, bundle add, and bundle outdated.

Escape hatch for an urgent fix — disable the delay for a single run:

--cooldown 0

Precedence, highest to lowest:

flowchart LR
  A[Command-line flags] --> B[Config settings]
  B --> C[Per-source Gemfile settings]

bundle outdated now annotates a newer-but-still-in-window version with the remaining cooldown time, rather than reporting the project as up to date.

Caveats

Cooldown does not determine whether a gem is safe — it only delays resolution to versions too new under the policy. It holds back legitimate releases too, including urgent security fixes; the opt-in design and --cooldown 0 are the intended releases valves. Because the filter depends on the source exposing timestamps, sources that don't provide the metadata remain fully resolvable, so the protection is only as good as timestamp visibility for a given registry.

Organisations named here

  • Alpha Omega
  • Hiroshi SHIBATA

Technologies named here

  • RubyGems
  • Bundler
  • RubyGems.org
  • RubyGems.org v2 compact index
  • gem.coop
  • pnpm
  • npm
  • Have I Been Pwned
  • Anthropic

Techniques named here

  • Time-based install delay
  • Malicious release via compromised maintainer account