Ruby 正規表現 脆弱性として、2026年10月23日に Ruby の開発チームがセキュリティ更新を実施しました。問題は、Ruby が内部で使う正規表現エンジン Onigmo にあり、細工した正規表現パターンをコンパイルするとメモリが破壊され、最悪の場合リモートコード実行(RCE)に至りうるというものです。見つけたのは GitLab で、自社の「GitLab」サーバーで RCE に悪用されうるとして報告しました。ただし、影響を受けるのは特定の書き方をしているアプリだけで、普通に正規表現を使っているだけなら対象外です。依存する処理系の脆弱性がどう伝わるかの全体像は、サプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説にまとめています。この記事は、何が起きたか・自分が影響するかの見分け方・仕組み・直し方を、Ruby と GitLab の一次情報で整理します。

ONIGMO REGEXP何が起きたか

正規表現のコンパイル時にメモリが壊れ、RCE になりうる

  1. 発見

    GitLab が Onigmo の不具合を報告

    自社サーバーで RCE に悪用されうるとして

  2. 先行

    GitLab がバンドル Ruby を先に修正

    GitLab 19.4.1 / 19.4.2 / 19.5.1

  3. 10/23

    Ruby 各系が修正版を公開

    4.0.9 / 3.4.12 / 3.3.13(3.3 は例外対応)

  4. CVE

    番号は GitLab が申請

    Ruby 側は脆弱性扱いを未決・独自 CVE 未申請

  5. 現状

    実環境での悪用は確認なし

    とはいえ版を上げるのが確実策

出典: ruby-lang.org『Regexp compilation fixes related to GitLab's CVEs』(2026-10-23)、GitLab の CVE 記録(2026-10-23 確認)

