当社のAIエンジンNeutronが、UCバークレーのCyberGymベンチマークで97.1%のスコアを記録しました。 詳細を見る

ディープダイブ

ディープダイブ

GHSA-673q-mjm6-r5xr:Next.jsの「use cache」関数における未認証RCE

GitHub Advisory DatabaseはGHSA-673q-mjm6-r5xrをクリティカル、CVSS v4.0 9.5と評価しています。App RouterとCache Componentsを使い、複数の型付き配列を返すuse cache関数があるNext.js 16サーバーで、未認証の攻撃者がコードを実行できます。データベースのレビューは、Next.jsが同梱するReact Server Componentsの通信プロトコルにおける、信頼できないデータのデシリアライゼーション(CWE-502)と分類しています。Next.js 16.4.1で修正済みで、回避策はありません。

要点

  • Cache Componentsを有効にし、複数の型付き配列を返すuse cache関数があるNext.js 16アプリケーションでは、未認証の攻撃者がリモートコード実行(RCE)を達成できます。GitHub Advisory Databaseのレビューは、CWE-502(信頼できないデータのデシリアライゼーション)と分類しています。
  • Next.js 16の16.0.0~16.4.0のすべてのリリースが影響を受けます。GitHub Advisory Databaseの評価はクリティカル、CVSS v4.0 9.5で、認証やユーザー操作なしにネットワーク経由で悪用できます。
  • 2026年10月23日時点で公開の概念実証(PoC)はなく、実環境での悪用も確認されていません。CISA Known Exploited Vulnerabilitiesカタログにも登録されていません。
  • 直ちにNext.js 16.4.1へアップグレードしてください。Vercelは回避策がないとし、型付き配列を返すuse cache関数がないアプリケーションにも、即時のアップグレードを推奨しています。

影響を受けるか

アプリケーションがNext.js 16.0.0~16.4.0でApp RouterとCache Componentsを有効にしている場合に影響を受けます。Cache Componentsは、use cacheディレクティブを付けた関数の結果をリクエスト間で保存・復元するNext.js 16のキャッシュモデルです。アドバイザリが示す発生条件は、Uint8ArrayやFloat64Arrayなど、複数の型付き配列を返すuse cache関数です。

ブランチ 影響を受けるバージョン 修正バージョン
Next.js 16.x 16.0.0 – 16.4.0 16.4.1

インストール済みのものを確認します。

# Installed Next.js version
npm ls next
node -e "console.log(require('next/package.json').version)"

# Lock file check (package-lock.json v2/v3 records the package under "node_modules/next")
grep -A1 '"node_modules/next"' package-lock.json

# Container image check
docker run --rm <your-image> node -e "console.log(require('next/package.json').version)"

次に、コードで影響機能を有効にしているか確認します。Cache Componentsはオプトインの設定で、use cacheはサーバーコードに直接現れます。

# Cache Components enabled in the Next.js config
grep -n "cacheComponents" next.config.*

# Any use of the cache directive across the project, including src/ and shared libraries
grep -rn "use cache" --include="*.tsx" --include="*.ts" --include="*.jsx" --include="*.js" --exclude-dir=node_modules --exclude-dir=.next .

一つの関数が2つ以上の型付き配列を返せば、公開された発生条件を満たします。

修正方法

Next.jsを16.4.1以降にアップグレードします。

npm install next@16.4.1
# or: pnpm add next@16.4.1   |   yarn add next@16.4.1

回避策はありません。Vercelのアドバイザリは、そのようなuse cache関数がないアプリケーションでも直ちにアップグレードするよう明記しています。同じリリースは、同日に公開されたImage Optimizationの未認証RCE(GHSA-2464-fhr4-w9xw、上流のlibrsvgの欠陥CVE-2026-96889が原因)も修正するため、一度のアップグレードで両方に対応できます。

根本原因

Next.jsはReact Server Components(RSC)を基盤とし、サーバーがコンポーネントの出力を、通常flightデータと呼ばれるシリアライズされたチャンクのストリームへレンダリングします。そのストリームを読み戻すのがデシリアライゼーションです。ランタイムはチャンクをたどり、参照を解決し、オブジェクト、Promise、ストリーム、型付き配列、サーバー関数参照を再構築します。Cache Componentsでは、use cache関数の戻り値も同じ通信機構で保存・復元するため、デシリアライザーはキャッシュエントリ由来のデータを扱います。アドバイザリはCWE-502、信頼できないデータのデシリアライゼーションと分類しています。

