---
title: "Rubyの最新バージョンは4.0.9｜正規表現の脆弱性修正・3系との違い・サポート期限（2026年11月）"
url: "https://www.issoh.co.jp/tech/details/10592/"
published: 2026-01-14
updated: 2026-11-01
categories: ["Ruby"]
publisher: "株式会社一創"
---

# Rubyの最新バージョンは4.0.9｜正規表現の脆弱性修正・3系との違い・サポート期限（2026年11月）

2026年11月1日時点で、Ruby公式サイトが安定版の最新として示しているのは4.0.9（2026年10月23日公開）です。前日の10月22日に定期リリースの4.0.8が出たばかりで、その翌日に3.4.12・3.3.13と同時に正規表現エンジンの修正版が出ました。GitLabが採番した4件のCVEの原因になった不具合で、外部入力から正規表現を組み立てるRubyアプリ全般が影響を受けます。この記事では、4.0系のリリース履歴と各シリーズの保守期限、今回の修正で更新が必要なアプリの見分け方、Ruby 3系から4系へ移るときに動かなくなるコード、10月12日公開の4.1.0-preview1で変わる挙動を整理します。根拠は公式の告知と、手元のRuby 4.0.6およびソースからビルドした4.1.0-preview1での実行結果です。

## まとめ：2026年11月時点のRubyバージョン選択と更新判断

- 安定版の最新は**Ruby 4.0.9**（2026年10月23日公開）。4.0.8（10月22日・定期）の翌日に出た正規表現の修正版。
- 4.0.9・3.4.12・3.3.13は、GitLabのCVE-2026-89078・93577・97229・110264の根本原因になった正規表現エンジン（Onigmo）の不具合を修正。`Regexp.new`・`Regexp.union`・`Regexp.compile`・式展開で外部入力から正規表現を組むアプリが対象で、`Regexp.timeout`では防げない。
- 4.1.0-preview1は2026年10月12日に公開された試用版。Ractorの改良が中心で、正式版の公開日は告知されていない。
- Ruby 3.2は2026年4月1日でEOL済み。3.3はセキュリティ修正のみで、EOL予定は2027年3月31日。3.4の最新は3.4.12（10月23日）。
- 新規開発は4.0系。既存のRuby 3系アプリは、まず同じシリーズの修正版（3.4.12か3.3.13）へ上げて穴を塞ぎ、削除された旧APIを洗い出してから4.0へ移る。

3系から4系への移行で止まる原因は、新機能よりも削除・変更された旧機能です。該当箇所は「Ruby 3のコードがRuby 4で壊れる箇所」で実行結果とともに挙げます。今回の正規表現の修正は同じシリーズ内のパッチ更新で受け取れるので、4.0への移行計画とは切り離して先に当ててください。

## Ruby 4.0.9の位置づけと4.0系のリリース履歴（4.0.0〜4.0.9）

### 4.0.0から4.0.9までの公開日と定期・臨時リリースの修正内容

| バージョン | 公開日        | 性格     | 主な内容                    |
| ----- | ---------- | ------ | ----------------------- |
| 4.0.0 | 2025-12-25 | メジャー   | Ruby Boxほか2機能           |
| 4.0.1 | 2026-01-13 | 定期     | Kernel#sleepの誤復帰を修正     |
| 4.0.2 | 2026-03-16 | 定期     | YJITの例外修正（Puma）         |
| 4.0.3 | 2026-04-21 | 臨時・脆弱性 | ERB 6.0.1.1のみ           |
| 4.0.4 | 2026-05-11 | 定期     | 通常のバグ修正                 |
| 4.0.5 | 2026-05-20 | 臨時・脆弱性 | CVE-2026-46727とビルド回帰の修正 |
| 4.0.6 | 2026-07-14 | 定期     | 通常のバグ修正                 |
| 4.0.7 | 2026-09-15 | 定期     | 通常のバグ修正                 |
| 4.0.8 | 2026-10-22 | 定期     | 通常のバグ修正                 |
| 4.0.9 | 2026-10-23 | 臨時・脆弱性 | 正規表現のコンパイル不具合を修正        |