30秒でわかる

  • ・何が:Ruby の正規表現エンジン Onigmo のコンパイル処理に整数オーバーフロー・二重解放。細工パターンでメモリ破壊〜RCE
  • ・誰が対象:攻撃者の入力から正規表現を作るアプリだけ(Regexp.new//#{input}/ など)。固定パターンだけなら対象外
  • ・直し方:Ruby を 4.0.9 / 3.4.12 / 3.3.13 以上へ。すぐ上げられないなら信頼できない入力をパターンにしない
  • ・CVE:4件はすべて GitLab が申請。Ruby 側は脆弱性扱いを未決で、追跡は当面 GitLab 番号で

まずやること

・ruby -v が 4.0.9 / 3.4.12 / 3.3.13 以上か確認し、低ければ更新する
・Regexp.new Regexp.union Regexp.compile や /#{...}/ に、外部から来た文字列を渡していないか探す
・すぐ上げられないときは、信頼できない入力から正規表現を作る箇所を止める

Onigmo の正規表現コンパイルで何が起きたか(GitLab 発見の4件)

Onigmo は、Ruby が標準で使っている正規表現エンジンです。今回の問題は、このエンジンが正規表現を内部形式へコンパイルする段で起きます。細工したパターンを渡すと、整数オーバーフローや二重解放(Double Free)が発生してメモリが壊れ、条件によってはそこを足がかりにコードを実行されうる、という流れです。

割り当てられた CVE は4件で、いずれも GitLab が申請したものです。

CVE 中身(Ruby 告知の原文より) 位置づけ
CVE-2026-89078 パーサーでの二重解放(Double Free) GitLab 申請
CVE-2026-93577 コンパイル済みパターンサイズの整数オーバーフロー GitLab 申請
CVE-2026-97229 コンパイル済みパターンサイズの整数オーバーフロー GitLab 申請
CVE-2026-110264 繰り返しが多いパターンでの内部IDのオーバーフロー GitLab 申請

GitLab は、これらの問題を同梱する Ruby にパッチを当てた版(GitLab 19.4.1 / 19.4.2 / 19.5.1)を先に出していましたが、今回 Ruby の各系列にも必要な修正が取り込まれ、修正版が公開されました。整数オーバーフローの一件(Ruby 本家の issue #19020)は、Johan Carlsson(joaxcar)氏が GitLab のバグバウンティ経由で見つけたものです。注意したいのは、Ruby 側はこれらを「脆弱性」として扱うかどうかを現時点で決めておらず、独自の CVE 番号は申請していない点です(決まり次第ページを更新するとしています)。スキャナーなどで追跡するときは、当面 GitLab が申請した CVE 番号を参照します。この記事の内容・数値は、報道の要約ではなく Ruby 公式サイトのリポジトリにある告知の原文で確認しています。

自分のアプリは影響を受けるか:信頼できない入力から正規表現を作っているか

今回いちばん大切なのは、「自分のアプリが対象か」を正しく見分けることです。影響を受けるのは、攻撃者が制御できる文字列から正規表現をコンパイルしているアプリに限られます。

ARE YOU EXPOSED影響するか

攻撃者の入力から正規表現を作るかどうかで決まる

影響を受ける

攻撃者が制御する文字列をパターンにする

  • Regexp.new / union / compile に渡す
  • /#{input}/ のようにリテラルへ埋め込む
  • 外部から来た文字列をコンパイルする

影響を受けない

開発者が書いた正規表現だけ

  • 固定の正規表現リテラルを直書き
  • 入力は match? の対象であってパターンにしない
  • ユーザー入力でパターンを組み立てない
出典: ruby-lang.org の告知(2026-10-23 確認)。タイムアウトや長さ制限は確実な対策にならない

具体的には、次のような書き方が対象です。

・外部入力を Regexp.new・Regexp.union・Regexp.compile に渡している
・/#{input}/ のように、ユーザー入力を正規表現リテラルへ埋め込んでいる
・検索条件やフィルタの文字列を、そのまま正規表現パターンとしてコンパイルしている

逆に、開発者が書いた固定の正規表現だけを使い、ユーザー入力はマッチの対象(str.match?(/固定/) の str 側)にしているだけなら、影響を受けません。「入力をパターンにしているか、入力をパターンで照合しているだけか」が分かれ目です。多くのアプリは後者なので、まずはこの一点を確かめてください。

気をつけたいのは、自分のコードで Regexp.new を書いていなくても、使っている gem やフレームワークが内部でユーザー入力から正規表現を組み立てていることがある点です。検索・絞り込み・ルーティング・バリデーションのような「文字列を正規表現に変える」機能を持つライブラリは、間接的な入口になりえます。だからこそ、入口を一つずつ塞ぐよりも、Ruby 本体を上げて根を断つほうが確実です。

なぜ正規表現のコンパイルでメモリが壊れるのか:仕組みの要点

攻撃の再現ではなく、「なぜ壊れるのか」の要点だけを押さえます。正規表現は、使う前に一度、エンジンが扱える内部形式へコンパイルされます。Onigmo はこのとき、パターンの要素数やサイズをもとに必要なメモリを計算して確保します。

WHY IT BREAKS仕組みの要点

細工したパターンがコンパイル段でメモリを壊す

  1. 細工した正規表現パターン

    攻撃者が制御する文字列

  2. 整数オーバーフロー/二重解放

    Onigmo がパターンを組み立てる段で

  3. メモリ破壊

    想定外の領域を壊す

  4. 最悪は RCE

    条件次第。GitLab が RCE を報告

出典: ruby-lang.org・GitLab の CVE 記録(2026-10-23 確認)。4 CVE は二重解放と整数オーバーフロー

細工したパターンを渡すと、このサイズ計算で整数オーバーフロー(扱える桁を超えて値が巻き戻る)が起き、本来より小さい領域しか確保しないまま書き込みを進めてしまう、あるいは解放済みの領域をもう一度解放する二重解放が起きます。どちらも「想定外の領域を壊す」メモリ破壊で、そこから書き込みを制御できれば、コード実行につながりうる、という段階構造です。パーサーやコンパイラーという入力を解釈する部分でメモリが壊れるため、信頼できないパターンを渡すこと自体が引き金になります。重要なのは、タイムアウト(Regexp.timeout)やパターンの長さ制限を設けても、確実な対策にはならないとされている点です。Ruby の告知は、その理由として短いパターンでも発動しうることを挙げています。長く走る正規表現を止める仕組みとは別の問題で、壊れるのはマッチの実行時間ではなくコンパイルの計算そのものだからです。

確認して直す:Ruby の版と Regexp の使い方

確認は2方向です。Ruby の版が修正版以上か、そして攻撃者の入力から正規表現を作っていないか、です。

# Ruby の版が修正版以上か(4.0.9 / 3.4.12 / 3.3.13 以上なら対応済み)
ruby -v

# 外部入力から正規表現を組んでいそうな箇所を探す
grep -rnE 'Regexp\.(new|union|compile)' app lib 2>/dev/null

grep で出た箇所が、本当に外部入力を渡しているかを一つずつ見ます。これは判定ではなく構成の確認で、この結果だけでは安全とは言えません。/#{...}/ の埋め込みや、ライブラリ内部で正規表現を組み立てている箇所まではこの一行では拾い切れないからです。確実なのは、各環境で Ruby 本体を修正版へ上げ切ることです。

当サイトで確かめたこと(2026-10-23)

この記事を書いた環境の Ruby は 3.3.6 で、修正版 3.3.13 より前、つまり告知の影響版でした。掲載した検知 grep -rnE 'Regexp\.(new|union|compile)' を、Regexp.new(params[:q]) を含むファイル(陽性)と、固定の正規表現リテラルだけのファイル(陰性)で実際に走らせたところ、陽性は1行を検出して終了コード0、陰性は検出なしで終了コード1になりました。何にでもマッチする無意味な検知ではないことを確かめた、という意味です。良性の文字列を Regexp.new でコンパイルできること(=入口の API が実在すること)も確認しましたが、脆弱性を発動させる細工パターンは一切作っていません。各 CVE の内容・対策の文言は、報道の要約ではなく Ruby 公式サイトのリポジトリにある告知の原文で裏を取っています。

WHAT TO DO対応

Ruby を上げ、信頼できない入力をパターンにしない

  1. 1.Ruby を修正版へ

    4.0.9 / 3.4.12 / 3.3.13 以上。3.3.13 は resolv も 0.3.2 に

  2. 2.信頼できない入力から正規表現を作らない

    Regexp.new / union / compile・/#{input}/ を避ける

  3. 3.タイムアウト・長さ制限は確実でない

    Regexp.timeout やパターン長の制限だけでは防げない

  4. 4.追跡は当面 GitLab の CVE 番号で

    Ruby 側は独自 CVE 未申請

出典: ruby-lang.org の告知(2026-10-23 確認)

直し方は図のとおりです。本筋は Ruby を 4.0.9 / 3.4.12 / 3.3.13 以上へ上げること。3.3 は通常セキュリティ修正だけを受ける系列ですが、今回は例外として 3.3.13 にこの修正が入りました。なお 3.3.13 では標準添付ライブラリ resolv も 0.3.2 へ更新されますが、これは別件の CVE-2026-80212・80213(resolv の脆弱性)の修正で、今回の Onigmo の4件とは別のものです(同じ 3.3.13 に同梱されているだけ)。すぐに上げられないときは、信頼できない入力から正規表現を作る箇所を止めるのが当座の緩和です。ただしこれは当座しのぎで、各環境の Ruby 本体を修正版へ上げ切るまでは根が残ります。

影響範囲と GitLab との関係

影響範囲は、修正前の Ruby を使い、かつ攻撃者の入力から正規表現をコンパイルしているアプリです。Web アプリの検索・フィルタ機能などで、ユーザーが入れた文字列をそのままパターンにしている箇所が典型的な入口になります。実行されるコードはプロセスの権限で動くため、Ruby を特権で動かしている環境ほど影響は大きくなります。実環境での悪用は、現時点で確認されていません。

GitLab 側では、これらは深刻度の高い脆弱性として扱われています。GitLab の記録では、CVE-2026-110264 は未認証の利用者から悪用されうる CVSS 10.0 の問題で、7.0 までさかのぼって影響するとされ、CVE-2026-89078 はログインした利用者が前提の CVSS 9.9 とされています。つまり同じ Onigmo のコンパイル処理でも、どこから正規表現が渡るか(未認証の入口か、認証後か)で前提が変わります。一方 Ruby 側は、これらを脆弱性として扱うかを決めておらず独自の CVE を申請していないため、評価の軸が両者で異なる点に注意が要ります。

この問題は、GitLab サーバー自体の脆弱性としても扱われています。GitLab は同梱 Ruby を先に修正し、CVE-2026-110264 などを自社の緊急パッチで塞ぎました。self-managed の GitLab を運用している場合の、系列ごとの上げ先と確認手順は、GitLab 脆弱性 CVE-2026-110264|CVSS 10.0の未認証RCEに別途まとめています。今回の Onigmo の件は、その「同じ根(正規表現のコンパイル)」が、GitLab に限らずあらゆる Ruby アプリに関わる、という位置づけです。

ここで一歩引くと、2026年10月に相次いだ処理系のRCEは、同じ形をしています。アプリの下で動く言語ランタイムが、フレームワークやライブラリが自動で処理する信頼できないデータで壊れる、という構図です。当サイトで扱った3件を並べると、見え方がそろいます。

通称 壊れる処理系の部分 攻撃者データが自動で渡る経路 直し方
php2shell PHP の unserialize 系の処理 セッション・入力の復元 PHP 本体を修正版へ
node2shell Node.js 同梱の Brotli デコーダ fetch 応答・Express のボディ展開 Node.js 本体を修正版へ
Onigmo(本記事) Ruby の正規表現コンパイラ 入力から作る正規表現のコンパイル Ruby 本体を修正版へ

共通するのは、自分のアプリのコードには脆弱性が無くても、下のランタイムと、それを自動で呼ぶフレームワークの組み合わせで露出する点です。だからこそ、入口を一つずつ塞ぐより、ランタイム本体を上げて根を断つのが確実、という結論も3件で共通します。実行時に信頼できないデータを解釈する処理をどう減らすかは、設計段階の脅威モデリングの話でもあります。

参照ソース

・Regexp compilation fixes related to GitLab’s CVEs(ruby-lang.org・2026-10-23) — 4件のCVEの中身・影響する書き方・対策(告知の原文を ruby/www.ruby-lang.org のリポジトリで直接確認、2026-10-23)
・Ruby 4.0.9 / 3.4.12 のリリース(ruby/ruby・GitHub) — 各系の修正版のリリースタグ(一次情報)
・Ruby 3.3.13 Released(ruby-lang.org) — 3.3 系の例外対応と resolv 0.3.2
・gitlab-org/cves CVE-2026-110264 — GitLab 申請の CVE 記録
・GitLab 脆弱性 CVE-2026-110264(当サイト) — GitLab サーバー側の系列ごとの修正版と確認手順