[緊急解説] 9router (Next.jsベース) の認証バイパス脆弱性 (CVE-2026-56681)
はじめに:9routerの深刻な認証バイパス脆弱性
日本のNext.js開発者の皆さん、こんにちは。今回は、9routerアプリケーション(Next.jsをベースに構築されています)に発見された、深刻度「High」の認証バイパス脆弱性(GHSA-5mj8-gf6m-fhw8 / CVE-2026-56681)について解説します。この脆弱性は、特定のデプロイモードにおいて、攻撃者がAPIキーなしでLLM(大規模言語モデル)のAPIにアクセスできてしまうというものです。皆さんのプロジェクトで9routerを使用している場合、あるいは同様の認証ロジックを実装しているNext.jsアプリケーションを運用している場合は、特に注意が必要です。
脆弱性の概要:`X-9r-Real-Ip`ヘッダを用いた認証バイパス
この脆弱性の核心は、9routerがリクエストがローカルホスト(127.0.0.1)から発信されたものかを判断する際に、信頼できないHTTPリクエストヘッダ `X-9r-Real-Ip` を信用してしまう点にあります。通常、このヘッダは、TCPソケットアドレスからIPアドレスを安全に抽出し、サニタイズする役割を持つ専用のラッパー(`custom-server.js`)によって生成されることを想定していました。しかし、この`custom-server.js`ラッパーを使用しないデプロイモードでは、クライアントから送信された`X-9r-Real-Ip`ヘッダがそのままNext.jsアプリケーションに渡されてしまいます。
その結果、未認証のリモート攻撃者は、単純にリクエストに`X-9r-Real-Ip: 127.0.0.1`というヘッダを追加するだけで、アプリケーションを「ローカルクライアント」であると誤認させることができます。これにより、本来APIキーの認証が必要なPublic LLM API(例:`/api/v1/*`)へのアクセス制限がバイパスされ、未認証でのアクセスが可能になってしまいます。
詳細解説:なぜ認証がバイパスされるのか?
具体的なコードレベルでは、`src/dashboardGuard.js`内の`isLocalRequest()`関数が問題の中心です。この関数は、クライアントから提供された`X-9r-Real-Ip`ヘッダを読み取り、その値がループバックアドレス(127.0.0.1)であれば、リクエストをローカルからのものとして分類します。そして、`canAccessPublicLlmApi()`関数は、`isLocalRequest()`が`true`を返した場合、LLM API (`/api/v1/*`) へのアクセスを許可し、APIキーの検証をスキップしてしまいます。
問題の根本原因は、認証レイヤーがクライアント側で制御可能なHTTPヘッダに基づいてセキュリティ判断を行っていることにあります。設計上は、このヘッダは信頼された`custom-server.js`ラッパーのみが設定でき、かつ外部からの入力は除去されるはずでした。しかし、このラッパーなしでアプリケーションが直接公開されると、Next.jsは攻撃者によって提供されたヘッダをそのまま通してしまうため、この信頼の前提が破綻します。脆弱性が確認された製品バージョンは9router-app 0.5.4 (Next.js 16.2.9) です。
具体的な攻撃シナリオ
攻撃は以下のような手順で実行されます:
1. 9routerのインスタンスが`custom-server.js`を使用しないモードでデプロイされており、LLM APIが攻撃者からアクセス可能である(デフォルトでは0.0.0.0でバインドされている)。
2. 攻撃者は`/api/v1/models`のようなLLM APIエンドポイントに通常のリクエストを送信し、APIキーが不足しているため「401 Unauthorized」を受け取る。
3. 攻撃者は、同じリクエストに`X-9r-Real-Ip: 127.0.0.1`というヘッダを1つ追加して再送信する。
4. アプリケーションはリクエストをローカルからのものと分類し、APIキーチェックをスキップする。結果、攻撃者はオーナーのモデルカタログを含む「200 OK」レスポンスを受け取り、LLM APIへの継続的なアクセス権を得る。
この脆弱性がもたらす深刻な影響
この認証バイパスが成功した場合、未認証のリモート攻撃者は、正規のAPIキーなしでLLM APIを利用できる「信頼されたローカルクライアント」として振る舞うことができます。これにより、以下のような深刻な影響が発生する可能性があります。
<ul><li>インスタンスオーナーが設定したLLMプロバイダ接続の不正利用。</li><li>有料APIクレジットの消費、およびインスタンスオーナーへの金銭的損失。</li><li>プロキシを介したアップストリームプロバイダアカウントの悪用。</li><li>設定されているプロバイダや利用可能なモデルの列挙(情報漏洩)。</li></ul>
フロントエンドエンジニアが取るべき対策
Next.jsアプリケーションの開発者として、この種の脆弱性から身を守るために以下の対策を検討してください。
最も重要な対策は、クライアントから直接送信されるHTTPヘッダ(特に`X-9r-*`のようなカスタムヘッダ)を、セキュリティ上の判断材料として無条件に信用しないことです。IPアドレスなどの認証関連情報は、信頼できるトランスポート層のソースから取得すべきです。
クライアントのIPアドレスを判断する際は、`req.socket.remoteAddress`のような、プロキシやクライアントによって偽装されにくい低レベルのソケット情報を使用することを検討してください。これは、`X-Forwarded-For`のようなプロキシヘッダよりも信頼性が高い場合が多いです。ただし、リバースプロキシやロードバランサーを使用している場合は、それらが設定する信頼できるヘッダ(例えば、適切に構成された`X-Forwarded-For`)を慎重に検証する必要があります。
`custom-server.js`がセキュリティモデルに不可欠な役割を果たす場合、そのラッパーを利用しないデプロイモードは避けるべきです。もし利用できない場合は、アプリケーションのエッジ(リバースプロキシやロードバランサーなど)で、クライアントから送られてくる`X-9r-*`ヘッダを明示的に除去または拒否する設定を導入してください。また、`custom-server.js`が存在しない場合は、セキュリティ的にフェイルクローズ(アクセスを拒否)するようなロジックも検討しましょう。
アプリケーションのドキュメントに、サポートされ、かつセキュアなデプロイおよび起動モードを明記し、開発チーム全体でそれを遵守するように徹底してください。ヘッダが攻撃者によって制御される可能性がある構成での運用は避けるべきです。
9routerやNext.js、および使用している全てのライブラリを常に最新の状態に保ち、セキュリティパッチがリリースされた際には速やかに適用してください。この脆弱性についても、提供元の修正を適用することが最優先です。
まとめ
この9routerの認証バイパス脆弱性は、HTTPヘッダの取り扱いにおける信頼のモデルが破綻した際に、どれほど深刻な問題が発生しうるかを示す典型的な例です。フロントエンドエンジニアであっても、アプリケーションのバックエンドロジックやデプロイ環境におけるセキュリティリスクに対する理解は不可欠です。本記事で解説した内容を参考に、ご自身のNext.jsプロジェクトや9routerの導入環境を改めて確認し、適切な対策を講じることを強く推奨します。
セキュリティは常に進化する脅威との戦いです。継続的な学習と対策で、安全なアプリケーション開発を目指しましょう。