この記事の対象読者
- React RouterまたはRemixでWebアプリを開発している方
- サーバーサイドでセッション管理を実装したことがある方
- 最近のReactエコシステムのセキュリティ動向を追いたい方
- 「パストラバーサル」という言葉を聞いたことがある方
この記事で扱わないこと
- React Routerの基本的な使い方
- セッション管理の一般的な実装パターン
- WAFやファイアウォールの詳細な設定方法
この記事で得られること
- CVE-2025-61686の技術的な仕組みを理解できる
- 自分のプロジェクトが影響を受けるかどうか判断できる
- 適切なパッチ適用と対策を実施できる
はじめに - またReact界隈で脆弱性かよ
正直、この見出しを書くのは気が重い。
2025年12月のReact2Shell(CVE-2025-55182)の騒動がようやく落ち着いてきたと思ったら、今度はReact Routerだ。2026年1月8日、React Routerのメンテナがセキュリティアドバイザリを公開した。CVE-2025-61686、CVSS 9.1。「Critical」に分類される深刻な脆弱性だ。
「え、また?」と思った人、その気持ちはわかる。でも残念ながら、これは別の話だ。
React2Shellがサーバーコンポーネントのデシリアライゼーションを突いた脆弱性だったのに対して、今回のCVE-2025-61686はセッションストレージのパストラバーサルを突いている。攻撃ベクトルも影響範囲も違う。
ただし、一つだけ共通点がある。デフォルト設定が危ないということだ。
CVE-2025-61686とは何か
公式による説明
まずはGitHubのセキュリティアドバイザリから引用しよう。
If you are using createFileSessionStorage() from @react-router/node (or @remix-run/node/@remix-run/deno in Remix v2) with an unsigned cookie, it is possible for an attacker to cause the session to try to read/write from a location outside the specified session file directory.
出典: GitHub Security Advisory GHSA-9583-h5hc-x8cw
日本語にするとこうなる。
「@react-router/nodeのcreateFileSessionStorage()を署名されていないCookieと共に使用している場合、攻撃者がセッションに対して指定されたセッションファイルディレクトリの外部から読み書きを試みさせることが可能です。」
つまり、セッションIDをいじることで、サーバー上の任意のファイルにアクセスできる可能性があるということだ。
何が問題なのか
createFileSessionStorage()は、React RouterやRemixでファイルベースのセッション管理を行うための関数だ。ユーザーのセッション情報をサーバーのファイルシステムに保存する、まあ古典的なアプローチ。
通常、セッションIDはCookieで管理される。で、このCookieには「署名」というセキュリティ機構がある。署名されたCookieは改ざんを検知できるから、悪意のある値を注入されても弾ける。
問題は、署名されていないCookieを使っている場合だ。
攻撃者は、Cookieの値にパストラバーサルシーケンス(../のこと)を仕込める。たとえばセッションIDに../../../../etc/passwdみたいな値を入れると、セッションファイルの保存先がそっちに向けられてしまう。
OffSeqの分析によると、この脆弱性は以下のように分類される。
CVE-2025-61686 is a critical security vulnerability classified under CWE-22 (Improper Limitation of a Pathname to a Restricted Directory, or Path Traversal) affecting the React Router and Remix Run frameworks.
日本語訳:「CVE-2025-61686はCWE-22(パストラバーサル:パス名の不適切な制限)に分類される重大なセキュリティ脆弱性で、React RouterおよびRemix Runフレームワークに影響する。」
CWE-22は、古くからあるパストラバーサル攻撃の分類だ。Webセキュリティの教科書には必ず載っている、いわば「基本のキ」。それがReact Routerに存在していたというのは、なかなか衝撃的な話だ。
技術的な仕組み - 何が起きているのか
パストラバーサル攻撃の基本
まず、パストラバーサル攻撃について軽くおさらいしよう。
ファイルパスを扱うプログラムがあるとする。たとえば「ユーザーが指定したファイル名でセッションを保存する」みたいな処理。
/var/sessions/abc123 ← 正常なセッションファイル
ここで、ユーザーが入力した値をそのままファイルパスに使ってしまうと、こうなる。
入力: ../../../etc/passwd
結果: /var/sessions/../../../etc/passwd → /etc/passwd
../は「一つ上のディレクトリ」を意味する。これを繰り返すことで、本来アクセスできないはずのディレクトリに到達できてしまう。これがパストラバーサル攻撃の原理だ。
CVE-2025-61686の攻撃シナリオ
では、今回の脆弱性ではどうなるか。
TheHackerWireの記事がわかりやすく解説している。
The core issue lies within createFileSessionStorage(). When a web application uses this function, it expects a session cookie to dictate where session data lives. But if that cookie isn't signed, the application doesn't properly validate the incoming path. It trusts user input too much.
出典: TheHackerWire
日本語訳:「核心的な問題はcreateFileSessionStorage()内にある。Webアプリケーションがこの関数を使う場合、セッションCookieがセッションデータの保存場所を決定することを想定している。しかしそのCookieが署名されていない場合、アプリケーションは入力されたパスを適切に検証しない。ユーザー入力を信用しすぎている。」
攻撃者は以下の手順で攻撃を実行できる。
ステップ1: 脆弱なアプリケーションにアクセス
ステップ2: セッションCookieを細工する。値に../../を含めてパストラバーサルを仕込む
ステップ3: 細工したCookieでリクエストを送信
ステップ4: サーバーがセッションファイルを読み書きしようとする際、指定外のパスにアクセス
攻撃の成否を分けるもの
ただし、この攻撃には制限がある。公式アドバイザリによると、
Read files cannot be returned directly to the attacker. Session file reads would only succeed if the file matched the expected session file format.
日本語訳:「読み取ったファイルは攻撃者に直接返却されない。セッションファイルの読み取りは、ファイルが期待されるセッションファイルフォーマットに一致した場合のみ成功する。」
つまり、単純に/etc/passwdを読めるわけではない。読み取られたファイルの内容がセッションファイルのフォーマットに合致していないと、パースに失敗する。また、読み取ったデータは攻撃者に直接返されるわけではなく、サーバーサイドのセッションに格納されるだけだ。
じゃあ大したことないのか?そうとも言えない。
Cybersecurity Newsの記事では、こう警告している。
If the targeted file—such as a configuration file, environment variable file (.env), or system credential store—matches the internal format expected by the session parser, the server could inadvertently process that sensitive data.
日本語訳:「設定ファイル、環境変数ファイル(.env)、システム認証情報ストアなど、ターゲットにされたファイルがセッションパーサーが期待する内部フォーマットに一致した場合、サーバーはその機密データを意図せず処理してしまう可能性がある。」
攻撃者が巧妙にファイルを選べば、機密情報がセッションに取り込まれ、アプリケーションのロジック次第ではそれが漏洩する可能性がある。さらに、ファイルの書き込みができるなら、任意のファイルを上書きしてシステムを破壊したり、セッションポイズニング(セッションの汚染)でDoS攻撃を仕掛けたりすることも可能だ。
React2Shellとの違い
先月話題になったReact2Shell(CVE-2025-55182)との違いを整理しておこう。
React2Shell(CVE-2025-55182)
これは私が以前Qiitaで解説した脆弱性だ。
参考: Reactの致命的脆弱性、React2Shellとは? - CVSS 10.0のヤバすぎる穴を解説
React2Shellは、React Server Components(RSC)のFlightプロトコルにおけるデシリアライゼーション脆弱性だった。攻撃者は細工したペイロードを送りつけることで、認証なしでサーバー上で任意のコードを実行できた。CVSS 10.0、最大深刻度。
CVE-2025-61686
今回のCVE-2025-61686は、React RouterのcreateFileSessionStorage()におけるパストラバーサル脆弱性だ。攻撃者はセッションCookieを細工することで、セッションディレクトリ外のファイルを読み書きできる。CVSS 9.1。
比較まとめ
影響するコンポーネント
- React2Shell: react-server(RSC/Flightプロトコル)
- CVE-2025-61686: @react-router/node、@remix-run/node、@remix-run/deno
攻撃ベクトル
- React2Shell: 悪意のあるFlightペイロード
- CVE-2025-61686: 細工されたセッションCookie
影響
- React2Shell: リモートコード実行(RCE)
- CVE-2025-61686: 任意ファイルの読み書き
前提条件
- React2Shell: RSCをサポートしていればデフォルトで脆弱
- CVE-2025-61686:
createFileSessionStorage()を署名なしCookieで使用している場合のみ脆弱
重要なのは、両者は別物だということ。React2Shellのパッチを当てたからといって、CVE-2025-61686が修正されるわけではない。逆も然り。
影響を受けるバージョンと環境
脆弱なパッケージバージョン
NVDおよびGitHub Security Advisoryによると、以下のバージョンが影響を受ける。
@react-router/node
- 脆弱: 7.0.0 〜 7.9.3
- 修正済み: 7.9.4以降
@remix-run/deno
- 脆弱: 2.17.1以前
- 修正済み: 2.17.2以降
@remix-run/node
- 脆弱: 2.17.1以前
- 修正済み: 2.17.2以降
脆弱性の発動条件
ここが重要だ。すべてのReact Router/Remixユーザーが影響を受けるわけではない。
脆弱性が発動するには、以下の条件を両方満たす必要がある。
条件1: createFileSessionStorage()を使用している
これはファイルベースのセッションストレージを使う場合の関数だ。代替としてcreateCookieSessionStorage()やcreateMemorySessionStorage()を使っている場合は、この脆弱性の影響を受けない。
条件2: セッションCookieが署名されていない
React Routerの公式ドキュメントには、Cookieに署名をつけることが推奨されている。でも、サンプルコードをそのままコピペしたり、「とりあえず動けばいい」で実装したりすると、署名なしになっているケースがある。
Purple Opsの分析では、動作モードによる影響の違いを指摘している。
Framework Mode: This mode includes server-side features, automatic code splitting, and full-stack data loading. It is the primary target for CVE-2025-61686.
Declarative Mode (): Users utilizing traditional client-side routing with are not impacted by the server-side session vulnerabilities.
出典: Purple Ops
日本語訳:「Framework Mode:このモードはサーバーサイド機能、自動コード分割、フルスタックデータ読み込みを含む。CVE-2025-61686の主要なターゲットである。Declarative Mode():従来のクライアントサイドルーティングを使用しているユーザーは、サーバーサイドセッションの脆弱性の影響を受けない。」
つまり、React Router 7の「Framework Mode」を使っている場合がリスク高で、昔ながらの<BrowserRouter>でクライアントサイドルーティングだけやっている場合は影響なし。
今すぐやるべき対策
1. バージョンアップ(最優先)
これが唯一かつ最優先の対策だ。
@react-router/nodeを使っている場合
npm install @react-router/node@7.9.4
または
yarn add @react-router/node@7.9.4
Remix v2を使っている場合
npm install @remix-run/node@2.17.2 @remix-run/deno@2.17.2
Security Online Infoによると、React Router mainパッケージ全体としては7.12.0または7.9.6への更新が推奨されている。
Patches have been released across the board, with safe versions generally starting at 7.12.0 or 7.9.6 for the main router package.
2. 署名付きCookieへの移行
もしまだ署名なしCookieを使っているなら、この機会に移行しよう。React Routerの公式ドキュメントでは、Cookieへの署名が推奨されている。
// 悪い例: 署名なし
const sessionStorage = createFileSessionStorage({
dir: "/sessions",
cookie: {
name: "__session",
// secrets がない = 署名なし
},
});
// 良い例: 署名あり
const sessionStorage = createFileSessionStorage({
dir: "/sessions",
cookie: {
name: "__session",
secrets: [process.env.SESSION_SECRET], // 署名用のシークレット
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
httpOnly: true,
},
});
secretsオプションを指定することで、Cookieに署名が付与される。署名されたCookieは改ざんを検知できるため、パストラバーサルシーケンスを注入されても弾ける。
3. セッションストレージ方式の見直し
そもそもcreateFileSessionStorage()を使う必要があるのか?という話。
代替案1: createCookieSessionStorage()
セッションデータをCookie自体に保存する。ファイルシステムへのアクセスがないため、パストラバーサルの余地がない。ただし、Cookieのサイズ制限(約4KB)があるので、大量のセッションデータを扱う場合には向かない。
代替案2: createMemorySessionStorage()
セッションをメモリに保存する。開発環境向けで、本番環境では使わないこと(サーバー再起動でセッションが消える)。
代替案3: Redis/データベースセッション
本番環境でスケーラビリティを求めるなら、Redisやデータベースを使ったセッション管理が一般的。これならファイルシステムの脆弱性は関係なくなる。
4. 自分が影響を受けるかの確認
以下のコマンドでパッケージのバージョンを確認できる。
# npm の場合
npm list @react-router/node @remix-run/node @remix-run/deno
# yarn の場合
yarn list @react-router/node @remix-run/node @remix-run/deno
また、コードベースでcreateFileSessionStorageを検索して、署名の有無を確認しよう。
grep -r "createFileSessionStorage" ./src
見つかったら、secretsオプションが指定されているかどうかをチェックする。
同時に公開された関連脆弱性
CVE-2025-61686と同じタイミングで、React Router/Remixには複数の脆弱性が公開されている。まとめて対応しておくことを推奨する。
CVE-2025-59057: Meta Component XSS
CVSS 7.6。script:ld+jsonタグ生成時のXSS脆弱性。SSRで信頼できないコンテンツを使用した場合に任意のJavaScriptが実行される可能性がある。
ScrollRestoration XSS
CVSS 8.2。<ScrollRestoration>APIのgetKey/storageKeyプロパティを使用した場合のXSS脆弱性。
CVE-2026-22029: Open Redirect XSS
CVSS 8.0。SPAナビゲーション時のオープンリダイレクトによるXSS。loadersやactionsからの安全でないURLへのリダイレクトが可能。
CVE-2026-22030: CSRF脆弱性
Framework Modeでサーバーサイドルートアクションハンドラーを使用している場合のCSRF脆弱性。
CVE-2025-68470: 外部リダイレクト
攻撃者が細工したパスにより、navigate()、<Link>、redirect()を通じて外部URLにリダイレクトされる可能性がある。
やってはいけないこと
「うちはRemixじゃなくてNext.jsだから関係ない」と安心する
確かにNext.jsはReact Routerを使っていない。でも、Next.jsには先月のReact2Shellが直撃している。そっちの対応は済んでいるか?
脆弱性は一つ対応して終わりじゃない。Reactエコシステム全体が攻撃対象になっている今、包括的なセキュリティレビューが必要だ。
「署名付きCookieにしたからOK」で終わらせる
署名はあくまでも改ざん検知の仕組みであって、暗号化ではない。署名付きでもCookieの中身は平文で読める。機密情報をCookieに入れてはいけない。
また、secretsに使う値は十分に長くランダムなものにすること。"mysecret"とかはダメだ。
バージョンアップだけして動作確認しない
セキュリティパッチは時として破壊的変更を含むことがある。特にセッション管理周りは、既存のセッションが無効化される可能性もある。本番環境に適用する前に、必ずステージング環境でテストしよう。
まとめ
CVE-2025-61686は、React RouterおよびRemixのcreateFileSessionStorage()に存在するパストラバーサル脆弱性だ。CVSS 9.1のCritical評価。
影響を受ける条件
-
createFileSessionStorage()を使用している - かつ、セッションCookieが署名されていない
今すぐやること
- @react-router/nodeを7.9.4以降に更新
- @remix-run/node、@remix-run/denoを2.17.2以降に更新
- 署名なしCookieを使っているなら、署名付きに移行
先月のReact2Shellに続いて、またしてもReactエコシステムに深刻な脆弱性が見つかった。正直なところ、「こうも立て続けに出るか」という思いはある。
ただ、見方を変えれば、これはセキュリティ研究者がReactエコシステムを真剣に監査し始めているということでもある。隠れていた問題が次々と表面化しているフェーズだと思えば、長期的には良いことかもしれない。
今できることは、パッチを当てること。そして、自分のコードベースを見直すこと。「デフォルト設定は安全」という幻想は、もう捨てた方がいい。
参考文献
公式情報
-
GitHub Security Advisory GHSA-9583-h5hc-x8cw(React Router)
https://github.com/remix-run/react-router/security/advisories/GHSA-9583-h5hc-x8cw -
NVD CVE-2025-61686
https://nvd.nist.gov/vuln/detail/CVE-2025-61686 -
React Router公式ドキュメント - Sessions and Cookies
https://reactrouter.com/explanation/sessions-and-cookies
セキュリティベンダーの分析
-
Security Online Info: Critical React Router Flaws
https://securityonline.info/critical-react-router-flaws-cve-2025-61686-exposes-server-files/ -
Cybersecurity News: React Router Vulnerability
https://cybersecuritynews.com/react-router-vulnerability/ -
Purple Ops: CVE-2025-61686 Analysis
https://www.purple-ops.io/resources-hottest-cves/react-router-cve-2025-61686/ -
TheHackerWire: CVE-2025-61686 React Router
https://www.thehackerwire.com/cve-2025-61686-react-router-is-a-router-for-react/ -
OffSeq Threat Radar: CVE-2025-61686
https://radar.offseq.com/threat/cve-2025-61686-cwe-22-improper-limitation-of-a-pat-74207ab3
関連記事
- Reactの致命的脆弱性、React2Shellとは?(筆者Qiita記事)
https://qiita.com/GeneLab_999/items/b6dc2cec308dfe35f357