Vercelは正確な攻撃経路を公開していないため、以下は修正コードを読んだ分析です。「Improve Server Component transport protocol」と題されたコミットa4cea6aは、同梱するreact-server-dom-webpackとreact-server-dom-turbopackのランタイムを、12種類すべてのビルドで置き換え、デシリアライゼーション境界の4か所を強化しています。

第一に、旧デシリアライザーは、thenというプロパティによって通常のオブジェクトがPromiseのように見えるか確認せず、モデルの各エントリを解決していました。JavaScriptは呼び出せるthenプロパティを持つオブジェクトをPromiseのようなもの(thenable)として扱い、awaitやチェーンを行うコードはその関数を呼びます。新しいコードは解析時にこの混同を拒否します。

// after the fix, in the bundled react-server-dom client and server runtimes
function createModel(response, model, parentObject, key) {
  return "then" === key && "function" === typeof model ? null : model;
}

修正前のcreateModelはモデルを変更せず返していたため、then関数を持つデシリアライズされたオブジェクトが、再構築されたオブジェクトグラフで有効なまま残り、ランタイムやアプリケーションがPromiseとして扱う場所で呼び出され得ました。

第二に、シリアライズされた参照を実際のサーバー関数に対応付け、requireModuleによるコード読み込みに至ることのあるサーバー参照の解決が、入力を検証するようになりました。

