Sentry Next.js SDKのミドルウェアバイパス(CVE-2026-114139)
SentryはCVE-2026-114139をクリティカル、CVSS v4.0 9.1と評価しています。webpackビルドでは@sentry/nextjs SDKが設定済みtunnelRoute配下の全パスでアプリケーションミドルウェアをスキップしますが、トンネルの書き換えは完全一致のパスだけを処理します。そのため、未認証リクエストがミドルウェア認可なしにトンネルパス配下のルートへ到達できます。影響範囲は@sentry/nextjs 9.36.0~9.47.1、10.75.2未満の10.x、11.0.0-rc.1未満の11.0.0プレリリースです。9.47.2、10.75.2、11.0.0-rc.1で修正済みで、実環境での悪用は確認されていません。
要点
- @sentry/nextjsはNext.jsミドルウェアをラップし、Sentryの「トンネル」リクエストではミドルウェアをスキップできるようにします。このスキップ条件がトンネル自体より広く、トンネルのエンドポイントだけでなく、トンネルパス配下の全リクエストパスがスキップされていました。
tunnelRoute: '/monitoring'に対する/monitoring/fooのような直接の競合や、app/[locale]/...のようなルート先頭の動的セグメントなど、トンネルパス配下に解決されるルートは、ミドルウェアが実行されずにリクエストを受け取ります。そこでの認可をミドルウェアだけが担っている場合、認可が回避されます。- Sentryはクリティカル、CVSS v4.0 9.1と評価し、CWE-693(保護機構の不備)に分類しています。2026年10月24日時点で実環境での悪用は確認されておらず、CISA KEVカタログにも登録されていません。npmパッケージ@sentry/nextjsの2026年10月16~22日のダウンロード数は7,848,686件でした。
- 9.47.2、10.75.2、11.0.0-rc.1にアップグレードしてください。設定変更は不要です。まだアップグレードできない場合は、自社のルートが配下に解決されないパスへtunnelRouteを移すか、Turbopackでビルドするか、ミドルウェアに加えてルート自体でも認可を適用してください。
影響を受けるか
以下の条件をすべて満たす場合に影響を受けます。
- アプリが影響範囲の@sentry/nextjsを使用し、
tunnelRouteオプションを設定している(文字列パスまたはtrue)。 - webpackでビルドしている。Next.js 16以降の
next buildでデフォルトとなるTurbopackビルドは影響を受けません。 - アプリケーションのルートがトンネルパス配下に解決される。
tunnelRoute: '/monitoring'に対する/monitoring/fooの直接の競合、または先頭の任意のパスセグメントに一致するapp/[locale]/...のような動的セグメントが該当します。 - そのルートの認可を適用する場所がミドルウェアだけである。
Sentryのアドバイザリは、バイパスによって生じないことも明記しています。ミドルウェアのスキップ自体がリクエストに権限を与えることはなく、サーバー側でセッションを確認するルートは引き続き保護されます。Sentry自体のサービスと、自社のSentry組織内のデータは影響を受けません。
| パッケージ | 影響を受けるバージョン | 修正バージョン |
|---|---|---|
| @sentry/nextjs 9.x | 9.36.0 – 9.47.1 | 9.47.2 |
| @sentry/nextjs 10.x | 10.0.0-alpha.0 – 10.75.1 | 10.75.2 |
| @sentry/nextjs 11プレリリース | 11.0.0-alpha.0 – 11.0.0-rc.0 | 11.0.0-rc.1 |
インストール済みのものと、該当する条件を確認します。
# Installed SDK version
npm ls @sentry/nextjs
node -e "console.log(require('@sentry/nextjs/package.json').version)"
# Lock file check (package-lock.json v2/v3 records the package under "node_modules/@sentry/nextjs")
grep -A1 '"node_modules/@sentry/nextjs"' package-lock.json
# Is the tunnel route configured?
grep -rn "tunnelRoute" next.config.* sentry.* .sentryclirc 2>/dev/null
# Container image check
docker run --rm <your-image> node -e "console.log(require('@sentry/nextjs/package.json').version)"
次に、トンネルパス配下に解決されるルートを確認します。app/(またはpages/)のディレクトリセグメントを、トンネルパスの先頭セグメントと照合してください。[locale]のようなルート直下の動的セグメントは、すべての先頭セグメントに一致します。
修正方法
SDKをアップグレードしてください。スキップ対象がトンネルの書き換えで実際に処理するリクエストだけになり、設定変更は不要です。
npm install @sentry/nextjs@10.75.2
# 9.x line: npm install @sentry/nextjs@9.47.2
# 11 prerelease line: npm install @sentry/nextjs@11.0.0-rc.1
# or: pnpm add @sentry/nextjs@10.75.2 | yarn add @sentry/nextjs@10.75.2
すぐにアップグレードできない場合、Sentryのアドバイザリは3つの回避策を挙げています。
- 自社ルートが配下に解決されないパスを
tunnelRouteに設定するか、オプションを削除する - Next.js 16以降の
next buildでデフォルトのTurbopackでビルドする - ミドルウェアに加えて、ルート、レイアウト、データアクセス経路でも認可を適用する
回避策には制約があります。最初の方法は、アプリの変化に伴ってもルート構造が競合しないことに依存します。2つ目はビルドパイプラインを変えます。3つ目はミドルウェアで集約するはずだった認可ロジックを重複させます。アップグレードは、すべての呼び出し元に対してSDK内部の不一致を取り除きます。
根本原因
Next.jsのミドルウェアはルートより前に実行され、認可を行う一般的な場所です。@sentry/nextjsがwebpackビルドでミドルウェアを計装すると、ミドルウェア関数をwrapMiddlewareWithSentryでラップします。このラッパーは、まず受信リクエストがSentryのトンネルリクエストか確認し、該当すればアプリのコードを呼ばずに即座に戻ります。
トンネルは広告ブロッカーを回避するためのものです。ブラウザーのイベントを/monitoringなど自社サーバーのパスへ送り、Next.jsの書き換えがSentryへ転送します。この書き換えは、Sentryの組織IDとプロジェクトIDを運ぶoとpのクエリパラメーターが設定された、完全一致するトンネルパスだけを処理します。
スキップはより広い条件を使っていました。修正前のラッパーは、リクエストパスがトンネルパス配下かだけを確認していました。
// packages/nextjs/src/common/utils/tunnelPathnameMatch.ts (before the fix)
export function isPathnameUnderSentryTunnelRoute(pathname: string, tunnelPath: string): boolean {
return pathname === tunnelPath || pathname.startsWith(`${tunnelPath}/`);
}
そして、一致するものすべてでミドルウェアをスキップしていました。
// packages/nextjs/src/common/wrapMiddlewareWithSentry.ts (before the fix)
if (tunnelRoute && typeof tunnelRoute === 'string') {
const req: unknown = args[0];
if (req instanceof Request) {
const url = new URL(req.url);
const isTunnelRequest = isPathnameUnderSentryTunnelRoute(url.pathname, tunnelRoute);
if (isTunnelRequest) {
// returns a response that lets the request continue, without calling
// the wrapped middleware
return new Response(null, { status: 200, headers: { 'x-middleware-next': '1' } });
}
}
}
問題は2つのチェックの差です。書き換えは、有効なoとpのパラメーターを持つ/monitoringを処理します。スキップはパラメーターの有無にかかわらず、/monitoringと/monitoring/で始まるすべてのパスを対象にしていました。/monitoring/fooへのリクエストはSentryへ書き換えられず、Next.jsがアプリケーションへルーティングします。しかしラッパーはすでに戻っているため、ミドルウェアは実行されません。
一文で言えば、ミドルウェアのスキップは「トンネルの書き換えが実際に処理するリクエストか」を判断すべきところで、「このパスはトンネルルート配下か」を判断していました。その2つの集合の差が、ミドルウェアの認証チェックを受けずに自社ルートへ届くリクエストの集合です。
悪用の仕組み
2026年10月24日時点で公開の概念実証(PoC)はなく、実環境での悪用も確認されていません。アドバイザリとパッチが示す攻撃経路は次のとおりです。
- 対象アプリが
tunnelRouteを通常は/monitoringなどのパスに設定し、webpackでビルドします。 - アプリにはトンネルパス配下に解決されるルートがあります。直接の競合、または
/monitoringをロケール値として扱うapp/[locale]/page.tsxのようなルート先頭の動的セグメントです。 - 攻撃者がそのルートパスに未認証リクエストを送ります。
- SDKのミドルウェアラッパーがトンネルルート配下のパスと判断し、続行レスポンスを返します。認可ロジックを含むアプリのミドルウェア本体は一度も実行されません。
- Next.jsがリクエストをルートハンドラーに振り分けます。ハンドラーからデータまでの間でセッションを再確認しなければ、ミドルウェアを通過したかのようにリクエストが処理されます。
攻撃は通常のHTTPリクエストです。何を達成できるかは、認証リダイレクト、テナントチェック、機能制限、ルートレベルの認可など、アプリのミドルウェアだけが守っていた内容に完全に依存します。
攻撃フロー
未認証リクエスト"] --> B["SDKミドルウェアラッパーが
トンネルルート配下と判定"] B --> C["ラッパーが続行レスポンスを返し
ミドルウェアは実行されない"] C --> D["トンネル書き換えに一致せず
Next.jsがアプリへルーティング"] D --> E["ルートハンドラーがミドルウェアの
認可なしにリクエストを処理"] E --> F["影響はミドルウェアだけが
保護していた内容に依存"]
不備のあるチェックはBです。スキップ判断の範囲が、そのために存在する書き換えの範囲より広くなっています。
攻撃者に可能なこと
影響を受けるルートがミドルウェアのチェックなしで公開するものを読み取り、操作できます。アドバイザリは、影響を脆弱なシステムの機密性と完全性に限定しています。CVSS v4.0ベクトルはAV:N/AC:L/AT:P/PR:N/UI:Nで、権限やユーザー操作は不要です。攻撃要件ありとされるのは、tunnelRouteの設定、webpackビルド、トンネルパス配下に解決されるルート、ミドルウェアだけでの認可という前提が揃う必要があるためです。
アドバイザリによれば、バイパス自体は権限を付与せず、サーバー側でセッションを確認するルートは保護されます。Sentry自体のサービスと、自社のSentry組織のデータは影響を受けません。
修正が機能する理由
プルリクエスト#24499とバックポート#24565、#24760の修正は、パスの前方一致テストを、書き換えが処理する内容と完全に一致する関数に置き換えます。
// packages/nextjs/src/common/utils/tunnelPathnameMatch.ts (after the fix)
/**
* Returns true only for requests the tunnel rewrite (see `setUpTunnelRewriteRules`) would serve.
*
* This decides whether the user's middleware is skipped, so it must never be broader than the rewrite:
* anything it matches that Next.js does not rewrite to Sentry reaches the app without middleware.
*/
export function isSentryTunnelRequest(request: Request, tunnelPath: string): boolean {
// The SDK transport only ever sends POST requests
if (request.method !== 'POST') {
return false;
}
const url = new URL(request.url);
if (url.pathname !== tunnelPath && url.pathname !== `${tunnelPath}/`) {
return false;
}
// Next.js evaluates `has` conditions against the last value of a repeated query param, so every value has to qualify
return ['o', 'p'].every(key => {
const values = url.searchParams.getAll(key);
return values.length > 0 && values.every(value => /^\d+$/.test(value));
});
}
ラッパーは前方一致テストの代わりにisSentryTunnelRequest(req, tunnelRoute)を呼ぶようになりました。両側を一致させる特徴は3つです。POSTリクエストだけであること(SDKの通信処理は他のメソッドを送りません)、末尾スラッシュの有無を除いて完全一致するトンネルパスであること、oとpのパラメーターが存在し、すべて数字であることです。これは、Next.jsが書き換えのhas条件を評価する方法に対応しています。いずれかのチェックに失敗したリクエストは、他の通常のリクエストと同じようにミドルウェアを通ります。
説明した不一致に対する修正は完全です。スキップと書き換えは、コードコメントで不変条件として明記された、同じトンネルリクエストの定義を共有します。ラッパーは引き続きwebpackビルドにのみ存在します。Turbopackビルドでは元々有効でなかったため、影響もありませんでした。
侵害されたかを確認する方法
このアドバイザリでは侵害指標が公開されておらず、悪用も確認されていません。影響を受ける構成を運用していてパターンを監査したい場合は、次を確認してください。
- WebサーバーやNext.jsのアクセスログで、トンネルパス配下のルートに到達した未認証リクエストを探し、ミドルウェアが拒否またはリダイレクトするはずだったものと照合する。
oとpのパラメーターがない/monitoring/...形式のパスへのリクエストや、ミドルウェアが遮断するはずの送信元から/en/...などルート先頭の動的セグメントへのリクエストが対象 - 影響を受けるルート自身のサーバー側処理をレビューし、ミドルウェアで呼び出し元が認証済みと想定している箇所を確認する
ミドルウェアで止めるべきなのに止まらなかったリクエストが見つかった場合、そのセッションは未認証でルートに到達したものとして扱い、ルートが返した内容を評価してください。
経緯
- 2026年9月18日:mainブランチに修正を反映(コミット878b685、「Align tunnel request matching in middleware with tunnel rewrite」)。
- 2026年9月21日:v10へのバックポートを反映(コミットd525a2f)。Sentryが2026年9月22日に11.0.0-rc.1と10.75.2をリリース。
- 2026年9月24日:SentryがアドバイザリGHSA-mchm-gjx6-7h55を公開。
- 2026年9月28日:v9へのバックポートを反映(コミットc122aac)。Sentryが2026年9月29日に9.47.2をリリース。
- 2026年10月21日:NVDがCVE-2026-114139を公開。
- 2026年10月22日:GitHub Advisory Databaseでアドバイザリを公開・レビュー。
- 2026年10月24日:本記事を公開。実環境での悪用は確認されておらず、CISA KEVカタログにも未登録。
よくある質問
デフォルト設定も影響を受けるか?
トンネルルートはオプトインなので、tunnelRouteのないデフォルトのwithSentryConfigは影響を受けません。アドバイザリの条件が完全なチェックリストです。tunnelRouteが設定されていること、webpackビルドであること、トンネルパス配下に解決されるルートがあること、ミドルウェアだけで認可していることです。
Turbopackビルドも影響を受けるか?
いいえ。スキップを行うミドルウェアラッパーは、webpack連携だけに存在します。Next.js 16以降のnext buildでデフォルトのTurbopackには、元々このスキップがありません。SDK自身のコードコメントはこれを、修正後にも残るビルド間の一貫性の問題として記載しています。
攻撃者が自社のSentry組織へ侵入できるか?
いいえ。Sentryのアドバイザリは、Sentry自体のサービスや自社のSentry組織内のデータに影響はないとしています。バイパスの対象はSentryではなく、自社アプリケーションのルートです。
監視用SDKなのに重大度がクリティカルである理由は?
影響はSDKではなくミドルウェアに依存するためです。競合するルートでミドルウェアが唯一の認可境界である場合、未認証のネットワークリクエストがそこに到達します。CVSS v4.0ベクトルは、機密性と完全性への影響を高とし、9.1と評価しています。SentryはCWE-693(保護機構の不備)にも分類しています。
ミドルウェアを認可ではなくリダイレクトに使っていてもアップグレードすべきか?
はい。都合のよいタイミングでアップグレードしてください。リダイレクトなど認可以外の用途ではセキュリティ上の影響はありませんが、ルート構造は変化します。また、このアップグレードに破壊的変更はありません。
OstorlabでNext.jsアプリケーションをスキャンし、リポジトリ全体の@sentry/nextjsのバージョンとtunnelRouteの使用状況を確認してください。
参考資料
- SentryのアドバイザリGHSA-mchm-gjx6-7h55:https://github.com/getsentry/sentry-javascript/security/advisories/GHSA-mchm-gjx6-7h55 (2026年10月24日確認)
- GitHub Advisory Database項目:https://github.com/advisories/GHSA-mchm-gjx6-7h55 (2026年10月24日確認)
- CVE-2026-114139レコード(CVSS v4.0 9.1、CWE-693、影響範囲):https://cveawg.mitre.org/api/cve/CVE-2026-114139 (2026年10月24日確認)
- 修正プルリクエスト#24499:https://github.com/getsentry/sentry-javascript/pull/24499 (2026年10月24日確認)
- 修正コミット878b685(mainブランチ):https://github.com/getsentry/sentry-javascript/commit/878b685c85dc12045e47e1932c96f5381d7ac532 (2026年10月24日確認)
- v10バックポートコミットd525a2f:https://github.com/getsentry/sentry-javascript/commit/d525a2f6015b47384bc139c30d58e0d5435d52e5 (2026年10月24日確認)
- v9バックポートコミットc122aac:https://github.com/getsentry/sentry-javascript/commit/c122aac4f29541eb6da494296822c91eab3cf5ae (2026年10月24日確認)
- 10.75.2リリース(2026年9月22日公開):https://github.com/getsentry/sentry-javascript/releases/tag/10.75.2
- 9.47.2リリース(2026年9月29日公開):https://github.com/getsentry/sentry-javascript/releases/tag/9.47.2
- 11.0.0-rc.1リリース(2026年9月22日公開):https://github.com/getsentry/sentry-javascript/releases/tag/11.0.0-rc.1
- @sentry/nextjsのnpmダウンロード数(2026年10月16~22日の週に7,848,686件):https://api.npmjs.org/downloads/point/last-week/@sentry/nextjs (2026年10月24日確認)