<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: SHIBATA Hiroshi</title>
    <description>The latest articles on Forem by SHIBATA Hiroshi (@hsbt).</description>
    <link>https://forem.com/hsbt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F44575%2F35bf85fc-f4e7-44d1-ad78-eb59e62a2669.jpeg</url>
      <title>Forem: SHIBATA Hiroshi</title>
      <link>https://forem.com/hsbt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/hsbt"/>
    <language>en</language>
    <item>
      <title>Is Your Ruby Version Still Supported? A Maintainer's Guide to Ruby's Release Cycle</title>
      <dc:creator>SHIBATA Hiroshi</dc:creator>
      <pubDate>Mon, 06 Apr 2026 07:25:38 +0000</pubDate>
      <link>https://forem.com/hsbt/is-your-ruby-version-still-supported-a-maintainers-guide-to-rubys-release-cycle-799</link>
      <guid>https://forem.com/hsbt/is-your-ruby-version-still-supported-a-maintainers-guide-to-rubys-release-cycle-799</guid>
      <description>&lt;p&gt;I'm Hiroshi Shibata (hsbt), a Ruby committer and one of the branch maintainers responsible for Ruby's stable releases. I also maintain RubyGems and Bundler.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Since the March 2026 security releases of Ruby 3.3.11 and 3.2.11, no critical build issues or other problems have been reported. As announced in each release note, I'm now confirming: &lt;strong&gt;Ruby 3.2 has reached end-of-life&lt;/strong&gt;, and &lt;strong&gt;Ruby 3.3 has moved to security-only maintenance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If you're on either version, now is the time to plan your upgrade to Ruby 3.4 or 4.0. This post explains how Ruby's release cycle works, who maintains each branch, and what "security maintenance" actually means in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened in March
&lt;/h2&gt;

&lt;p&gt;On March 26-27, 2026, we released Ruby 3.3.11 and Ruby 3.2.11 — both addressing CVE-2026-27820, a buffer overflow in &lt;code&gt;Zlib::GzipReader&lt;/code&gt;. These weren't ordinary patch releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.ruby-lang.org/en/news/2026/03/27/ruby-3-2-11-released/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ruby 3.2.11&lt;/strong&gt;&lt;/a&gt; is the final release of the 3.2 series. No further updates of any kind will be provided. Ruby 3.2 had been supported for over three years since its initial release on December 25, 2022.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.ruby-lang.org/en/news/2026/03/26/ruby-3-3-11-released/" rel="noopener noreferrer"&gt;&lt;strong&gt;Ruby 3.3.11&lt;/strong&gt;&lt;/a&gt; is the last normal maintenance release of the 3.3 series. From now on, Ruby 3.3 enters security-only maintenance for one year, until March 2027.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This kind of status transition happens every spring, roughly three to four months after the Christmas release of a new Ruby version. If you've been using Ruby for a while, the pattern might feel familiar. But the details of how it works aren't widely documented in English, so here's the full picture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ruby's Versioning: Not Quite Semver
&lt;/h2&gt;

&lt;p&gt;Ruby follows a &lt;a href="https://docs.ruby-lang.org/en/master/maintaining_ruby.html" rel="noopener noreferrer"&gt;&lt;code&gt;MAJOR.MINOR.TEENY&lt;/code&gt;&lt;/a&gt; scheme that looks like semantic versioning but isn't exactly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MAJOR&lt;/strong&gt; increases when Matz decides the time is right. There's no predetermined criteria or schedule — it's entirely his call. The jump from 2.x to 3.0 happened when Ruby 3x3 (3x performance), Ractor (parallelism), and RBS (type signatures) came together. The &lt;a href="https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/" rel="noopener noreferrer"&gt;jump to 4.0&lt;/a&gt; brought ZJIT (a next-generation JIT compiler), Ruby Box (definition isolation), and Ractor improvements. Both bumps reflected Matz's judgment that the accumulated changes warranted a new major version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MINOR&lt;/strong&gt; increases every Christmas. Each December 25, a new stable version ships. API-incompatible changes can and do appear in MINOR releases — for example, libraries moving from default gems to bundled gems, meaning you need to add them to your Gemfile explicitly. This surprises people coming from strict semver ecosystems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TEENY&lt;/strong&gt; increases for bug fixes and security patches, released every two to three months. TEENY releases maintain API compatibility. The number can go above 9 — Ruby 3.2 reached 3.2.11.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Christmas release cadence is one of Ruby's distinctive traits. It means every year, there's a predictable moment when a new version appears and the maintenance window shifts.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Branch Lifecycle
&lt;/h2&gt;