function loadServerReference(response, metaData, parentObject, key) {
  if ("then" === key) return null;
  var id = metaData.id;
  if ("string" !== typeof id) return null;
  ...

修正前はmetaData.idが型チェックなしでresolveServerReferenceとrequireModuleに届いていました。

第三に、ランタイムがチャンクグラフを介して内部のレスポンスオブジェクトを公開しなくなりました。旧コードは、解決済みモデルチャンクのchunk.reasonに、生のレスポンスオブジェクトを直接保存していました。再構築されたオブジェクトのプロパティをたどると、それに到達し、さらにデシリアライゼーションの機構に届く可能性がありました。新コードは、ランタイムが生成したシンボルを使ってホルダーオブジェクト内へレスポンスを隠し、通常のプロパティ走査では到達できなくします。

// before: new ReactPromise("resolved_model", value, response)
// after:
var RESPONSE_SYMBOL = Symbol();
function createResolvedModelChunk(response, value) {
  var holder = {};
  return new ReactPromise("resolved_model", value,
    ((holder[RESPONSE_SYMBOL] = response), holder));
}

第四に、以前は一つのキースペースを共有していたものを通信機構で分離します。シリアライズされたペイロードは、接頭辞とチャンクIDをキーとするform-dataエントリとして運ばれます。関心事ごとの変更は次のとおりです。

  • 旧デシリアライザーは、全エントリへの生の検索response._formData.data.get(response._prefix + id)で内部状態を解決し、型付き配列の読み取りもresponse._formData.data.get(key).arrayBuffer()で同様に行っていた
  • 新コードは到着時に種類別に分類する。ストリームチャンクはフィールド接頭辞に「S」を付けたキー、文字列チャンクとバイナリblobはそれぞれのマップへ保存し、型付き配列はgetBackingBlob(response._formData, key)を通して読む
  • シリアライズ側では、クライアントがストリームエントリを、単純なformFieldPrefix + streamIdではなくformFieldPrefix + "S" + streamIdで書く
  • 型付き配列のシリアライズは、4096バイト(ブラウザービルドでは2048バイト)を超える配列について、ビューが基底バッファの先頭から始まらない、バッファ全体を覆わない、またはバッファが可変長の場合にコピーする

一文で言えば、デシリアライザーは読み戻したエントリの構造を信頼し、Promiseに見せかけたオブジェクト、任意の型の識別子を持つサーバー参照、たまたま持つキーだけで種類が決まるエントリを受け入れていました。パッチは、これらの信頼点それぞれに型と種類のチェックを加えます。

悪用の仕組み

PoCは公開されておらず、Vercelは正確なリクエスト経路を説明していません。したがって、以下はアドバイザリとパッチが示す悪用の類型であり、具体的な手順書ではありません。

  1. アプリケーションがCache Componentsを有効にし、複数の型付き配列を返すuse cache関数を定義します。各型付き配列はシリアライズされたペイロード内で別のバイナリチャンクになります。これがVercelが必要とする条件です。
  2. 未認証リクエストがアプリケーションに届きます。CVSSベクトル(ネットワーク、権限不要、ユーザー操作不要)とCWE-502分類がアタックサーフェスを示します。攻撃者の入力が、flightデシリアライザーが処理するデータに到達します。
  3. 攻撃者は、パッチが閉じる信頼上の欠陥を狙ったエントリをデータ内に入れます。ランタイムがPromiseとして呼ぶthen関数を持つオブジェクト、文字列ではないidが攻撃者の選んだ内容に解決されるサーバー参照、あるいは平坦なキースペースを利用して内部チャンクとして扱われるエントリです。
  4. デシリアライザーが細工されたエントリを解決します。サーバー参照の解決を介して、シリアライズされた参照を実際のサーバーコードに対応付けるrequireModuleへ到達する可能性があります。
  5. 攻撃者の選んだ参照がNext.jsサーバープロセスの権限で実行され、リモートコード実行になります。

型付き配列という条件は、この経路と直接対応します。修正のシリアライズ側は、ビューが基底バッファ全体を覆わない配列の出力方法を修正します。デシリアライズ側は、基底blobの検索方法を変更します。これは複数の型付き配列が一つのペイロードを共有するときに動くコードです。

攻撃フロー

flowchart LR A["Cache Componentsのルートへの
未認証リクエスト"] --> B["use cache関数が
複数の型付き配列を返す"] B --> C["Flightプロトコルが結果を
チャンク化したform-dataエントリへ変換"] C --> D["攻撃者の影響するエントリが
内部チャンクと平坦なキースペースを共有"] D --> E["デシリアライザーが内部モデルまたは
サーバー参照としてエントリを解決"] E --> F["thenableの混同や
未検証の参照IDを受け入れる"] F --> G["requireModuleが参照を解決し
コードが実行される"]

欠けていたチェックはDとEです。修正前は、解決の前にエントリの種類やサーバー参照の識別子の型を検証していませんでした。

攻撃者に可能なこと

悪用に成功すると、Next.jsサーバープロセスとして任意のコードが実行されます。そのプロセスは通常、デプロイ用シークレット、データベース接続、サービス認証情報を保持し、アプリケーションが到達できるものをすべて読み書きできます。CVSS v4.0ベクトル(CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:H/SC:H/SI:H/SA:N)は、脆弱なシステムと後続システムの両方で機密性と完全性への影響を高、可用性は脆弱なシステムだけを高と評価しています。

アドバイザリに記載された範囲で、攻撃者に必要な条件は次のとおりです。

  • アプリケーションがNext.js 16.0.0~16.4.0を使用し、App RouterとCache Componentsを有効にしている
  • 複数の型付き配列を返すuse cache関数がある
  • 攻撃は未認証でユーザー操作不要。ただしCVSSベクトルでは攻撃要件ありとされ、上記の機能に依存する発生条件に対応

そのような関数がなくてもアップグレードするよう求めるVercelの指示は、この境界を確実な防御と見なすべきではないことを示唆しています。アプリのコードは変化し、通信機構は共有基盤だからです。

修正が機能する理由

パッチコミットa4cea6aは、サーバーとクライアント、webpackとturbopack、開発と本番という全ビルド対象で、同梱のReact Server Componentsランタイムを置き換えます。4つの変更が、それぞれデシリアライゼーション境界の信頼上の欠陥を一つ閉じます。

-function createModel(response, model) {
-  return model;
+function createModel(response, model, parentObject, key) {
+  return "then" === key && "function" === typeof model ? null : model;
 }

 function loadServerReference(response, metaData, parentObject, key) {
+  if ("then" === key) return null;
+  var id = metaData.id;
+  if ("string" !== typeof id) return null;
   ...

デシリアライズされたデータ内のthen関数は除去されるため、再構築されたオブジェクトがPromiseに見せかけることはできなくなります。サーバー参照は解決や読み込みの前に文字列識別子を持つ必要があります。レスポンスオブジェクトはプロパティ走査で届かない場所に置かれます。エントリの種類別分類と型付き配列のシリアライズ修正により、チャンクの種類は攻撃者が選ぶキーではなく保存先から決まります。

修正は完全でしょうか。Next.jsが提供する全対象である12種類の同梱ランタイムすべてで、パッチが触れる欠陥を閉じます。元の報告が一つの経路を使ったのか、複数を組み合わせたのかは、Vercelが詳細を公開していないため公開資料からは確認できません。ただし、どの経路でもデシリアライザーに入る際に追加チェックを通るようになり、修復はこの類型をカバーします。

侵害されたかを確認する方法

このアドバイザリには侵害指標が公開されていません。公開ガイダンスがないため、次の一般的な兆候を探してください。

  • Cache Components配下のルートへの予期しないPOST通信。特に、通常のフォームフィールドではなくシリアライズ用接頭辞のフィールド名を持つform-dataボディ
  • キャッシュハンドラーがキーを記録する場合、キーやペイロードが不正に見えるエントリ、または正当なキャッシュ書き込みと対応しないチャンクIDを含むエントリ
  • 自社コードと一致しない、サーバー参照の解決やモデルチャンクの初期化エラーなど、flightデシリアライザーのサーバー側スタックトレース
  • そうしたエラーの前後のコード実行エビデンス。新しいファイル、サーバープロセスからの外向き接続、環境状態の変更など

疑わしい動きが見つかった場合、サーバープロセスが完全に侵害されたものとして扱ってください。デプロイトークン、データベース認証情報、APIキーなど、読み取り可能なすべてのシークレットをローテーションし、正常と確認できる状態から再構築します。

経緯

  • 2026年10月14日:VercelがGHSA-673q-mjm6-r5xrとNext.js 16.4.1を公開。Server Component通信機構の修正を含む(2026年10月14日作成のコミットa4cea6a)。
  • 2026年10月22日:GitHub Advisory Databaseがアドバイザリを公開・レビュー。
  • 2026年10月23日:本記事を公開。公開PoCはなく、実環境の悪用は確認されておらず、CISA KEVカタログにも未登録。

よくある質問

この問題にCVEはあるか?

2026年10月23日時点で、アドバイザリGHSA-673q-mjm6-r5xrにCVE識別子はありません。GitHub Advisory DatabaseでGHSA IDにより追跡されています。

影響を受けるにはCache Componentsを有効にする必要があるか?

アドバイザリは、App RouterとCache Componentsを使い、複数の型付き配列を返すuse cache関数があるアプリケーションの脆弱性として説明しています。ただし、Vercelはそのような関数がなくても全ユーザーに即時アップグレードを求めています。16.4.1はImage OptimizationのRCEも修正するため、実務上はいずれの場合もアップグレードすべきです。

型付き配列とは何か。複数であることが重要な理由は?

Uint8Arrayなどの型付き配列は、メモリブロック上の固定長のバイナリビューです。flightプロトコルでは、それぞれが独自のキーを持つ個別チャンクとしてシリアライズされます。そのため、複数の型付き配列を返す関数は、多くのチャンクエントリを含むペイロードを生成します。これが公開された発生条件の構造です。

キャッシュ関数から型付き配列を削除するだけでよいか?

コードから公開された発生条件は取り除けますが、修正にはなりません。Vercelは回避策はないとして即時アップグレードを求めています。また、コード変更によって条件が再び成立する可能性があります。16.4.1へアップグレードしてください。

誰が発見し、修正したか?

GitHubユーザーevolutionstormが報告し、GitHub Advisory Databaseで発見者として記載されています。Vercelの担当者が同梱React Server Componentsランタイムの修正を作成し、Vercelのセキュリティチームがアドバイザリを公開しました。

影響するソフトウェアはどれほど普及しているか?

nextパッケージは、npmで2026年10月16~22日の週に44,586,009回ダウンロードされました。JavaScriptエコシステムで最も広く使われるWebフレームワークの一つです。

OstorlabでNext.jsアプリケーションをスキャンし、リポジトリ全体で影響を受ける16.xバージョンとuse cacheの使用を確認してください。

参考資料

  • VercelのアドバイザリGHSA-673q-mjm6-r5xr:https://github.com/vercel/next.js/security/advisories/GHSA-673q-mjm6-r5xr (2026年10月23日確認)
  • ReactのアドバイザリGHSA-xqc2-xf4c-x3h3。react-server-dom-webpack、react-server-dom-turbopack、react-server-dom-parcelの同じ型付き配列RCE。19.0.9、19.1.10、19.2.9、19.3.1で修正:https://github.com/react/react/security/advisories/GHSA-xqc2-xf4c-x3h3 (2026年10月26日確認)
  • GitHub Advisory Database項目(重大度、CVSS v4.0 9.5、CWE-502を2026年10月24日に確認):https://github.com/advisories/GHSA-673q-mjm6-r5xr
  • 修正コミットa4cea6a、「Improve Server Component transport protocol」:https://github.com/vercel/next.js/commit/a4cea6aec5da89d116b8960e113189cf51745d2f (2026年10月23日確認)
  • Next.js 16.4.1リリースノート:https://github.com/vercel/next.js/releases/tag/v16.4.1 (2026年10月23日確認)
  • nextのnpmダウンロード数(2026年10月16~22日の週に44,586,009件):https://api.npmjs.org/downloads/point/last-week/next (2026年10月24日確認)