「React 脆弱性」で検索すると、JVN や CVE のデータベース、個別の CVE 速報が並ぶ。だが実務で手が止まるのは、多くの場合 react / react-dom 本体のバグではない。本記事は react・react-dom 19.3.1 を最小構成で動かして npm audit と描画の挙動を実測し、現場で言う「React 脆弱性」の実体を XSS・依存・SSR・古い版の4層に分けて整理する。特定の新しい CVE に乗らず、長く参照できる形で残す。
WHAT IT MEANS言葉の中身
React 本体の脆弱性は稀、実体は本体の外側にある
React 本体(react / react-dom)
JSX は既定で文字列をエスケープ
- 公開アドバイザリは主に Server Components 層
- クライアント描画の自前コードの勧告は稀
現場で言う「React 脆弱性」
多くは本体の外の層
- XSS を生む書き方/依存パッケージ
- SSR・フレームワーク/古い版
30秒でわかる(2026-10-21時点)
- ・本体の勧告は稀:facebook/react の公開アドバイザリは10件で、いずれも Server Components 層
- ・実体は4層:XSS を生む書き方/依存パッケージ/SSR・フレームワーク/古い版
- ・実測:クリーンな react/react-dom 19.3.1 で
npm auditは0件。脆弱な依存を1つ足すと critical 1件 - ・JSX は既定で守る:ただし
dangerouslySetInnerHTMLは素通し。ref や SSR の文字列結合も抜け道
まずやること(運用者向け・順番)
- ・①版を確かめる:
npm ls react react-domで実際に入っている版を見る(古い版なら層4) - ・②既知の脆弱性を洗う:
npm auditを走らせ、critical / high から仕分ける - ・③書き方を点検する:
dangerouslySetInnerHTMLを使っている箇所を洗い出し、入れる文字列の出所を確かめる
依存の乗っ取りそのものの手口は サプライチェーン攻撃とは|手口・防御ツール比較・npm 12の新機構まで実践解説 で、npm audit の結果の仕分け方は npm audit の結果はどれから直す?依存関係の脆弱性を到達性・EPSS・KEVで仕分ける実践手順 で扱った。本記事は、その手前にある「React 脆弱性という言葉の中身」を分解する。
「React 脆弱性」の多くは本体ではなく別の層にある
まず言葉を分ける。React 本体(npm の react と react-dom)に重大な脆弱性が出ることは稀だ。一方、現場で「React 脆弱性」と呼ばれる事象の実体は、本体の外側にある4つの層に散らばっている。
FOUR LAYERS4つの層
「React 脆弱性」の実体は4つの層に分かれる
-
層1
XSS を生む書き方
dangerouslySetInnerHTML・javascript: URL・ref での DOM 直接操作・SSR の文字列結合
-
層2
依存パッケージ
間接依存に入る既知の脆弱性。npm audit が見る範囲
-
層3
SSR・フレームワーク
Next.js・react-router など React を使う側の脆弱性。本体と混同されやすい
-
層4
古い版
サポート外の版や既知の問題を抱えたまま使い続ける
この4層は責任の所在も直し方も違う。層1は自分のコードの書き方、層2と層4はパッケージの版、層3は React を使うフレームワーク側だ。「React が危ない」とひとくくりにすると、直す場所を取り違える。以下、層ごとに実測で確かめる。
層1:XSS で React が守る所と抜ける所
React は JSX に渡した文字列を既定でエスケープする。これが「React を使うと XSS が減る」と言われる根拠だが、エスケープを外す経路が複数あり、そこが層1の実体だ。react-dom 19.3.1 の renderToStaticMarkup に同じ悪意ある文字列を4通りで渡して、どこがエスケープされどこが抜けるかを確かめた。
MYTH VS REALITY誤解と実態
React は既定で守るが、抜け道は残る
よくある誤解
実際の挙動(react-dom 19.3.1 で実測)
よくある誤解: JSX に入れた文字列はそのまま危険
実際の挙動(react-dom 19.3.1 で実測): 既定でエスケープ。imgタグの文字列は無害化される
よくある誤解: href に入れた値はそのまま出力される
実際の挙動(react-dom 19.3.1 で実測): javascript: の URL は React が throw に置換してブロック
よくある誤解: React を使えば XSS は起きない
実際の挙動(react-dom 19.3.1 で実測): dangerouslySetInnerHTML は素通し。ref で DOM を直接触る経路も残る
実測した結果は次のとおり。入力は <img src=x onerror="alert(1)"> という典型的な XSS 文字列。
| 渡し方 | 出力(実測) | 判定 |
|---|---|---|
| JSX のテキスト子要素 | <img src=x onerror=... にエスケープ |
既定で無害化 |
属性値(title など) |
同じくエスケープ | 既定で無害化 |
dangerouslySetInnerHTML |
<img src=x onerror=...> がそのまま |
素通し |
href="javascript:alert(1)" |
React が throw する URL に置換 | React がブロック |
注目は下2行だ。dangerouslySetInnerHTML は名前のとおりエスケープを外すので、信頼できない文字列を渡せばそのまま DOM に入る。一方 href に入れた javascript: スキームは、react-dom 19.3.1 では javascript:throw new Error('React has blocked a javascript: URL as a security precaution.') に置き換えられ、実行されなかった。つまり javascript: URL は React 本体が止めるが、dangerouslySetInnerHTML は止めない——同じ「XSS」でも、React が面倒を見る範囲とそうでない範囲が分かれる。
ただし React がブロックするのは、あくまで JSX 経由で属性に入れた場合だ。ref で取得した DOM ノードに innerHTML や setAttribute で直接書き込む経路、サーバー側で React の外で HTML 文字列を結合して差し込む経路は、React のエスケープを通らない。層1は「React に任せきれる所」と「自分で無害化する所」を分けて扱うのが要点になる。
層2〜4:依存パッケージ・SSR/フレームワーク・古い版
残りの3層は版とフレームワークの話だ。実際に npm audit を陰性・陽性の対照つきで走らせて、何がどう出るかを確かめた。
層2(依存パッケージ)。react と react-dom だけを入れたクリーンなアプリで npm audit を走らせると found 0 vulnerabilities だった。そこに既知の脆弱性を持つ [email protected] を1つ足すと、結果は critical 1件(Prototype Pollution)に変わる。このとき報告に現れるのは minimist であって、react でも react-dom でもない。実務の「React 脆弱性」の多くがこの層、つまり React を使うアプリが抱える周辺パッケージの既知の脆弱性だ。仕分けの手順は npm audit の記事 に譲る。
層3(SSR・フレームワーク)。Next.js や react-router など「React を使う側」の脆弱性は、見出しに React の名が出るため本体と混同されやすい。たとえば React Router v7 RCE脆弱性 CVE-2026-42211 は react-router の問題で、react / react-dom 本体ではない。直すのはそのフレームワークの版であって、React の版ではない。
層4(古い版)。サポート外の古い版を使い続けると、本体ではなくその版が引き込む依存で警告が出ることがある。react 16.0.0 を入れて npm audit を走らせると、react と react-dom 自体が high と報告された。だが理由は本体のコードではなく「脆弱な版の fbjs に依存している」ため——古い版が古い周辺パッケージを連れてくる、という形だった。版を上げれば消える種類の警告だ。
| 層 | 実体 | 確かめ方 | 直す対象 |
|---|---|---|---|
| 層1 XSS | 書き方(dangerouslySetInnerHTML など) |
コードの点検・サニタイズ | 自分のコード |
| 層2 依存 | 周辺パッケージの既知の脆弱性 | npm audit |
該当パッケージの版 |
| 層3 SSR/FW | Next.js・react-router 側 | 各フレームワークの告知 | フレームワークの版 |
| 層4 古い版 | サポート外の版が連れる依存 | npm ls react と版の確認 |
React と周辺の版 |
React 脆弱性を自分のプロジェクトで確かめる手順
ここまでを自分のプロジェクトに当てる手順をまとめる。すべて読み取りだけのコマンドで、設定は変えない。層ごとに対策(直す場所)が違うので、まず現状を見てから手を入れる。
まず、実際に入っている版を見る。package.json の宣言ではなく、解決後の版を確かめる。
npm ls react react-dom
クリーンな構成では react-dom が react を deduped で参照する木が出る。ここで古い版が出れば層4の候補だ。次に既知の脆弱性を洗う。
npm audit
npm audit fix --dry-run
npm audit fix --dry-run は、実際には変えずに「自動で直せるか」を見せる。実測では、[email protected] のように修正版が宣言した依存範囲の外にある場合、--dry-run は up to date と表示して何もしなかった。npm audit fix が黙って直せるのは semver の範囲内に収まる修正だけで、範囲をまたぐ修正は --force が要る。audit が「fix available via npm audit fix –force」と書いたら、それは互換性が壊れうる変更なので、自動では直さず自分で版を確かめる合図だ。
最後に層1の書き方を洗い出す。
grep -rn "dangerouslySetInnerHTML" src/
このコマンドが見ているもの(過大解釈しない)
- ・見ているのは
dangerouslySetInnerHTMLを使っている箇所であって、安全かどうかの判定ではない。ヒットしても安全とは言えないし、危険とは限らない。各行で「入れている文字列の出所」を1件ずつ確かめる - ・陽性(使っている)ならヒット、陰性(使っていない)なら何も出ずに終了(exit 1)することを手元で確かめた
- ・
ref経由の直接 DOM 操作やサーバー側の文字列結合はこの grep には出ない。層1はこの結果だけでは判断できない
React 本体のアドバイザリは実際どれくらいあるか
「本体の勧告は稀」の根拠を示す。facebook/react の公開セキュリティアドバイザリは2026-10-21時点で10件だった。そして10件とも React Server Components / Server Functions に関するもので、最新の Critical は GHSA-xqc2-xf4c-x3h3(Unauthenticated RCE、CVSS v4 で 9.5、2026-10-14 公開)だ。
ただしこれは「React 本体に脆弱性はゼロ」という意味ではない。本体の勧告は存在するが、その多くはクライアントの描画そのものではなくサーバー側の新しい層(Server Components)に集まっている。実際 GHSA-xqc2-xf4c-x3h3 の影響範囲は react-server-dom-webpack / turbopack / parcel で、クライアント描画の react-dom 単体は対象外とされ、RSC をフレームワークやバンドラ経由で使う構成でのみ成立する。サーバーを持たない、または RSC を使わないアプリは影響しないと告知されている。なお同アドバイザリの修正版の一つが react-server-dom-* の 19.3.1 で、本記事で実測した react-dom 19.3.1 と版番号がそろう。
逆に言えば、サーバー側で RSC を使う構成では本体側のアドバイザリも現実の対象になる。「本体は安全だから読まなくてよい」ではなく、自分の構成が本体のアドバイザリの前提(RSC やサーバー実行)に当てはまるかを確かめるのが正しい付き合い方だ。アドバイザリの原文は参照ソースの facebook/react のページで版ごとに確認できる。
まとめ
「React 脆弱性」は一つのものではない。本体の勧告は稀で主にサーバー層に集まる一方、実務で遭遇するのは XSS を生む書き方・依存パッケージ・SSR/フレームワーク・古い版という本体の外の4層だ。やることは、入っている版を見て(npm ls)、既知の脆弱性を洗い(npm audit)、書き方を点検する(dangerouslySetInnerHTML の箇所を確かめる)——層ごとに直す場所を取り違えないことに尽きる。
この記事の結論
- ・本体だけ更新しても足りない:周辺の依存とフレームワークの版、自前コードの書き方を層ごとに点検する
- ・audit が0件=安全ではない:XSS の書き方は audit の範囲外。コードの点検を別に行う
参照ソース
・facebook/react Security Advisories — 公開アドバイザリ10件と GHSA-xqc2-xf4c-x3h3 の影響範囲(2026-10-21確認)
・React 公式ドキュメント dangerouslySetInnerHTML — エスケープを外す経路の定義(2026-10-21確認)