&lt;p&gt;Ruby doesn't have LTS (Long-Term Support) versions. Instead, every stable branch goes through the same lifecycle:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Normal maintenance&lt;/strong&gt; — receives bug fixes and security fixes. Lasts about two years.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security maintenance&lt;/strong&gt; — receives only security fixes and critical build fixes. Lasts about one year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;End of life&lt;/strong&gt; — no further releases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A stable branch typically lives for about three years total. At any given time, we maintain three or four branches simultaneously.&lt;/p&gt;

&lt;p&gt;Here's the current state as of April 2026:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Branch Maintainer&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ruby 4.0&lt;/td&gt;
&lt;td&gt;Normal maintenance&lt;/td&gt;
&lt;td&gt;k0kubun&lt;/td&gt;
&lt;td&gt;Released 2025-12-25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby 3.4&lt;/td&gt;
&lt;td&gt;Normal maintenance&lt;/td&gt;
&lt;td&gt;nagachika&lt;/td&gt;
&lt;td&gt;Released 2024-12-25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby 3.3&lt;/td&gt;
&lt;td&gt;Security maintenance&lt;/td&gt;
&lt;td&gt;hsbt&lt;/td&gt;
&lt;td&gt;Released 2023-12-25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ruby 3.2&lt;/td&gt;
&lt;td&gt;End of life&lt;/td&gt;
&lt;td&gt;hsbt&lt;/td&gt;
&lt;td&gt;Released 2022-12-25&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And here's how the transition works each year:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;December 25: New stable version released (e.g., 3.4.0)
  → 4 branches under maintenance for ~3 months

March-April: Oldest branch reaches EOL
  → Back to 3 branches
  → Second-oldest branch moves to security maintenance

December 25: Next stable version released
  → Cycle repeats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see how this plays out concretely: in March 2025, Ruby 3.1 reached end-of-life with its final release 3.1.7, and Ruby 3.2 moved from normal maintenance to security-only maintenance. One year later, in March 2026, the same thing happened one version up — Ruby 3.2 reached end-of-life and Ruby 3.3 entered security maintenance. If the pattern holds, Ruby 3.3 will reach end-of-life in March 2027 when Ruby 3.4 moves to security maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Maintains What
&lt;/h2&gt;

&lt;p&gt;Ruby's branch maintenance isn't a solo effort, but it's not a large team either. Currently, four people handle all stable releases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nurse" rel="noopener noreferrer"&gt;nurse&lt;/a&gt;&lt;/strong&gt; (naruse) — maintains the development branch (master) and handles the Christmas release of each new stable version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/k0kubun" rel="noopener noreferrer"&gt;k0kubun&lt;/a&gt;&lt;/strong&gt; — maintains the latest stable version (currently Ruby 4.0). Releases every two to three months, sometimes faster when warranted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/nagachika" rel="noopener noreferrer"&gt;nagachika&lt;/a&gt;&lt;/strong&gt; — maintains Ruby 3.4 (normal maintenance).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/hsbt" rel="noopener noreferrer"&gt;hsbt&lt;/a&gt;&lt;/strong&gt; (me) — maintains the security maintenance versions (currently Ruby 3.3) and handles branches until EOL (Ruby 3.2, now concluded). Also handles release infrastructure and automation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This structure was formalized through a &lt;a href="https://bugs.ruby-lang.org/issues/20432" rel="noopener noreferrer"&gt;proposal in 2024&lt;/a&gt; to streamline the teeny release workflow. Before that, branch maintainer assignments were less systematic.&lt;/p&gt;

