Bundler cooldown delays resolution without certifying a gem
Bundler 4.0.13 can exclude newly published gem versions during resolution. The policy uses registry timestamps, preserves existing lockfiles and needs an explicit path for urgent fixes.
A compromised publishing account can distribute a malicious gem before its users have time to notice. Bundler's new cooldown setting introduces a delay between publication and eligibility during dependency resolution. The June 3 announcement describes the feature in Bundler 4.0.13. It is opt-in and filters versions by age. It does not establish that a release has passed a security review.
That distinction explains both its usefulness and its limit. Waiting can create time for reports and detection before a dependency reaches a deployment. Passage of time alone does not inspect the package. The policy assumes that delaying adoption can reduce exposure to short-lived malicious releases while other controls work to discover or remove them.
I still appreciate Ruby's readable syntax and its consistent object model, although its age makes me question choosing it automatically for new projects. This feature addresses a more immediate concern for existing applications. Dependency selection is executable code selection, and the newest available release is not always the most appropriate default for unattended updates.
Registry publication time supplies the evidence
Cooldown reads a per-version created_at timestamp from RubyGems.org's v2 compact index. The announcement says the registry added that data through a dual-write migration and a controlled cutover. Bundler can then determine which versions are younger than the configured number of days. The timestamp is registry metadata, rather than a package author's declaration of when the release should count as published.
The design discussion identifies that metadata issue directly. During discussion, Hiroshi Shibata noted that a gemspec's date can accept arbitrary values. A security policy based on publication age needs an authoritative observation of publication. Otherwise a malicious release could present itself as old through data controlled by its publisher.
Not every source supplies the new timestamp. The announcement says historical entries and older or private servers may lack created_at. Such versions remain resolvable. The filter excludes versions it can establish are too new. It does not turn missing metadata into an indefinite ban on installation.
That compatibility decision gives the feature a precise coverage boundary. Enabling cooldown does not prove that every configured registry enforces an age delay. For a source without the necessary timestamp, the policy cannot distinguish a new version from an old one through this mechanism. The source's metadata support is therefore part of interpreting the configuration.
Resolution and installation of a lockfile differ
The recommended project-level form puts the policy on the Gemfile source. This example uses the seven-day interval illustrated by the announcement.
source "https://rubygems.org", cooldown: 7
gem "rails"
gem "puma"
Committing the source declaration places the interval alongside the dependency requirements. Developers and automation can read the same policy from the project. The setting applies to versions from that source during resolution, without requiring a separate decision for every gem declaration.
An existing Gemfile.lock is honored unchanged. Adding cooldown does not remove versions already selected in that lockfile. The filter matters when creating a resolution without a lockfile or when updating the selected dependencies. This avoids a new policy unexpectedly disrupting an installation that is supposed to reproduce an existing selection.
It also prevents a common misunderstanding. Cooldown is not a retrospective scanner of the locked dependency set. A version already in the lockfile does not become rejected merely because a newly added policy would exclude it from a fresh resolution. Applications need to understand when their automation resolves versions and when it simply installs the recorded set.
The announcement recommends aligning the Bundler version used by the team and recorded in the lockfile. The policy requires the implementation that understands it. A Gemfile declaration and an older resolver are not equivalent to a working shared control. Versioning the tool is part of making the dependency procedure reproducible.
Precedence can change a source's policy
The implementation supports command-line options, configuration and per-source Gemfile settings. Command-line flags take precedence over configuration, which takes precedence over a source's cooldown: option. A global or per-run setting can therefore override the interval visible in the project's source declaration.
The value is a nonnegative integer number of days. Strings, floating-point values, negative numbers and arrays are rejected. This keeps the time unit and accepted configuration explicit. The announcement also describes BUNDLE_COOLDOWN for environment-based control, which is relevant to automation that receives settings outside the repository.
Per-source configuration can distinguish public and internal registries. A public source can require a waiting interval while an internal source uses zero. A command-line cooldown still applies across sources for that run, including a source exempted in the Gemfile. The effective policy must therefore be read through the precedence rules, rather than inferred from one line alone.
When all candidate versions remain within the interval, Bundler fails resolution and reports the exclusions. It does not silently select a too-new version. bundle outdated also distinguishes a newer version held back by cooldown from an immediately eligible update. This makes intentional delay visible instead of presenting every excluded update as though it did not exist.
Urgent fixes need a deliberate exception
A newly published security fix can be exactly the version an application needs immediately. The announcement provides --cooldown 0 as an override. A targeted update can use that option without removing the project's standing source policy. The exception changes the current operation, while the usual delay remains available for later updates.
This tradeoff appeared in the design discussion. Participants raised the risk of delaying legitimate fixes and debated whether stronger publishing authentication should take priority. Others pointed out that controls applied before publication and controls applied after publication address different failures. The released design keeps cooldown optional and provides an explicit urgent-update path.
The scope should remain clear when explaining the feature to application maintainers. MFA and trusted publishing govern who may publish. Cooldown governs when a published version becomes eligible for a resolver using the policy and suitable metadata. Neither mechanism alone establishes that the package contents are correct or benign.
My preference is for dependency policies whose decisions remain explainable from recorded inputs. Cooldown provides a narrow rule based on a registry timestamp and an interval, with a documented exception. Its useful operational result is a resolver that can distinguish an eligible release from one deliberately held back. Security fixes still require a separate decision about whether waiting is appropriate for the vulnerability being addressed.