[緊急注意喚起] Axiosのプロトタイプ汚染脆弱性 (GHSA-gcfj-64vw-6mp9) とNode.jsバックエンドへの影響
はじめに:フロントエンドエンジニアも無関係ではないAxiosの脆弱性
現代のWeb開発において、データの取得や送受信に欠かせないHTTPクライアントライブラリ「Axios」。多くのフロントエンドエンジニアがブラウザ環境で利用する一方で、Node.jsをバックエンド(BFF: Backend For Frontend、SSR: Server Side Renderingなど)で利用している方も少なくないでしょう。
今回解説する脆弱性 (GHSA-gcfj-64vw-6mp9) は、まさにそのNode.js環境におけるAxiosに影響を及ぼす、非常に深刻なものです。あなたの担当するNode.jsアプリケーションが意図せず機密情報を漏洩する可能性を秘めているため、詳細を理解し、速やかに対策を講じる必要があります。
脆弱性の概要:プロトタイプ汚染が悪用される経路
この脆弱性は、AxiosのNode.js HTTPアダプターに存在する、プロトタイプ汚染 (Prototype Pollution) を悪用したものです。深刻度は「High」と評価されています。
具体的には、アプリケーション内の別の場所で何らかの理由で <code>Object.prototype.proxy</code> が汚染された場合、そしてAxiosのリクエストインターセプターが特定の方法で設定オブジェクトを「クローン」して返す場合に、本来送信されるべきエンドポイントとは異なる、攻撃者制御のプロキシ経由でHTTPリクエストがルーティングされてしまいます。
これにより、以下の機密情報が攻撃者に傍受される可能性があります。
<ul><li>明示的な <code>Authorization</code> ヘッダー</li><li><code>config.auth</code> から生成されるBasic認証ヘッダー</li><li>リクエストメソッド、完全なURL、<code>Host</code> ヘッダー</li><li>POSTリクエストのボディ内容</li></ul>
さらに、攻撃者はプロキシ経由で独自のレスポンスをAxiosに返すことも可能です。これにより、アプリケーションの動作が意図しない形で改ざんされるリスクも存在します。
**重要な注意点として、この脆弱性はブラウザ環境のAxiosには影響しません。Node.js環境のHTTPアダプターを使用している場合にのみ該当します。**
技術的詳細:なぜプロトタイプ汚染がバイパスされるのか?
Axiosはプロトタイプ汚染への対策として、リクエスト設定をマージする際に、nullプロトタイプオブジェクト (<code>Object.create(null)</code>) を生成し、継承されたプロパティが読み取られないように工夫しています。これは、プロトタイプ汚染によって意図しない設定が適用されるのを防ぐための「硬化」処理です。
しかし、この「硬化」された設定オブジェクトがリクエストインターセプターに渡された後、問題が発生します。多くのインターセプターでは、設定を不変に保つために以下のようなパターンでオブジェクトをクローンして返すことがあります。
<code>api.interceptors.request.use((config) => ({ ...config, headers: { ...config.headers, 'X-App': 'demo' } }));</code>
この <code>{...config}</code> や <code>Object.assign({}, config)</code> といった操作は、元のnullプロトタイプオブジェクトを、通常の <code>Object.prototype</code> を継承するオブジェクトへと「軟化」させてしまいます。そして、Axiosはこのインターセプターが返した「軟化」された設定オブジェクトを、再度の「硬化」処理なしにHTTPアダプターに渡してしまいます。
結果として、Node.jsのHTTPアダプターが <code>config.proxy</code> プロパティを読み込む際に、プロトタイプチェーンを辿ってしまい、もし <code>Object.prototype.proxy</code> が攻撃者によって汚染されていれば、そこに設定されたプロキシ情報が参照されてしまうのです。
あなたのプロジェクトは影響を受けますか?
以下の条件が全て揃う場合、あなたのNode.jsアプリケーションは本脆弱性の影響を受ける可能性があります。
<ul><li>**Node.js環境**でAxiosを使用している(例:BFF、SSR、APIサーバーなど)。</li><li>Axiosが**Node.js HTTPアダプター**を使用している(通常、Node.jsでのデフォルト動作、または <code>adapter: 'http'</code> を明示的に指定)。</li><li>アプリケーション内で**プロトタイプ汚染**を引き起こす別の脆弱性、または依存ライブラリが存在し、<code>Object.prototype.proxy</code> が汚染される可能性がある。</li><li>Axiosの**リクエストインターセプター**で、設定オブジェクトを <code>{...config}</code> や <code>Object.assign({}, config)</code> のように**通常のオブジェクトとしてクローンして返している**。</li><li>影響を受けるAxiosのバージョンは <code>axios@1.15.2</code> および <code>axios@1.16.0</code> が確認されています(それ以前のバージョンでも異なる経路で同様の問題が存在する場合があります)。</li></ul>
特に、ヘッダー追加などで広く用いられるインターセプターのパターンが影響を受けるため、注意が必要です。
対策と回避策
この脆弱性に対処するために、以下の対策を速やかに検討してください。
Axiosのメンテナーは、この問題に対処するための修正をリリースしているはずです。常に最新の安定版Axiosにアップデートすることが、最も確実な対策となります。
すぐにアップデートが難しい場合や、念のための対策として、以下のいずれかを検討してください。
プロキシの使用が不要な場合、Axiosインスタンス全体、または個別のリクエスト設定で <code>proxy: false</code> を明示的に設定することで、プロトタイプチェーンを介したプロキシ設定の読み込みを防ぐことができます。
<code>const api = axios.create({ proxy: false });</code><br><code>api.get(url, { proxy: false });</code>
リクエストインターセプターで設定オブジェクトをクローンする際に、<code>Object.prototype</code> を継承しないように配慮します。ただし、これは実装が複雑になりがちで、誤ると再び脆弱になる可能性があるため、推奨度は低いです。
例:既存のオブジェクトを直接変更するか、<code>Object.create(null)</code> で完全に新しいオブジェクトを作成してプロパティをコピーする。
アプリケーションの要件と互換性がある場合、Node.jsの <code>fetch</code> APIを基盤とするアダプター (<code>adapter: 'fetch'</code>) を利用することも有効な回避策となり得ます。ただし、<code>fetch</code>アダプターはHTTPアダプターと挙動が異なる場合があるため、十分なテストが必要です。
まとめ
AxiosのGHSA-gcfj-64vw-6mp9脆弱性は、Node.js環境でAxiosを使用している場合に、プロトタイプ汚染と特定のリクエストインターセプターの組み合わせによって機密情報が漏洩するリスクを伴います。
フロントエンドエンジニアの皆さんも、BFFやSSRといったNode.js環境での開発に携わっている場合は、この脆弱性の影響範囲を確認し、速やかにAxiosを最新バージョンへアップデートするか、上記回避策を適用することを強く推奨します。
ライブラリのセキュリティ情報は常にチェックし、最新の状態を保つことが、セキュアなアプリケーション開発の基本であることを改めて認識しましょう。