&lt;p&gt;I sometimes describe my coordination role as "release manager manager" — I don't just release my own branches, but also prepare templates for release announcements, ensure CDN publication works, purge negative caches, and automate as much of the process as possible so that other branch maintainers can ship releases with minimal friction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "Security Maintenance" Actually Means
&lt;/h2&gt;

&lt;p&gt;The term "security maintenance" suggests we only fix CVEs during this phase. In practice, the scope is broader than that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Security fixes&lt;/strong&gt; — any vulnerability with a CVE assignment gets patched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Critical build fixes&lt;/strong&gt; — if a supported OS releases a new version and Ruby can't build on it, that gets fixed. Software breaks if you leave it alone; keeping Ruby buildable on current platforms is part of the job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test fixes&lt;/strong&gt; — if CI platforms we test against cause test failures, we fix the test code to keep the suite green. This lowers the barrier for future emergency releases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is simple: if you're running Ruby 3.3 in production for the next year, it should keep building and running on the platforms you actually use. We won't add features or fix minor bugs, but we won't let it rot either.&lt;/p&gt;

&lt;p&gt;If you discover a security vulnerability in Ruby, please report it through &lt;a href="https://hackerone.com/ruby" rel="noopener noreferrer"&gt;HackerOne&lt;/a&gt;. For bundled gems, you can also use &lt;a href="https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability" rel="noopener noreferrer"&gt;GitHub's private vulnerability reporting&lt;/a&gt; on the gem's repository. We've been gradually migrating to GitHub for bundled gems since it allows the maintainers of each gem to handle the process directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  How a Release Gets Made
&lt;/h2&gt;

&lt;p&gt;For a normal teeny release, the process looks roughly like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Bug fixes land on master first, then get backported to stable branches. For the latest stable version, contributors actively triage and create patches, which the branch maintainer backports. For older branches, I cherry-pick fixes manually.&lt;/li&gt;
&lt;li&gt;The branch maintainer runs CI across all supported platforms and fixes anything that breaks.&lt;/li&gt;
&lt;li&gt;When ready, the maintainer tags the release. From that point, automation takes over — packages are built, tested, and published.&lt;/li&gt;
&lt;li&gt;The release announcement is posted on ruby-lang.org.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you've found a bug that's been fixed on master but hasn't made it into a stable release yet, you can request a backport. The process is documented in the &lt;a href="https://github.com/ruby/ruby/wiki/How-To-Request-Backport" rel="noopener noreferrer"&gt;How To Request Backport&lt;/a&gt; wiki page. In short: file a ticket on &lt;a href="https://bugs.ruby-lang.org/" rel="noopener noreferrer"&gt;bugs.ruby-lang.org&lt;/a&gt; with the commit hash in the subject (e.g., "Backport abcde123"), and the branch maintainer will pick it up. Generally, only bug fixes are eligible for backport — feature additions stay on master. Even better, you can open a pull request directly against the target branch (e.g., &lt;code&gt;ruby_3_4&lt;/code&gt;) on GitHub. This saves the branch maintainer time and gets your fix into the next release faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  What This Means for You
&lt;/h2&gt;

&lt;p&gt;If you're on &lt;strong&gt;Ruby 3.2&lt;/strong&gt;: upgrade now. There will be no more releases, not even for security issues.&lt;/p&gt;

&lt;p&gt;If you're on &lt;strong&gt;Ruby 3.3&lt;/strong&gt;: you have until March 2027, but only security fixes will be backported. Start planning your upgrade.&lt;/p&gt;

