2026年6月、人気ルーティングライブラリReact Router v7のFramework Modeに、深刻な脆弱性CVE-2026-42211(CVSS 8.1 / High)が公表された。原因はReact Routerが内部に取り込んでいる(vendored)turbo-stream v2のデシリアライズ処理にあり、特定条件下で未認証のリモートコード実行(RCE)に至る。React Routerは旧Remixの後継として広く使われており、SSRでloader/actionを動かす構成が影響を受ける。本記事では、影響バージョンの確認・パッチ適用・SCA(Software Composition Analysis)による継続検知までを手順で解説する。
AIエージェント時代のセキュリティ全体像を整理したい方は、ピラー記事AIセキュリティとは?LLM時代の脅威モデル・代表的リスク・OSS対策ツールを体系解説する入門ガイドを先に読むと、本記事の位置づけがつかみやすい。
- ・影響範囲: React Router 7.0.0〜7.14.1のFramework Mode。修正版は7.14.2。Declarative Mode / Data Modeは影響なし。
- ・攻撃内容: vendored turbo-stream v2のTYPE_ERRORデシリアライズで任意コンストラクタを呼び出せ、アプリ側のプロトタイプ汚染と連鎖して未認証RCE(CVSS 8.1)に到達。
- ・対応: npm ls / npm audit / GHSAアラートで使用有無を確認し、
react-router@^7.14.2へ更新。上げられない場合はloader入力の厳格バリデーションとプロトタイプ汚染対策で緩和。
30秒で理解する
まず要点だけを押さえる。CVE-2026-42211は「React Router v7が内部に抱えるturbo-stream v2のデシリアライズが、攻撃者の指定したコンストラクタを呼んでしまう」という一点に集約される。単独で即RCEになるのではなく、アプリ側のプロトタイプ汚染と組み合わさったときに発火する2段構えの脆弱性である点が重要だ。
・対象と深刻度: CVE-2026-42211、CVSS 8.1(High)、CWE-502(信頼できないデータのデシリアライズ)。攻撃ベクトルはNetwork、必要権限はNone(未認証)、攻撃難易度はHigh
・影響範囲: React Router 7.0.0以上7.14.1以下のFramework Mode。<BrowserRouter>のDeclarative Mode、createBrowserRouter/<RouterProvider>のData Modeは影響なし
・修正版: 7.14.2。これ以降に更新すれば本脆弱性は解消する
・確認手順: (1)npm ls react-routerで直接・推移的依存とバージョンを洗い出し (2)npm auditでアラート確認 (3)GitHubのDependabot / GHSAアラートを点検
・当面の対応: 即時アップデートが最優先。上げられない場合はloader/actionの入力を厳格にバリデーションし、自前コードのプロトタイプ汚染を潰し、SSRエンドポイントの公開範囲を絞る
何が起きたか — React Router v7のRCE脆弱性
2026年6月2日にGitHub Security Advisory(GHSA-49rj-9fvp-4h2h)が、6月3日にGitLab Advisory Databaseが公開され、React Router v7のFramework ModeにおけるRCE脆弱性が明らかになった。CVE番号はCVE-2026-42211、深刻度はCVSS 8.1(High)である。発見・報告はGitHubのセキュリティリサーチャー(@SM41ldRag0n)によるもので、React Routerメンテナのチームがアドバイザリを公開し、同時に修正版7.14.2をリリースした。
React Routerは旧Remixを取り込んで生まれたv7で、ルーティングだけでなくサーバサイドレンダリング(SSR)とデータローディングを担うFramework Modeを提供する。今回の脆弱性はこのFramework Modeでのみ発火し、クライアント専用のルーティング(Declarative Mode / Data Mode)には影響しない。攻撃ベクトルがネットワーク経由かつ未認証である点で、対象アプリにとっては優先度の高いアップデートだ。
近年、フロントエンド/フルスタックフレームワークのSSR層を狙った脆弱性は急増している。直近でも、Viteベースのテストランナーを突いたVitest RCE脆弱性(CVE-2026-47429ほか)の影響確認・パッチ適用・SCA検知の手順、Next.jsのSSRFを扱ったNext.js SSRF脆弱性(CVE-2026-44578)の解説を公開してきた。今回のReact Routerも、これらと同じ「サーバ側で信頼境界を越えた入力を処理する」系統に位置づけられる。
脆弱性の詳細とCVSS評価
CVE-2026-42211のCVSSベクトルは CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H で、ベーススコアは8.1(High)だ。AV:N(ネットワーク到達)、PR:N(権限不要)でありながら、AC:H(攻撃難易度が高い)が付いているのは、アプリ側に別途プロトタイプ汚染の欠陥が存在するという前提条件が必要なためである。機密性・完全性・可用性はすべてHighで、最終的に任意コード実行に至る。
技術的な核心は、React Router v7のFramework Modeが内部に取り込んでいるturbo-stream v2にある。turbo-streamは、Date・Map・Set・Errorといった複雑なJavaScriptオブジェクトをHTTPストリーム越しにシリアライズ/デシリアライズするためのライブラリだ。問題はError型を復元する処理にある。シリアライズされた値の型がTYPE_ERRORのとき、turbo-streamは対応するコンストラクタを呼び出してオブジェクトを再構築するが、呼び出すコンストラクタが正規のものか検証していない。
つまり攻撃は次の2段で構成される。第1段で、アプリ自身あるいはその依存パッケージに存在するプロトタイプ汚染の欠陥を突き、サーバ側JavaScript環境の組み込みオブジェクトのプロトタイプを汚染する。第2段で、細工したturbo-streamペイロードを送り、TYPE_ERRORのデシリアライズを通じて汚染済みのコンストラクタを発火させる。第2段だけでは成立せず、第1段の前提が揃ったときに初めてRCEが成立する——これが「条件付き未認証RCE」と表現される理由だ。
なお本記事では防御・検知・修正の観点に限定し、攻撃ペイロードの具体例は掲載しない。重要なのは「自前コードや依存にプロトタイプ汚染がある環境では、turbo-streamのデシリアライズがRCEの最終トリガになり得る」という構造の理解である。
アプリ/依存の
プロトタイプ汚染欠陥} B -->|Error.prototype 等を汚染| C[組み込みコンストラクタを
任意のものに差し替え] C --> D{第2段
細工した
turbo-stream ペイロード} D -->|TYPE_ERROR を含む| E[turbo-stream v2
デシリアライズ] E -->|コンストラクタ未検証| F[汚染済みコンストラクタを呼び出し] F --> G[任意コード実行 RCE] style B fill:#ffe6e6 style D fill:#ffe6e6 style G fill:#ff9999
影響範囲:影響バージョンと修正バージョン
影響範囲を表に整理する。判定の軸は「React Routerのバージョン」と「動作モード」の2つだ。
| 項目 | 内容 |
|---|---|
| CVE / GHSA | CVE-2026-42211 / GHSA-49rj-9fvp-4h2h |
| 深刻度 | CVSS 8.1(High)、CWE-502 |
| 影響バージョン | React Router 7.0.0 〜 7.14.1 |
| 修正バージョン | React Router 7.14.2 以降 |
| 関連パッケージ | turbo-stream v2(React Routerにvendored) |
| 影響を受ける構成 | Framework Mode(SSR + loader/action) |
| 影響を受けない構成 | Declarative Mode(<BrowserRouter>)、Data Mode(createBrowserRouter/<RouterProvider>) |
| 前提条件 | アプリ側に別途プロトタイプ汚染の欠陥が存在すること |
ここで一点、現実的な落とし穴を補足する。「自分のアプリにはプロトタイプ汚染なんてない」と思っても、前提条件は依存パッケージ側のプロトタイプ汚染でも満たされる。npmエコシステムではプロトタイプ汚染系のCVEが定期的に見つかっており、推移的依存のどこか一つにそれがあれば連鎖が成立し得る。だからこそ「前提条件が高い=安全」ではなく、根本対策である7.14.2への更新を優先すべきだ。
⚡対応確認の手順(重点セクション)
ここからが本記事の中心だ。自組織が影響を受けるかを確実に判定し、対応漏れを防ぐための手順を4ステップで示す。
Step 1: React Routerを使っているか・どこで使っているか確認
まず依存ツリー上のReact Routerを洗い出す。直接依存だけでなく、別パッケージ経由の推移的依存も見逃さないことが重要だ。
# npm
npm ls react-router
# yarn
yarn why react-router
# pnpm
pnpm why react-router
# モノレポ(全ワークスペース横断)
pnpm -r exec npm ls react-router
npm lsはツリー形式で「どのパッケージがreact-routerを引き込んでいるか」を表示する。dedupedと出る箇所は重複排除済みの同一バージョンを指す。Remixからの移行プロジェクトでは@remix-run/*経由でreact-routerが入ることもあるため、ヒットしたパスは一つずつ確認する。
Step 2: バージョンを確定する
次に実際のインストールバージョンを確認する。package.jsonの宣言(キャレット付き範囲)と、lockfileに固定された実バージョンは別物なので、必ずlockfileを見る。
# package.json の宣言を確認
grep -E "\"react-router\"" package.json
# lockfile の実バージョン(パッケージマネージャに応じて)
grep -A 2 '"react-router"' package-lock.json
grep -A 3 'react-router@' yarn.lock
grep -A 3 'react-router@' pnpm-lock.yaml
実バージョンが7.0.0以上7.14.1以下なら影響対象だ。^7.0.0のようにキャレット指定でも、lockfileが7.14.1で固定されていれば自動では7.14.2に上がらない点に注意する。
Step 3: npm audit / GHSA / Dependabotで突き合わせる
手作業の確認に加えて、自動ツールでも裏取りする。npm auditはlockfileを脆弱性データベースと突き合わせ、該当アドバイザリを表示する。
# npm audit(該当パッケージのみ絞り込みたい場合は出力をgrep)
npm audit
npm audit --json | grep -A 5 react-router
# GitHub の脆弱性アラート(Dependabot)をAPIで確認
gh api graphql -f query='
{
repository(owner: "ORG", name: "REPO") {
vulnerabilityAlerts(first: 20, states: OPEN) {
nodes {
securityVulnerability {
package { name }
advisory { ghsaId summary }
vulnerableVersionRange
firstPatchedVersion { identifier }
}
}
}
}
}'
gh api graphqlのORG/REPOを自組織のものに置き換えれば、Dependabotが検知したreact-router関連アラート(GHSA-49rj-9fvp-4h2h)が一覧できる。複数リポジトリを抱える組織では、このGraphQLクエリをスクリプト化して横断棚卸しするのが効率的だ。
Step 4: 過去ログ・公開状況の確認
最後に、影響バージョンを使っていた期間の運用ログを点検する。確実な侵害判定は難しいが、リスク評価には有効だ。
・公開状況: SSRエンドポイント(loader/actionを処理するルート)が外部から到達可能だったか。内部ネットワーク限定なら攻撃面は小さい
・異常ペイロード: loader/actionへのリクエストに__proto__・constructor・prototypeを含む不審なJSON、想定外のturbo-streamフォーマットがなかったか
・プロセス異常: デシリアライズ処理の直後に、子プロセス生成・想定外の外部通信・ファイル書き込みが発生していないか(APM / EDRで確認)
・依存の汚染源: 同時期に自組織が抱えていたプロトタイプ汚染系CVE(第1段の前提)の有無
⚙️ 修正手順
確認が済んだら修正に進む。規模や運用形態に応じて3つのパターンを示す。
A. シンプルなアップデート(単一リポジトリ)
最も基本的なのは、react-routerを7.14.2以降へ更新することだ。
# react-router を修正版へ
npm install react-router@^7.14.2
# 関連の @react-router/* を含め推移的依存を整える
npm update react-router @react-router/dev @react-router/node @react-router/serve
# lockfile から再現インストールして確認
npm ci
npm ls react-router
更新後はnpm ls react-routerで実バージョンが7.14.2以上になっていること、npm auditでGHSA-49rj-9fvp-4h2hが消えていることを必ず確認する。
B. モノレポでの一括更新
複数パッケージを抱えるモノレポでは、ワークスペース全体で揃える。バージョンのばらつきが残ると「一部だけ脆弱版」という穴ができる。
# pnpm workspaces:全ワークスペースで更新
pnpm -r update react-router@^7.14.2
# yarn workspaces
yarn workspaces foreach -A up react-router@^7.14.2
# turborepo を併用している場合、更新後にキャッシュをクリアして再ビルド
pnpm -r exec npm ls react-router # 全パッケージのバージョン確認
turbo run build --force
更新後はpnpm -r exec npm ls react-routerで全ワークスペースのバージョンが7.14.2以上に揃っていることを確認する。lerna運用の場合もlerna exec -- npm ls react-routerで同様に横断確認できる。
C. すぐにアップデートできない場合の暫定緩和策
事情があって即時更新できない場合の緩和策を挙げる。いずれも時間稼ぎであり根本対策ではない点を強調しておく。
・loader/actionの入力厳格化: 信頼できない入力をスキーマ(zod等)で厳格にバリデーションし、想定外の構造を早期に弾く
・プロトタイプ汚染の遮断: 第1段の前提を潰す。JSONマージ・オブジェクト代入時に__proto__・constructor・prototypeキーを拒否し、必要に応じて重要オブジェクトをObject.freezeする
・WAFでの異常ペイロードブロック: プロトタイプ汚染の典型キーを含むリクエストをWAFで検知・遮断する(汎用シグネチャでは抜ける可能性があるため補助的位置づけ)
・公開範囲の縮小: SSRエンドポイントの外部到達性を見直し、不要な公開を止める
SCA(Software Composition Analysis)でCIから検知する
今回のように「依存ライブラリの内部にvendoredされたパッケージ」が原因の脆弱性は、目視では追い切れない。CIにSCAを組み込み、新たなアドバイザリが出た瞬間に気づける状態を作るのが本質的な対策だ。
| ツール | 特徴 | 向いているケース |
|---|---|---|
| Dependabot | GitHub標準・無料。脆弱性アラート+自動修正PR | まず最初に有効化する基本線 |
| Snyk | 商用。詳細スキャンと修正提案、推移的依存の可視化 | 修正の優先度付けまで欲しい組織 |
| Socket | インストール時スクリプトや通信先など挙動を分析 | サプライチェーン攻撃まで警戒する場合 |
| GitGuardian | シークレット検知が主軸、依存監視も併設 | 機密漏洩リスクを併せて見たい場合 |
| Phylum | パッケージのリスクスコアリングとポリシー制御 | ポリシーベースで遮断したい組織 |
最短ルートはDependabotだ。GitHubなら設定一つで脆弱性アラートとセキュリティ更新PRが回り始める。そのうえで、パッケージの実挙動(インストール時の通信先など)まで見たい場合にSocketを、商用の詳細スキャンと修正提案が欲しい場合にSnykを重ねる。「まず気づける状態を作り、運用が回ってから挙動分析系を足す」のが現実的な順序である。
CIに組み込む最小例は次のとおりだ。
# .github/workflows/sca.yml(抜粋)
name: SCA
on: [push, pull_request]
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci
# High 以上の脆弱性が出たらCIを失敗させる
- run: npm audit --audit-level=high
--audit-level=highを付けることで、CVSS 8.1のCVE-2026-42211のようなHigh以上の脆弱性が混入した時点でCIを赤くできる。pnpm環境ならpnpm audit --audit-level highが同等だ。
React Routerユーザーの追加チェック
バージョン更新だけで終わらせず、自組織の構成に応じて次の点も点検したい。
・SSRエンドポイントの公開状態: loader/actionを処理するルートが、本当に外部公開が必要か。管理画面系は内部限定にできないか
・loader/actionの入力経路: クエリ・ボディ・ヘッダのどこから信頼できない入力が入り、どこでデシリアライズされるかを棚卸しする
・Remixからの移行プロジェクト: Remix v2からReact Router v7へ移行した/移行中のリポジトリは、Framework Modeのまま運用されていることが多く、優先的に7.14.2へ
・カスタム認証/認可レイヤとの相互作用: 未認証で到達するSSRエンドポイントがある場合、認可前にデシリアライズが走らないかを確認する
似たパターンで狙われやすいフレームワーク脆弱性史
React Routerのケースは突発的な単発事故ではなく、SSR/フルスタックフレームワークが構造的に抱えるリスクの一例だ。近年の主な事例を振り返ると、対策の方向性が見えてくる。
・デシリアライズ起因のRCE: 信頼できない入力をオブジェクトに復元する処理は、コンストラクタやガジェットチェーンの悪用と相性が悪い。CWE-502は言語を問わず繰り返し悪用される定番だ
・プロトタイプ汚染の連鎖: JavaScript特有の弱点で、単体では軽微に見えても、今回のように別の機構と連鎖して致命傷になる。npmエコシステムで定期的に発見されている
・テストツールのサーバ化: Vitest RCE脆弱性のように、開発ツールが内部でサーバを立てる構成は新たな攻撃面になる
・サプライチェーン文脈: vendored依存の脆弱性は「自分は直接入れていない」ため発見が遅れやすい。npm汚染の広がりはAIを悪用したnpmサプライチェーン攻撃「Miasma」の解説も参照したい
これらに共通するのは「信頼境界の内側だと思っていた場所が、実は外部入力に晒されていた」という構図だ。トークンやセッションの保護を多層で考える視点はトークン窃取に対する多層防御の解説でも整理している。
企業向けチェックリストとよくある落とし穴
組織として今回の脆弱性に対応する際のチェックリストと、現場で起きがちな失敗をまとめる。
- ・全リポジトリで
react-routerの実バージョンを棚卸しし、7.0.0〜7.14.1を洗い出す - ・Framework Mode利用の有無とSSRエンドポイントの公開状況を整理する
- ・影響対象を7.14.2以降へ更新し、
npm auditでアラート消失を確認する - ・DependabotをCIに組み込み、High以上でCIを失敗させるポリシーを設定する
- ・SBOM(ソフトウェア部品表)を整備し、vendored依存まで可視化する
- ・受託・客先案件は、使用バージョン・公開設定・更新済みである旨を報告する
よくある落とし穴は次のとおりだ。
・推移的依存の見落とし: 直接package.jsonに書いていなくても、別パッケージ経由でreact-routerが入る。npm lsで必ずツリー全体を見る
・npm audit fixでの意図しない降格: --force付き自動修正がメジャーダウングレードや破壊的変更を引き込むことがある。差分を確認してから適用する
・Dependabot PRの放置: アラートだけ出て更新PRがマージされず放置される。CIゲートとレビュー担当を決めて運用に乗せる
・SSR/SPAの取り違え: 「うちはSPAだから無関係」と思い込み、実はSSRビルドだったというケース。ビルド構成を実際に確認する
まとめ
React RouterのRCE脆弱性CVE-2026-42211(CVSS 8.1)は、vendored turbo-stream v2のTYPE_ERRORデシリアライズが任意コンストラクタを呼び出し、アプリ側のプロトタイプ汚染と連鎖して未認証RCEに至る2段構えの脆弱性だ。発火するのはFramework Modeのみで、Declarative / Data Modeは影響しない。とはいえ前提条件は依存パッケージ側のプロトタイプ汚染でも満たされ得るため、「前提が高いから安全」と考えるのは危険だ。
対応はシンプルである。npm ls react-routerで影響バージョンを洗い出し、7.14.2へ更新し、SCAをCIに組み込む——この3点を押さえれば本脆弱性は確実に封じられる。あわせてloader/actionの入力厳格化と自前コードのプロトタイプ汚染対策を進めれば、同系統の将来の脆弱性に対する耐性も上がる。NVDの詳細解析を待つ必要はなく、GHSAとGitLab Advisoryで影響範囲は確定している。今すぐnpm ls react-routerから始められる。
参照ソース
・GHSA-49rj-9fvp-4h2h: Potential RCE via 2-step attack chained onto existing prototype pollution vulnerability(React Router公式・GitHub Security Advisory) — 一次ソース。影響バージョン・修正版・CVSS・前提条件はここを基準にした
・CVE-2026-42211: React Router’s vendored turbo-stream v2 allows arbitrary constructor invocation via TYPE_ERROR deserialization leading to Unauth RCE(GitLab Advisory Database) — 影響範囲とturbo-stream TYPE_ERRORデシリアライズの機序
・CVE-2026-42211(NVD・National Vulnerability Database) — CVSS 8.1 / ベクトル / CWE-502 の確認
・remix-run/react-router(公式リポジトリ・リリース) — 修正版7.14.2のリリース情報