The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
- Sarah Gooding
Bundler 4.0.18 adds the opt-in --cooldown
flag to bundle lock
and bundle cache
, closing gaps where the setting could not be applied.
Bundler 4.0.18, released August 5, 2026 alongside RubyGems 4.0.18, extends the cooldown feature to two more commands. The opt-in --cooldown
flag now works with bundle lock
and bundle cache
, which previously resolved dependencies without accepting the flag. RubyGems lists the change under Bundler security in the release notes.
The cooldown feature is not new. It shipped in Bundler 4.0.13 in June as a time-based filter that refuses to resolve to a gem version until it has been public for a set number of days. The 4.0.18 change does not alter how cooldown works. It makes the flag available on commands that were left out of the first release.
What cooldown does
Cooldown delays resolution to gem versions that are too new under a configured policy. It does not decide whether a gem is safe. It reads per-version created_at
metadata from RubyGems.org's v2 compact index, compares each version's release time against the configured window, and skips versions that are still inside it.
The feature is opt-in and disabled by default. A project enables it per source in the Gemfile:
source "https://rubygems.org" cooldown: 7
With that setting, Bundler skips gem versions published in the last seven days. When a project needs the newest version anyway, including an urgent security fix, --cooldown 0
disables the delay for a single run.
That situation came up in late July. On July 29, the Rails security team published a critical Active Storage advisory, an arbitrary file read that can escalate to remote code execution. Bundler maintainer Hiroshi SHIBATA pointed out that projects running cooldown would need to run bundle update rails --cooldown 0
to pull the patched version immediately rather than wait out the window.
The gap in the first release
The original cooldown work added the flag to bundle install
, bundle update
, bundle add
, and bundle outdated
. bundle lock
and bundle cache
also resolve dependencies, but neither accepted --cooldown
.
That left a dead end. When cooldown blocks a version, Bundler's resolver prints a failure hint that suggests running with --cooldown 0
to override the delay. On bundle lock --update
, that hint pointed at a flag the command did not accept, so a developer who followed the suggestion got an error instead of a resolved lockfile.
bundle lock --update
regenerates a lockfile without installing gems. It is common in automated workflows, including scheduled jobs that raise dependency updates. That use case was raised directly in the discussion thread that led to cooldown. Without the flag, those workflows could not override the delay the way bundle install
could.
What changed in 4.0.18
The PR for this feature adds --cooldown
to bundle lock
and bundle cache
with the same validation and settings propagation as bundle install
. bundle cache
resolves through bundle install
internally, so the flag applies on both the cache path and the direct resolve path. The change also documents the flag in Bundler's manual entries for both commands.
The override the resolver was already recommending now works on lock:
bundle lock --update --cooldown 0
The pull request also adds a regression test for an existing property of the filter. Cooldown exclusion keys on gem name and version and ignores platform. RubyGems allows publishing platform-specific builds, such as a native gem for x86_64-linux
, under a version number that already exists. If the filter checked platform, an attacker could push a fresh build under an already-aged version number and have it resolve immediately. Keying on name and version alone prevents that. No test previously covered the behavior, and the new spec pins it so a future change cannot weaken it without failing CI.
Bundler 4.0.18 also now warns when duplicate source declarations conflict on cooldown, added in pull request #9736 and listed under Bundler enhancements in the release notes. Teams that declare the same source more than once with different cooldown values now get a warning rather than a silently applied result.
Cooldown as a layered control
Cooldown remains opt-in and off by default. It does not replace registry-side defenses such as push-time validation, mandatory 2FA, and trusted publishing. It gives consumers a way to delay adoption of releases that have only just appeared, on the assumption that many malicious versions are detected and removed within hours while automated installs can consume them almost immediately.
Extending the flag to bundle lock
and bundle cache
means the control now applies across the commands that resolve dependencies, including lockfile generation and gem vendoring, not just install and update.
The change fits a wider pattern across package managers. pnpm added minimumReleaseAge
to delay dependency updates, npm followed with a similar setting, and gem.coop tested cooldown at the registry layer. Bundler applies the same idea in the client during dependency resolution, and 4.0.18 makes it usable across more of the commands that trigger that resolution.