&lt;p&gt;If you're on &lt;strong&gt;Ruby 3.4 or 4.0&lt;/strong&gt;: you're in good shape. Normal maintenance continues.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;One exception&lt;/strong&gt;: if you're using Ruby packages provided by a Linux distribution such as RHEL, Ubuntu, or Debian, the upstream EOL dates above don't directly apply to you. Those distributions maintain their own packages and backport security fixes according to their own support lifecycle. Check your distribution's documentation for the actual support timeline of the Ruby version you're running.&lt;/p&gt;

&lt;p&gt;Check the official branch status page for the latest maintenance status: &lt;a href="https://www.ruby-lang.org/en/downloads/branches/" rel="noopener noreferrer"&gt;ruby-lang.org/en/downloads/branches/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For details on what changed in each version, the &lt;a href="https://github.com/ruby/ruby/blob/master/NEWS.md" rel="noopener noreferrer"&gt;NEWS file&lt;/a&gt; in Ruby's source tree is the authoritative reference. If you want to catch deprecation warnings in your application, try running with &lt;code&gt;ruby -w&lt;/code&gt; to enable all warnings including deprecations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Written in April 2026. Branch status and maintainer assignments may change over time.&lt;/li&gt;
&lt;li&gt;I'm a Ruby committer and branch maintainer. This reflects my perspective on how the process works in practice.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>programming</category>
      <category>opensource</category>
      <category>releases</category>
    </item>
    <item>
      <title>Should RubyGems/Bundler Have a Cooldown Feature?</title>
      <dc:creator>SHIBATA Hiroshi</dc:creator>
      <pubDate>Thu, 19 Mar 2026 01:45:21 +0000</pubDate>
      <link>https://forem.com/hsbt/should-rubygemsbundler-have-a-cooldown-feature-40cp</link>
      <guid>https://forem.com/hsbt/should-rubygemsbundler-have-a-cooldown-feature-40cp</guid>
      <description>&lt;p&gt;I'm Hiroshi Shibata (hsbt), a Ruby committer and the maintainer of RubyGems and Bundler.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Every major package manager is adding "cooldown" — a waiting period before you can install newly released packages. RubyGems/Bundler doesn't have one yet. I've been discussing whether we should add it. Short answer: yes, as an opt-in option, but cooldown alone isn't enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is a Cooldown?
&lt;/h2&gt;

&lt;p&gt;A cooldown prevents upgrading to a new package version until a certain time has passed since its release. The idea is simple: if a malicious package is published, the waiting period gives security researchers time to catch it before it reaches your &lt;code&gt;Gemfile.lock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://blog.yossarian.net/2025/11/21/We-should-all-be-using-dependency-cooldowns" rel="noopener noreferrer"&gt;William Woodruff's analysis&lt;/a&gt; found that 8 out of 10 supply chain attacks he examined had an exploitation window of less than one week. A 7-day cooldown could have prevented most of them.&lt;/p&gt;

&lt;p&gt;As Andrew Nesbitt summarizes in "&lt;a href="https://nesbitt.io/2026/03/04/package-managers-need-to-cool-down.html" rel="noopener noreferrer"&gt;Package Managers Need to Cool Down&lt;/a&gt;", from late 2025 into 2026, cooldown adoption has accelerated rapidly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Landscape
&lt;/h2&gt;

&lt;p&gt;Cooldown started in dependency update tools, then spread to package managers themselves. One complication: every tool picked a different config name — &lt;code&gt;minimumReleaseAge&lt;/code&gt;, &lt;code&gt;min-release-age&lt;/code&gt;, &lt;code&gt;npmMinimalAgeGate&lt;/code&gt;, &lt;code&gt;exclude-newer&lt;/code&gt;, &lt;code&gt;uploaded-prior-to&lt;/code&gt;, and so on. At least 10 different names exist. Polyglot developers, beware.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Update Tools
&lt;/h3&gt;

