🚨

【緊急】Next.js (CVE-2025-66478) / React (CVE-2025-55182) の脆弱性について

に公開

1. はじめに:何が起きたのか

2025年12月3日、Next.js および React Server Components (RSC) の通信プロトコルにおいて、認証不要でリモートコード実行 (RCE) が可能となる重大な脆弱性が公表されました。

今回、特に事態を重くしている要因は以下の2点です。

  • 土台である React 起因の欠陥
    Next.js 固有の実装ミスではなく、その基盤である React (RSC) の処理機構そのものに脆弱性が存在しました。そのため、フレームワーク側での表面的な対処ではなく、根本的な修正が必要となりました。
  • 標準構成での影響
    何か特殊な設定をした場合に限らず、Next.js (App Router) の「デフォルトの状態」で RSC が動作しているため、普通に利用しているプロジェクトのほぼ全てが影響対象となってしまいました。

開発者のミスではなく、私たちが信頼して任せているフレームワークの「裏側」で問題が起きたため、界隈には緊張が走っています。

2. 技術的メカニズム:攻撃の仕組みを整理する

この脆弱性は、例えるなら 「関係者専用の裏口に、鍵がかかっていなかった」 ような状態と言えます。

Flight プロトコルと「裏口」
RSC では、サーバーとブラウザの間でコンポーネントを受け渡すために「Flight」という独自の形式(バイナリ/テキスト)を使います。これは本来、フレームワーク内部で自動的に処理されるべきデータです。

どこに穴があったのか
公開された情報によると、問題はサーバーがこの Flight 形式のデータを受け取って復元(デシリアライズ)する際の検証不足にありました。

  1. リクエストの偽装
    攻撃者はブラウザの正規操作を経由せず、悪意あるコード(ペイロード)を含んだリクエストを直接サーバーへ送信します。
  2. 無防備なデシリアライズ
    サーバー(Next.js / React)側は、「これは内部処理用のデータだろう」と信頼して処理を進めてしまいます。
  3. コードの実行
    この過程で、ペイロード内に隠された「サーバー内の関数実行」などの指示が通ってしまい、認証もなしにサーバー上で任意のコードが実行されるリスクが生じました。

3. なぜ「認証」をすり抜けてしまったのか

通常、私たち開発者は Middleware などで認証ガードをかけますが、今回の脆弱性が「CVSS 10.0」という最大スコアを叩き出した理由は、どうやらその 「処理順序」 にあったようです。

今回のケースでは、RSC のペイロード解析(デシリアライズ)が、アプリケーションの認証ロジックが走る「前」、あるいはフレームワークの深層部で先行して行われるケースがありました。

つまり、いくら middleware.ts でルートを保護していても、門番がチェックする「手前」の段階で攻撃コードが処理されてしまう──これが、今回の脆弱性が「回避困難」とされた大きな要因ではないでしょうか。

4. 影響範囲と対象バージョン

Next.js だけでなく、React 本体のバージョン確認も必須です。公式情報を基に整理しました。

ソフトウェア CVE ID 脆弱性のあるバージョン 修正済みバージョン (Update Required)
Next.js CVE-2025-66478 v15.x (全般), v16.x (全般)
v14.3.0-canary.77 以降
v15.0.5, v15.1.9, v16.0.7
(※v14 Stable版は影響なし)
React CVE-2025-55182 v19.0.0, 19.1.0, 19.1.1, 19.2.0 v19.0.1, 19.1.2, 19.2.1

5. 今すぐやるべき対応と、恒久対策

今回の件は影響度が大きいため、まずは止血(パッチ適用)を最優先にしつつ、その後に恒久的な運用体制を見直すのが良さそうです。

1. まずは止血:パッチ適用

もっとも確実な対処法は、修正パッチが含まれるバージョンへのアップデートです。next だけでなく、react 関連のパッケージも足並みを揃えて更新する必要があります。

npm / yarn / pnpm での更新コマンド例:

# npm の場合
npm install next@latest react@latest react-dom@latest

# yarn の場合
yarn add next@latest react@latest react-dom@latest

# pnpm の場合
pnpm add next@latest react@latest react-dom@latest

⚠️ 落とし穴:内部依存の確認
トップレベルの package.json だけを見て安心するのは少し危険です。
今回の脆弱性の震源地に近い react-server-dom-webpack 等が、内部的に古いバージョンのまま残っていないか、ロックファイルを確認しておくことを強くおすすめします。

# package-lock.json や yarn.lock 内を grep してバージョンを確認する例
grep -A 5 "react-server-dom-webpack" package-lock.json

# もし古いバージョン (脆弱性対象) が残っている場合は、ロックファイルの再生成を検討
# rm package-lock.json && npm install

2. 今後検討すべき運用:WAF と自動化

パッチを当てて終わり、ではなく「次」に備えるための構成も考えておきたいところです。

WAF (Web Application Firewall) での防御
Next.js アプリケーションの手前に WAF を置くことで、そもそも不正なリクエストをアプリに到達させない構成が有効です。

  • Vercel / Cloudflare: プラットフォーム側で提供される Firewall Rules を活用し、不審な POST リクエストや、異常に大きなペイロードを持つリクエストを遮断するルールの適用を検討しましょう。
  • AWS WAF: App Runner や ECS 等でホストしている場合は、AWS Managed Rules の適用に加え、Flight プロトコル特有のヘッダー異常を検知するカスタムルールの追加も視野に入れましょう。

監視体制の自動化 (Renovate / Dependabot)
「脆弱性が公開されてから手動で対応」では後手に回るため、セキュリティパッチを自動で検知・PR作成するフローが不可欠だと再認識しました。

例えば Renovate を導入している場合、以下のようにセキュリティ修正を最優先にする設定を入れておくと、緊急時の初動が早くなります。

// renovate.json の設定例
{
  "packageRules": [
    {
      // セキュリティパッチは自動マージ、もしくは即時PR作成の優先度を上げる
      "matchUpdateTypes": ["patch", "minor"],
      "matchPackageNames": ["next", "react", "react-dom"],
      "vulnerabilityAlerts": {
        "enabled": true,
        "labels": ["security"]
      }
    }
  ]
}

6. 個人的な所感と教訓

今回のインシデントを経て、個人的にはフロントエンド開発における「セキュリティの常識」が少し変化しつつあるように感じています。

「便利さ」の裏にあるブラックボックス
Next.js のようなフルスタックフレームワークは開発を劇的に楽にしてくれますが、裏側では通信やシリアライズといった複雑な処理を行っています。便利さと引き換えに、私たちは「見えない部分」のリスクも抱え込んでいるのだと、改めて考えさせられました。

境界線への意識
RSC はサーバーとクライアントをシームレスに繋ぐ素晴らしい技術ですが、それは裏を返せば 「セキュリティ境界(Security Boundary)が曖昧になりやすい」 ということでもあります。
サーバーサイドの知識なしに「なんとなく」で実装することの危うさが、以前よりも増している──今回の件は、そんな警鐘のようにも思えました。

7. 一次情報・関連リンク

本記事の執筆にあたり、以下の公式発表および詳細レポートを参照しました。最新のパッチ情報や正確な仕様については、必ず一次情報をご確認ください。

Discussion