4.0.0の主な追加機能はRuby Box・ZJIT・Ractor::Portです。4.0.3のERB 6.0.1.1への差し替えはCVE-2026-41316への対応です。各版の公開日はRuby公式の[リリース一覧](https://www.ruby-lang.org/en/downloads/releases/)、保守期限は[ブランチ別のメンテナンス状況](https://www.ruby-lang.org/en/downloads/branches/)で確認できます。4.0.3は内容がERB 6.0.1.1の差し替えだけで、公式告知も「Marshal.loadを信頼できないデータに対して呼び、かつerbとactivesupportを両方読み込んでいるアプリ」に限って更新を促しています。条件に当てはまらないアプリなら、急いで当てる種類のリリースではありません。

4.0.9は性格が違います。[4.0.9の公式告知](https://www.ruby-lang.org/en/news/2026/10/23/ruby-4-0-9-released/)は、GitLabのCVE-2026-110264が依存する正規表現コンパイルの不具合を直したリリースだと説明しています。前日の[4.0.8の告知](https://www.ruby-lang.org/en/news/2026/10/22/ruby-4-0-8-released/)は「バグ修正を含む定期更新」とだけ書いており、4.0.8の時点では4件のうち1件がまだ直っていません。4.0.8へ上げた直後の環境も、4.0.9へもう一度上げる必要があります。

### 「2か月ごと」の公称と、臨時リリースで実際にずれた番号の確認方法

公式はリリース告知のたびに「最新の安定版を直近のリリースから2か月ごとに出す」と書いています。2026年1月の4.0.1告知が予告していたのは「3月に4.0.2、5月に4.0.3、7月に4.0.4、9月に4.0.5」でした。実際には4月と5月にCVE対応の臨時リリースが割り込み、9月の番号は予告より2つ先の4.0.7になりました。4.0.7の告知が11月としていた4.0.8も、10月22日に前倒しで出ています。

番号の進みだけでは、自分の環境が修正を取り込めているかを判断できません。4.0系を本番で使うなら、リリース一覧ではなく[公式のセキュリティ告知](https://www.ruby-lang.org/en/security/)を購読してください。今回のように定期版の翌日に臨時版が出ることもあるため、パッチ番号を固定値で管理している依存表やCIの設定は、告知を見たその日に書き換える運用にしておきます。

## 4.0.9・3.4.12・3.3.13の正規表現修正とCVE 4件の影響範囲

この章で扱う4件のCVEはGitLabが採番したものです。2026年10月23日、Ruby公式は[GitLabのCVE 4件に関係する正規表現コンパイルの修正](https://www.ruby-lang.org/en/news/2026/10/23/regexp-fixes-for-gitlab-cves/)を告知しました。Rubyの正規表現エンジンOnigmoの不具合がGitLabサーバー上でのリモートコード実行に使える、という報告を受けて、GitLabが4件のCVEを採番したものです。Ruby側は4.0.9・3.4.12・3.3.13にすべての修正を入れました。

### CVE-2026-89078ほか4件の内容と修正を含む最初の版

| GitLabのCVE      | 不具合                      | 修正を含む最初の版               | GitLab修正版 |
| --------------- | ------------------------ | ----------------------- | --------- |
| CVE-2026-89078  | 選択肢を含むパターンの解析失敗後の二重解放    | 4.0.0 ／ 3.4.12 ／ 3.3.13 | 19.4.1    |
| CVE-2026-93577  | コンパイル後パターンのサイズの整数オーバーフロー | 4.0.8 ／ 3.4.12 ／ 3.3.13 | 19.4.1    |
| CVE-2026-97229  | 同じ整数オーバーフロー（CI・CD側）      | 4.0.8 ／ 3.4.12 ／ 3.3.13 | 19.4.2    |
| CVE-2026-110264 | 繰り返しの多いパターンで内部IDがあふれる    | 4.0.9 ／ 3.4.12 ／ 3.3.13 | 19.5.1    |

CVE-2026-97229はCI/CD側の正規表現処理に関係する整数オーバーフローです。4.0系は二重解放の修正を4.0.0の時点で取り込んでおり、整数オーバーフローは4.0.8、内部IDのあふれは4.0.9で直りました。3.4系と3.3系は3件とも今回の版でまとめて直っています。つまり**4.0.8以前・3.4.11以前・3.3.12以前はどれも1件以上が未修正**です。

CVE番号はGitLabの採番で、Ruby側は現時点で自前のCVEを申請していません。公式は、扱いを検討して申請する場合は告知ページを更新するとしたうえで、それまでは脆弱性スキャナー等での追跡にGitLabの番号を使うよう案内しています。DependabotやTrivyの結果でRuby本体が指摘されない場合でも、未修正でないとは限りません。`ruby -v`の版で判断してください。

### 外部入力から正規表現を組むコードの影響範囲と依存gemの調査方法

公式によれば、不具合に到達するのは攻撃者が制御できる文字列から正規表現をコンパイルする場合だけです。対象のAPIは`Regexp.new`・`Regexp.union`・`Regexp.compile`と、`/#{input}/`のような正規表現リテラルへの式展開の4つで、開発者が自分で書いた正規表現だけを使うアプリは影響を受けないと明記されています。

検索条件・URLルーティング・ログのフィルタ・入力チェックのルールを、利用者や管理画面から受け取った文字列で組み立てている箇所が典型です。リポジトリ内の該当箇所は次のgrepで拾えます。

```
# Regexp.new／union／compile の呼び出し
$ git grep -nE 'Regexp[.](new|union|compile)' -- '*.rb' '*.erb'

# 正規表現リテラル内の式展開（誤検知を含むので目で確かめる）
$ git grep -nE '/[^/]*#[{][^}]+}[^/]*/[imxo]*' -- '*.rb'

# 使っているRubyが修正版か（4.0.9／3.4.12／3.3.13 以上）
$ ruby -e 'fixed = {"4.0" => "4.0.9", "3.4" => "3.4.12", "3.3" => "3.3.13"}[RUBY_VERSION[/\A\d+\.\d+/]]; puts fixed.nil? ? "表にないシリーズ（EOLなら更新が必要）" : Gem::Version.new(RUBY_VERSION) >= Gem::Version.new(fixed) ? "修正済み" : "要更新：#{fixed}以上"'
```

自社コードで見つからなくても、依存gemが内部で`Regexp.new`を呼んでいることがあります。`bundle list --paths`で依存gemの展開先を一覧にし、そのディレクトリにも同じgrepを掛けてください。Railsアプリでの具体的な洗い出し手順と、検索機能・ルーティング周りで見つかりやすい書き方は[Rubyの脆弱性：正規表現エンジン4件の修正版とRailsでの影響箇所の洗い出し](https://www.issoh.co.jp/tech/details/19129/)で詳しく扱っています。

### Regexp.timeoutと入力長の制限ではコンパイル時の不具合を塞げない理由

Ruby 3.2で入った`Regexp.timeout`は、マッチングに時間がかかりすぎる正規表現（ReDoS）を打ち切る仕組みです。今回の不具合はマッチングではなく**コンパイル**の段階で起きるメモリ破壊なので、公式も`Regexp.timeout`では防げないと明記しています。入力されたパターンの長さを制限する対策も、短いパターンで発動しうるため確実な防御にならないとしています。

更新できない場合の回避策として公式が挙げているのは、信頼できない入力から正規表現をコンパイルしないことだけです。部分一致の検索なら`String#include?`や`start_with?`、複数語の検索ならDB側の`LIKE`やプレースホルダ付きのクエリに置き換えられます。`Regexp.escape`で包んだ入力が安全かどうかは告知に書かれていないため、エスケープ済みであることを理由に更新を見送るのはやめてください。

### セキュリティ保守中の3.3.13が例外的に出た理由とアプリ更新の判断

3.3はセキュリティ保守の段階で、通常はセキュリティ修正しか入りません。[3.3.13の告知](https://www.ruby-lang.org/en/news/2026/10/23/ruby-3-3-13-released/)は、今回の正規表現修正を「例外として」入れたと説明しています。同じ版には標準添付gemのresolvを0.3.2へ上げる修正（CVE-2026-80212・80213）も入っており、8月の告知で個別に更新を促されていたresolvも本体の更新でまとめて修正される形です。[3.4.12の告知](https://www.ruby-lang.org/en/news/2026/10/23/ruby-3-4-12-released/)は、正規表現の修正とその他のバグ修正を含むとしています。

判断は単純です。外部入力から正規表現を組む箇所が1つでもあるアプリは、同じシリーズの修正版へ即日上げます。該当箇所が見つからないアプリも、依存gemまで調べ切るより更新のほうが安く済むので、次のデプロイで上げてください。パッチ更新なので、4.0.7から4.0.9、3.4.11から3.4.12への移行でAPIの非互換は告知されていません。GitLabをセルフホストしている場合は、Rubyとは別にGitLab本体を19.4.1・19.4.2・19.5.1以降の該当版へ上げる必要があります。

## Ruby 4.1.0-preview1の変更点（2026年10月12日公開）と4.0との差

[4.1.0-preview1の公式告知](https://www.ruby-lang.org/en/news/2026/10/12/ruby-4-1-0-preview1-released/)は、4.1の柱を「Ractor local GC、YJITのWindows対応、autoload\_relative」と要約しています。告知のtarballをsha256で照合してからソースでビルドし、4.0.6と同じコードを両方で実行して違いを確かめました。

### Ractor local GCの回収方式とRactorの所有権・例外の挙動変更

GCはRactorごとに自分のヒープを自分のスレッドで回収する方式になり、他のRactorを止める全体停止のGCは、明示的な全体GCの要求、共有可能オブジェクトの増加、終了したRactorのヒープ回収など、全体回収が必要な場合に実行されます。公式は、割り当ての多いRactorプログラムが「forkしたプロセスのようにスケールする」と説明しています。

そのぶん、4.0では通っていたコードが例外になります。手元で差が出たのは次の4点です。

```
$ ruby -e 'r = Ractor.new { 42 }; p r.value; r.value'
# 4.0.6：2回目も42を返す
# 4.1.0-preview1：2回目は Ractor::Error「The value was already taken」

$ ruby -e 'p Ractor.new { String.class_eval { def shout = upcase }; :ok }.value'
# 4.0.6：:ok
# 4.1.0-preview1：Ractor::IsolationError「can not modify String because it is created by another Ractor」

$ ruby -e 'port = Ractor::Port.new; r = Ractor.new { :done }; r.monitor(port); p port.receive'
# 4.0.6：:exited
# 4.1.0-preview1：[#<Ractor:#2 -e:1 terminated>, :exited]
```

2つ目の例外がいちばん影響の大きい変更です。4.1ではクラスやモジュールを変更できるのは作成したRactorだけになり、起動時やrequireで読み込んだ定義はすべてメインRactorの所有になります。メイン以外のRactorからのモンキーパッチは通りません。ほかにも、メイン以外のRactorで`at_exit`を呼ぶとRactor::IsolationErrorになることを確認しました。なお4.1.0-preview1でも、Ractorを生成すると「Ractor API is experimental」の警告が出ます。実験的扱いはまだ外れていません。

### autoload\_relativeなど追加されたメソッドとpreview1の実行結果

| 追加                        | preview1での実行結果              |
| ------------------------- | --------------------------- |
| Kernel#autoload\_relative | 呼び出し元ファイル基準でautoload        |
| Module#descendants        | `A.descendants` → \[B, C\]  |
| Integer#bit\_count        | `255.bit_count` → 8         |
| Range#clamp               | `(1..10).clamp(3,5)` → 3..5 |
| ENV.fetch\_values         | 未定義の名前はKeyError             |
| String#tr（Hash指定）         | Hash指定で`"heLL0"`            |
| MatchData#integer\_at     | `"12-34"`の2番目 → 34          |
| pack／unpackのR・r           | LEB128。300 → `"\xAC\x02"`   |

Module#descendantsの例では、BがAを、CがBを継承しています。String#trの例は`"hello".tr({"l" => "L", "o" => "0"})`で、結果は`"heLL0"`です。MatchData#integer\_atの例は正規表現`/(\d+)-(\d+)/`で`"12-34"`にマッチした結果です。

実務で効くのはautoload\_relativeです。`require_relative`と同じく呼び出し元のファイルを基準にパスを解決するので、同じディレクトリのファイルを遅延読み込みするために絶対パスを組み立てたり`$LOAD_PATH`を書き換えたりする必要が無くなります。同じコードを4.0.6で動かすと、新設メソッドはNoMethodError、String#trへのHash指定とpackのR指定はArgumentErrorで止まります。これらの4.1専用の機能をgemの中で使う場合は`required_ruby_version`を4.1以上にしてください。

### 4.1で動かなくなるコードと例外の種類（preview1で実行確認）

- **Symbol#to\_sが凍結文字列を返す**：`:abc.to_s << "d"`は4.0.6では通り、4.1.0-preview1ではFrozenError。
- **Regexpはリテラル以外も凍結**：`Regexp.new("a").frozen?`が4.0.6のfalseからtrueに変わった。
- **ObjectSpace.\_id2refの削除**：4.1.0-preview1ではNoMethodError。
- **to\_setへの引数**：4.0.6では非推奨警告だけだった`[1, 2].to_set(Set)`がArgumentError。
- **prismがbundled gemへ**：Bundler配下で`require "prism"`すると、4.0.6はPrism 1.8.1を読み込むが、4.1.0-preview1はLoadError。Gemfileにprismを足すか、実行中のパーサーで足りるなら新設の`Ruby::Prism`を使う。
- **net-ftpとnet-popがbundled gemから外れた**：`require "net/ftp"`が4.1.0-preview1ではLoadError。rubygems.orgからは引き続き入れられる。

削除予告も始まっています。モジュール内の`alias`がObjectへのフォールバックで元メソッドを見つける書き方は、4.1.0-preview1の`-W:deprecated`で「Ruby 4.3で削除」の警告が出ました。`Hash.ruby2_keywords_hash?`は4.5で、`Module#ruby2_keywords`と`Proc#ruby2_keywords`は4.4で削除予定です。

### YJITのWindows対応に必要なビルド条件とZJITの開発の現状

YJITはWindows（mswin、x64）に対応しました。`win32\configure.bat --enable-yjit`でビルドし、rustcのx86\_64-pc-windows-msvcターゲットが必要です。対象はリリースビルドだけで、MinGWは対象外です。RubyInstallerはMinGW系の配布なので、Windowsで4.1のYJITを使うにはmswin版を自分でビルドする必要があります。

ZJITについては、preview1の告知にも、tarballに同梱のNEWS.mdにも記述がありません。preview1の公開後、2026年10月19日のコミットで開発ブランチの[NEWS.md](https://github.com/ruby/ruby/blob/dd69f1031aaa58b095010ba93c24f6f25fa5ced9/NEWS.md)にZJITの現状が追記されました。内容は「多くのベンチマークでYJITより速くなったが、4.1.0のプレビュー時点では大きなベンチマークやアプリケーションでYJITより遅いことがある」で、正式版を待つよう求めています。今回ビルドした4.1.0-preview1はrustcを入れずにビルドしたためJITが含まれず、YJITとの性能比較はしていません。公式がこう書いている以上、4.1の正式版が出て自分のアプリで測るまでは、本番のJITはYJITのままにしておくのが安全です。

## Ruby 3系とRuby 4系の違い：Ruby Box・ZJIT・Ractor::Port

### Ruby Box：RUBY\_BOX=1で有効になる定義の隔離

Ruby Boxは[Ruby 4.0.0の公式告知](https://www.ruby-lang.org/en/news/2025/12/25/ruby-4-0-0-released/)で発表された実験的機能で、box（`Ruby::Box`）の中で読み込んだ定義を外側から隔離します。公式は、テスト同士の汚染防止や、同じプロセス内で依存の新旧を並走させる用途を挙げています。環境変数RUBY\_BOX=1を指定しないと使えず、4.1.0-preview1でも同じです。

```
$ ruby -e 'Ruby::Box.new'
-e:1:in 'Ruby::Box#initialize': Ruby Box is disabled. Set RUBY_BOX=1 environment variable to use Ruby::Box. (RuntimeError)

$ RUBY_BOX=1 ruby -e 'box = Ruby::Box.new; box.eval("class String; def shout = upcase; end"); p "hi".respond_to?(:shout)'
ruby: warning: Ruby::Box is experimental, and the behavior may change in the future!
false
```

box内で足したString#shoutが外側では未定義のまま、というのが隔離の効き方です。ここで確認できるのは定義の隔離だけなので、本番で使うなら依存ライブラリとの互換性や障害時の挙動を別に検証してください。

### ZJITとYJITの開発状況と4.0で本番に使うJITの選択基準

ZJITはYJITの次世代として開発されているJITコンパイラで、`--zjit`を付けたときだけ有効になります。ソースからZJIT付きでビルドするにはRust 1.85.0以降が必要です。4.0.0の公式告知は「ZJITはインタプリタより速いが、まだYJITほどではない」とし、当面は本番投入を控えるよう書いています。4.0系で本番を速くしたい場合の選択肢は`--yjit`です。JITの先にあるAOTコンパイルの動きは[Spinelとは？MatzのRuby AOTコンパイラの仕組みと使い方、書けないRubyを実測で整理](https://www.issoh.co.jp/tech/details/12090/)で扱っています。

### Ractor::Port、Set・Pathnameのコア化と文法の細部

Ractorにはメッセージの窓口となる`Ractor::Port`が加わり、終了待ちは`Ractor#join`と`Ractor#value`に整理されました。SetとPathnameはコアクラスになってrequireなしで使え、Set#inspectは`Set[1, 2]`という表記に変わっています。文法面では、行頭の`&&`や`||`が前の行の続きとして扱われるようになりました。Array#rfindの追加や、inspectで表示するインスタンス変数を絞る`instance_variables_to_inspect`も4.0からです。

## Ruby 3のコードがRuby 4で壊れる箇所（4.0.6で実行確認）

### Kernel#openのパイプ起動削除と移行時の例外・置き換え先

先頭に`|`を付けたファイル名でプロセスを起動する記法は、Kernel#openとIOのクラスメソッドから削除されました。厄介なのはNoMethodErrorにならないことです。手元の4.0.6では、パイプ記法がそのままファイル名として扱われました。

```
$ ruby -e 'open("|echo hi"){|f| p f.read}'
-e:1:in 'File#initialize': No such file or directory @ rb_sysopen - |echo hi (Errno::ENOENT)

$ ruby -e 'IO.readlines("|echo hi")'
-e:1:in 'IO.readlines': No such file or directory @ rb_sysopen - |echo hi (Errno::ENOENT)
```

Errno::ENOENTはファイルが無いときの一般的な例外なので、ログだけではパスの設定ミスと区別が付きません。移行前に`open("|`や`IO.readlines("|`をgrepし、`IO.popen`へ置き換えておくのが確実です。

### Ractor.yieldとRactor#takeの削除後の値の受け渡し方法

Ruby 3系のRactorのサンプルは、yieldとtakeで値を受け渡す書き方が主流でした。4.0ではこの2つが無くなり、手元の4.0.6でも`Ractor.respond_to?(:yield)`と`Ractor.instance_methods.include?(:take)`はどちらもfalseです。書き換え先はRactor::Port、結果を1回受け取るだけならRactor#valueです。4.1ではそのRactor#valueも2回目が例外になるので、値は最初の呼び出しで変数に受けておきます。

### \*nilとSet#inspectの挙動変更が既存テストに与える影響

`*nil`はnil.to\_aを呼ばなくなりました。手元の4.0.6でNilClass#to\_aを再定義してから`[*nil]`を評価しても、返るのは空配列です。Set#inspectの表記変更と合わせて、inspect結果を文字列で比較しているテストは落ちます。削除済みAPIの検出は[RuboCopとは？読み方・使い方と-a/-Aの違い、.rubocop.yml設定](https://www.issoh.co.jp/tech/details/3570/)で扱っている静的解析へ組み込んでおくと、定型作業に落とせます。

### Net::HTTPのContent-Type自動設定廃止と標準ライブラリの整理

本文付きのリクエストでContent-Typeが未指定のとき、Net::HTTPが`application/x-www-form-urlencoded`を自動で付ける挙動が廃止されました。この既定値は送信の瞬間に付く仕組みだったので、リクエストを組み立てた直後のヘッダーを見ても新旧の差は出ません。次のように送信処理をStringIOへ流してから確かめます。

```
$ ruby -e 'require "net/http"; req = Net::HTTP::Post.new("/"); req.body = "a=1"; require "stringio"; io = StringIO.new; def io.continue_timeout; nil; end; req.exec(io, "1.1", "/"); p req["Content-Type"]'
nil
```

手元では4.0.6と4.1.0-preview1がnil、macOS付属のRuby 2.6.10が`"application/x-www-form-urlencoded"`を返しました。フォーム形式でPOSTしている箇所は`req.content_type = "application/x-www-form-urlencoded"`のように明示します。標準ライブラリでは、CGIがエスケープ系（`cgi/escape`）だけの提供になり、SortedSetも使えなくなりました。4.0.6では`SortedSet`がNameError、`require "set/sorted_set"`がLoadErrorです。使い続けるならsorted\_set gemを入れて明示的にrequireします。

本番での移行事例としては、マイベストが3.3.1から4.0.2へ上げた経緯を[Zennで公開](https://zenn.dev/mybest%5Fdev/articles/e1d2fa750b7ef1)しています。4.0への更新で自動テストはほぼ落ちず、待ったのはDatadogのトレースgem（dd-trace-rb）の4.0対応だけでした。一方で同社の計測では平均メモリが3.4GBから4.2GBへ増えています。依存gemの対応状況とメモリの上限は、更新前に確認する項目に入れてください。今回の正規表現の修正のように、シリーズ内のパッチ更新が月に何度も来る状態を自社だけで追い切れない場合や、稼働中システムのRuby更新を計画から任せたい場合は、[保守運用・内製化支援](https://www.issoh.co.jp/service/system/maintenance/)で相談を受けています。

## Rubyの各シリーズのサポート状況とEOL日程、LTSが無い保守体系

| シリーズ | 状態       | 最新                        | 通常保守の終了    | EOL            |
| ---- | -------- | ------------------------- | ---------- | -------------- |
| 4.1  | プレビュー    | 4.1.0-preview1 2026-10-12 | 未定         | 未定             |
| 4.0  | 通常保守     | 4.0.9（2026-10-23）         | 未定         | 未定             |
| 3.4  | 通常保守     | 3.4.12（2026-10-23）        | 未定         | 未定             |
| 3.3  | セキュリティ保守 | 3.3.13（2026-10-23）        | 2026-04-01 | 2027-03-31（予定） |
| 3.2  | EOL      | 3.2.11（2026-03-27）        | 2025-04-01 | 2026-04-01     |

Rubyの保守は「通常保守（バグ修正と脆弱性修正）」「セキュリティ保守（脆弱性修正のみ）」「EOL（修正なし）」の3段階です。Node.jsのような長期サポート版の枠は無く、**Rubyに「LTS」という区分はありません**。日付は公式のブランチ表で確認してください。公式自身がこの表を暫定の予定と断っています。3.2のEOLを「2026年3月末」、3.4の公開日を「12月24日」とするまとめサイトもありますが、公式の記載はそれぞれ2026年4月1日、2024年12月25日です。

3.2以前には脆弱性修正も来ません。今回の正規表現の不具合も3.2系には修正版が出ておらず、3.2.11のまま外部入力から正規表現を組んでいるアプリは塞ぐ手段が更新しかありません。動いているからという理由で据え置く選択肢は無いと考えてください。3.3は2027年3月末まで猶予がありますが、来るのはセキュリティ修正だけです。4.0の非互換をすぐに吸収できない場合は、通常保守が続く3.4系へ上げてから4.0を目指してください。

## バージョン確認と4.0.9への更新手順（rbenv・Docker・CI）

### rbenvとRVMでの4.0.9への切り替えと版を固定した設定の更新

`ruby -v`はパッチ版・リリース日・リビジョンまで表示するので、どのパッチかまで一度で分かります。

```
$ ruby -v
ruby 4.0.6 (2026-07-14 revision 03b6d3f889) +PRISM [x86_64-darwin23]

$ rbenv install --list | grep -E '^[[:space:]]*4[.]0[.]'
$ rbenv install 4.0.9
# 以下は目的に応じてどちらか一方を実行
# ユーザー全体の既定を切り替える場合
$ rbenv global 4.0.9

# プロジェクトのディレクトリだけ切り替える場合
$ rbenv local 4.0.9
$ ruby -v

# 3系に留まる場合は同じシリーズの修正版へ
$ rbenv install 3.4.12   # または 3.3.13
```

rbenvで選べる版は、実体であるruby-buildの定義ファイルに依存する仕組みです。導入と更新の手順は[rbenvとは？Rubyバージョン管理の仕組みとRVMとの違い・1.3系の導入手順](https://www.issoh.co.jp/tech/details/7474/)にまとめています。RVMなら`rvm install 4.0.9`のあと`rvm use 4.0.9 --default`で既定を切り替えます。`.ruby-version`とGemfileの`ruby`指定、Dockerfileの`FROM`行に版を固定している場合は、3か所とも書き換えてからデプロイしてください。

### インストールに失敗するときの原因（ruby-buildとmacOS 26）

4.0.9が入らないときは、まずruby-buildの版を見ます。[ruby-build v20261023](https://github.com/rbenv/ruby-build/releases/tag/v20261023)が4.0.8・4.0.9・3.4.12・3.3.13の定義を一度に追加したので、それより古いruby-buildでは次のように止まります。

```
$ ruby-build --version
ruby-build 20261013
$ ruby-build 4.0.9 ~/.rbenv/versions/4.0.9
ruby-build: definition not found: 4.0.9

# Homebrewで入れている場合
$ brew upgrade ruby-build
```

v20261023はOpenSSL 4系を、対応するRubyで使えるようにする変更も含んでいます。4.0.7のときも同じで、定義はv20260915で追加されたため、手元のv20260902では「definition not found」で止まることを確認しています。

macOS 26に、macOS 27のSDKを含むCommand Line Tools 27（Xcode 27）を入れた環境では、定義があってもビルドが途中で落ちます。報告された[ruby-buildのissue #2640](https://github.com/rbenv/ruby-build/issues/2640)では、`linking miniruby`の直後に`builtin_binary.rbbin`の生成でSegmentation fault: 11が出ています。SDKが`dup3()`と`pipe2()`を宣言しているためconfigureが「使える」と判定し、実行時にはmacOS 26に存在しない関数を呼ぶのが原因です。ruby-build v20260916は、macOS 27より古いホストでこの2関数を無効にしてビルドするよう修正しました。PRには「リリース済みのtarballは壊れたまま」とあるので、ruby-buildを通さずtarballから手でビルドする場合は、configureに`ac_cv_func_dup3=no ac_cv_func_pipe2=no`を渡します。

### Docker・CI・Windowsでの入手と4.1.0-preview1の試し方

Docker公式イメージには、2026年11月1日時点でruby:4.0.9・ruby:3.4.12・ruby:3.3.13のタグがあり、ruby:4.1.0-preview1（slim・alpine・trixie・bookworm派生を含む）も配信されています。ローカルに入れずに版を確かめたり4.1の挙動を見たりするなら、次の1行で足ります。

```
$ docker run --rm ruby:4.0.9 ruby -v
$ docker run --rm ruby:4.1.0-preview1 ruby -e 'p :abc.to_s.frozen?'
```

`FROM ruby:4.0`のようにマイナー版までのタグを使っているイメージは、再ビルドしないと中身が古いまま残ります。`docker build --pull`で基底イメージを取り直してください。ruby-buildはv20261013で4.1.0-preview1の定義を追加しました。GitHub Actions向けのruby/setup-rubyも、バージョン一覧（ruby-builder-versions.json）に4.0.8・4.0.9と4.1.0-preview1を含んでいます。対応するUbuntu・macOSのCIジョブに4.1.0-preview1を追加し、テストで非互換を確認できます。ruby/setup-rubyのWindows向け配布にはプレビュー版が含まれないため、OSも組み合わせたマトリクスではWindowsとの組み合わせを除外してください。なおsetup-rubyのREADMEは、プレビュー版よりruby-headでテストすることを勧めています。Windowsでは、RubyInstallerプロジェクトがRubyInstaller-4.0.9-1・3.4.12-1・3.3.13-1を本家と同じ2026年10月23日に公開しました。4.0.8に対応するRubyInstallerは出ていないので、Windowsでは4.0.7から4.0.9へ直接上げます。開発環境の組み立ては[ruby on rails を vscode で開発する環境構築【2026年版】Ruby LSP・デバッグ・Dev Container](https://www.issoh.co.jp/tech/details/2878/)が参考になります。

Ruby本体を上げたら、同梱gemの脆弱性告知も確認してください。2026年8月27日の公式告知は、resolvで名前解決するアプリに対し、Ruby 4.0・3.4ではresolv 0.7.2、3.3では0.3.2への更新を推奨しています。4.1.0-preview1に同梱されるRubyGemsとBundlerの版は4.1.0.beta2です。Bundler 4系のコマンドの変化は[gemとBundlerの使い方｜Bundler 4系で変わったコマンドとGemfileの書き方](https://www.issoh.co.jp/tech/details/4221/)で確認できます。

## 次に来るRubyのリリース：4.0系の次のパッチと4.1.0正式版の時期

4.0.7の告知が11月としていた4.0.8は10月22日に出て、翌日に4.0.9が続きました。4.0.8・4.0.9の告知には次のパッチ版の予定が書かれていないため、4.0.10の時期は2026年11月1日時点で未告知です。「2か月ごと」の公称どおりなら12月以降になりますが、4.0系ではすでに臨時リリースが3回（4.0.3・4.0.5・4.0.9）入っているので、日付で待つより告知を見て動くほうが確実です。

4.1.0の正式版の日付も告知されていません。手掛かりは過去の公開日で、3.4.0が2024年12月25日、4.0.0が2025年12月25日と、マイナー版以上は12月25日に出す慣例が続いています。4.0.0では2025年11月17日にpreview2、12月18日にpreview3が出て、その1週間後が正式版でした。4.1の正式版を待つあいだは、preview1で非互換を洗い出しておくのが現実的です。

## よくある質問

Rubyの版選びと、2026年10月の正規表現の修正版について、よく調べられている質問に答えます。

### Rubyの最新バージョンは？

2026年11月1日時点の最新安定版は4.0.9（2026年10月23日公開）です。旧シリーズの最新は3.4.12と3.3.13（どちらも同日公開）、プレビュー版は4.1.0-preview1（2026年10月12日）です。4.0.9の前日には定期リリースの4.0.8が出ていますが、正規表現の修正が1件足りないため、4.0系は4.0.9を使ってください。

### Ruby 4.0.9へはすぐ更新すべきですか？

外部入力から`Regexp.new`・`Regexp.union`・`Regexp.compile`や式展開で正規表現を組むコードがあるなら、即日更新してください。GitLabではこの不具合がリモートコード実行につながると報告されており、`Regexp.timeout`や入力長の制限では防げません。該当箇所が無いアプリでも、依存gemが内部で使っている可能性があるので、次のデプロイで4.0.9（3系なら3.4.12か3.3.13）へ上げるのが安全です。

### Ruby 3と4はどこが違う？

4.0で加わった主な機能はRuby Box、ZJIT、Ractor::Portで、Ruby BoxとZJITは既定で無効です。移行で影響が出るのは削除・変更された機能のほうで、Kernel#openのパイプ起動、Ractor.yieldとRactor#take、\*nilがnil.to\_aを呼ぶ挙動、Net::HTTPのContent-Type自動設定が無くなりました。

### RubyにLTS版はありますか？

ありません。公式の分類は通常保守・セキュリティ保守・EOLの3段階で、シリーズごとに期限が決まります。今回の3.3.13のように、セキュリティ保守のシリーズへ例外的に修正が入ることはありますが、期間を延ばす扱いではありません。

### Ruby 3.3はいつまで使えますか？

3.3は2026年4月1日に通常保守を終え、現在はセキュリティ修正だけが提供されています。EOL予定は2027年3月31日です。3.3系を使い続けるなら最低でも3.3.13へ上げてください。バグ修正が必要なら3.4系か4.0系へ移ります。

## 関連記事

- [Rubyの脆弱性：正規表現エンジン4件の修正版とRailsでの影響箇所の洗い出し](https://www.issoh.co.jp/tech/details/19129/)：4.0.9・3.4.12・3.3.13で直った不具合の詳細と、Railsでの調べ方
- [rbenvとは？Rubyバージョン管理の仕組みとRVMとの違い・1.3系の導入手順](https://www.issoh.co.jp/tech/details/7474/)：4.0.9への切り替えに使うバージョン管理の導入
- [gemとBundlerの使い方｜Bundler 4系で変わったコマンドとGemfileの書き方](https://www.issoh.co.jp/tech/details/4221/)：Ruby更新とあわせて確認するgem管理
- [Spinelとは？MatzのRuby AOTコンパイラの仕組みと使い方、書けないRubyを実測で整理](https://www.issoh.co.jp/tech/details/12090/)：JITの先にあるAOTコンパイルの選択肢
- [RuboCopとは？読み方・使い方と-a/-Aの違い、.rubocop.yml設定](https://www.issoh.co.jp/tech/details/3570/)：削除済みAPIを静的解析で拾う方法

---

出典: [Rubyの最新バージョンは4.0.9｜正規表現の脆弱性修正・3系との違い・サポート期限（2026年11月）](<https://www.issoh.co.jp/tech/details/10592/>)（株式会社一創）