&lt;p&gt;Dependabot added a &lt;code&gt;cooldown&lt;/code&gt; block in July 2025. You can set different waiting periods per semver level, and security updates bypass the cooldown:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/dependabot.yml&lt;/span&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="na"&gt;updates&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;package-ecosystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bundler"&lt;/span&gt;
    &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/"&lt;/span&gt;
    &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;weekly"&lt;/span&gt;
    &lt;span class="na"&gt;cooldown&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;default-days&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;semver-major-days&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Renovate has &lt;code&gt;minimumReleaseAge&lt;/code&gt; (formerly &lt;code&gt;stabilityDays&lt;/code&gt;), with per-package and per-update-type granularity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minimumReleaseAge"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3 days"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"packageRules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"matchUpdateTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"major"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"minimumReleaseAge"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"7 days"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Package Managers
&lt;/h3&gt;

&lt;p&gt;pnpm was first, shipping &lt;code&gt;minimumReleaseAge&lt;/code&gt; in v10.16 (September 2025):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# pnpm-workspace.yaml&lt;/span&gt;
&lt;span class="na"&gt;minimumReleaseAge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1440&lt;/span&gt;  &lt;span class="c1"&gt;# 24 hours&lt;/span&gt;
&lt;span class="na"&gt;minimumReleaseAgeExclude&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;@myorg/*'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;npm followed with &lt;code&gt;min-release-age&lt;/code&gt; in CLI 11.x (February 2026). Bun added &lt;code&gt;minimumReleaseAge&lt;/code&gt; in October 2025, Deno added &lt;code&gt;--minimum-dependency-age&lt;/code&gt;. All major JavaScript runtimes now support cooldowns.&lt;/p&gt;

&lt;p&gt;On the Python side, uv extended its &lt;code&gt;--exclude-newer&lt;/code&gt; flag (originally for reproducible builds) to accept relative durations like &lt;code&gt;"7 days"&lt;/code&gt;. pip introduced &lt;code&gt;--uploaded-prior-to&lt;/code&gt; in 26.0 (January 2026), though pip only takes absolute timestamps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where Does Ruby Stand?
&lt;/h2&gt;

&lt;p&gt;RubyGems and Bundler have no cooldown feature. A community member opened a &lt;a href="https://github.com/ruby/rubygems/discussions/9113" rel="noopener noreferrer"&gt;Discussion on ruby/rubygems&lt;/a&gt; requesting one, and I discussed it with Ruby community members and the RubyGems team.&lt;/p&gt;

&lt;p&gt;What follows is my take on the discussion. I'm the RubyGems/Bundler maintainer, so keep that bias in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "guinea pig" problem
&lt;/h3&gt;

&lt;p&gt;My first concern. Cooldowns implicitly assume that &lt;em&gt;someone else&lt;/em&gt; will install the new version first and find problems. But if everyone enables cooldowns, nobody tries new releases during the waiting period — and the mechanism becomes useless. Better than nothing, probably. But it's a structural limitation of how OSS works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Delayed security fixes
&lt;/h3&gt;

&lt;p&gt;A strict cooldown also delays urgent security patches. Distinguishing a malicious release from a legitimate security fix automatically is extremely difficult. Cooldowns could actually &lt;em&gt;increase&lt;/em&gt; risk in some cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  The illusion of safety
&lt;/h3&gt;

&lt;p&gt;Software that hasn't been updated in 10 years may contain undiscovered vulnerabilities. Consider a gem that's been on RubyGems for years without updates — age tells you nothing about whether it's been audited. Time passing doesn't guarantee security. Cooldowns provide a sense of security, but a sense of security isn't the same as actual security.&lt;/p&gt;

&lt;h3&gt;
  
  
  Buying time for security researchers
&lt;/h3&gt;

&lt;p&gt;On the other hand — and this is the strongest argument for cooldowns — they buy time for people who are actually scanning packages.&lt;/p&gt;

&lt;p&gt;A concrete example: &lt;a href="https://mensfeld.pl/" rel="noopener noreferrer"&gt;Maciej Mensfeld&lt;/a&gt;, a member of the RubyGems security team and developer of Diffend (a supply chain security platform for Ruby). He has detected and reported over 20,000 malicious packages across ecosystems.&lt;/p&gt;

&lt;p&gt;In the RubyGems ecosystem specifically, he found over 700 typosquatting gems in 2020 (e.g., &lt;code&gt;rail&lt;/code&gt; targeting &lt;code&gt;rails&lt;/code&gt;), and in 2022, more than 400 malicious packages were removed. His RubyKaigi 2023 talk "&lt;a href="https://rubykaigi.org/2023/presentations/maciejmensfeld.html" rel="noopener noreferrer"&gt;RubyGems on the watch&lt;/a&gt;" covers these efforts.&lt;/p&gt;

&lt;p&gt;Today, the security team including Maciej reviews gems after release on rubygems.org. Gems found to contain malicious code are removed. A cooldown isn't just about waiting — it becomes effective when combined with this kind of scanning infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We're Considering
&lt;/h2&gt;

&lt;p&gt;My current thinking: offer cooldown as an opt-in option in the short term, pursue more technically effective measures longer term.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bundler Cooldown Option
&lt;/h3&gt;

&lt;p&gt;Enterprise environments want this. Dependabot and Renovate already have equivalent features, so it makes sense to support it at the Bundler level too.&lt;/p&gt;

&lt;p&gt;What the spec might look like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bundle update --cooldown 3&lt;/code&gt; (CLI option)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bundle config set cooldown 3&lt;/code&gt; (global config)&lt;/li&gt;
&lt;li&gt;Block syntax in the Gemfile for per-gem cooldowns&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gem install&lt;/code&gt; support for CI/CD environments like GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Opt-in, disabled by default. Users choose based on their own needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scanning and Metadata on RubyGems.org
&lt;/h3&gt;

&lt;p&gt;To make cooldowns actually useful, "has this gem been scanned?" matters as much as "has enough time passed?" On the rubygems.org side, we're considering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated scanning of new releases, with scan status published as index metadata&lt;/li&gt;
&lt;li&gt;Delays for high-risk releases (recent ownership changes, Trusted Publishing disabled)&lt;/li&gt;
&lt;li&gt;Letting RubyGems/Bundler reference this metadata to adjust behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's also been a suggestion for a "scanned" badge on rubygems.org — worth exploring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Beyond Cooldown
&lt;/h3&gt;

&lt;p&gt;Separately, there's discussion about sandboxing code execution during &lt;code&gt;gem install&lt;/code&gt;: &lt;a href="https://github.com/ruby/rubygems/issues/9138" rel="noopener noreferrer"&gt;ruby/rubygems#9138&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;RubyGems and Bundler recently landed a change that separates the download and install phases: &lt;a href="https://github.com/ruby/rubygems/pull/9381" rel="noopener noreferrer"&gt;ruby/rubygems#9381&lt;/a&gt;. This was for performance, but the separation opens the door to running SAST or other verification after download and before install — potentially more effective than cooldown alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Cooldown is not a silver bullet. But combined with server-side scanning and metadata on rubygems.org, it can be a meaningful layer of defense. We plan to offer it as an opt-in option in RubyGems/Bundler.&lt;/p&gt;

&lt;p&gt;If you have thoughts, join the &lt;a href="https://github.com/ruby/rubygems/discussions/9113" rel="noopener noreferrer"&gt;GitHub Discussion&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Written in March 2026. The ecosystem is evolving quickly — specifics may change.&lt;/li&gt;
&lt;li&gt;I'm a Ruby committer and the maintainer of RubyGems/Bundler. My perspective is shaped by that role.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>security</category>
      <category>supplychainsecurity</category>
      <category>packaging</category>
    </item>
  </channel>
</rss>
