💬

axiosで発見された重大な脆弱性 - 2026.04.12

に公開3

概要

  • axios に Critical 脆弱性 (CVSS 10.0) が公表された(2026-04-09)
  • 影響範囲: すべての < 1.13.2(公式の patched version は >= 1.15.0
  • プロトタイプ汚染と組み合わさると、外部入力なしで AWS IAM 認証情報の窃取 まで到達しうる
  • 対応: axios を 1.15.0 以上にアップデート

Advisory: https://github.com/axios/axios/security/advisories/GHSA-fvcv-3m26-pcqx

影響を受けるか確認する方法

まず自分のプロジェクトで使っている axios のバージョンを確認する。

npm ls axios

または package-lock.json / yarn.lock を直接見る。

grep -A 1 '"axios"' package-lock.json
バージョン 状態
< 1.13.2 脆弱
1.13.21.14.x 部分修正だが公式には "patched" 扱いされていない
>= 1.15.0 安全

直接 axios を入れていなくても、依存先のライブラリが axios を使っているケースは多い。npm ls axios で依存ツリー全体を確認するのがおすすめ。

何が起きる脆弱性なのか

CWE-113 (CRLF Injection) × プロトタイプ汚染 のコンボによる HTTP Request Smuggling。

攻撃の流れ

  1. 依存ツリーのどこか(qs, minimist, body-parser など)でプロトタイプ汚染が発生
  2. Object.prototype に CRLF (\r\n) を含むヘッダー値が仕込まれる
  3. アプリが axios.get(...) を呼ぶ
  4. axios が config マージ時にプロトタイプ由来のプロパティも取り込む
  5. ヘッダー値の CRLF を検証せずソケットに書き込む
  6. 1 本の HTTP リクエストの中に、攻撃者が仕込んだ別のリクエストが密輸される

Advisory に掲載されている PoC の核心部分を引用する。

// 他ライブラリの脆弱性でプロトタイプが汚染される想定
Object.prototype['x-amz-target'] =
  "dummy\r\n\r\nPUT /latest/api/token HTTP/1.1\r\n" +
  "Host: 169.254.169.254\r\n" +
  "X-aws-ec2-metadata-token-ttl-seconds: 21600\r\n\r\n" +
  "GET /ignore";

// アプリ側は完全にハードコードされた安全なリクエスト
await axios.get('https://analytics.internal/pings');

実際にソケットに書かれるバイト列はこうなる。

GET /pings HTTP/1.1
Host: analytics.internal
x-amz-target: dummy

PUT /latest/api/token HTTP/1.1
Host: 169.254.169.254
X-aws-ec2-metadata-token-ttl-seconds: 21600

GET /ignore HTTP/1.1
...

2 本目の PUT が AWS の Instance Metadata Service (IMDSv2) に届き、セッショントークンが返ってくる。これで IAM 認証情報を取得され、クラウドアカウントを乗っ取られる可能性がある。

なぜ IMDSv2 まで突破できるのか

IMDSv2 は通常の SSRF を防ぐために、X-aws-ec2-metadata-token-ttl-seconds ヘッダー付きの PUT リクエストを要求する設計になっている。普通の SSRF だとこのヘッダーを付けられないので守れるはずだった。

ところが今回の手法では、リクエストスマグリングによって任意のヘッダー・メソッドを持つ HTTP リクエストを丸ごと注入できるため、IMDSv2 の前提が崩れる。

怖いポイント

  • 直接の外部入力が不要。アプリ側のコードは axios.get('https://hardcoded.url/') のように完全にハードコードされていても発火する
  • 自前のコードを監査しても防げない。依存ツリーのどこかにプロトタイプ汚染の穴があれば成立する

対応方法

基本: バージョンを上げる

npm install axios@^1.15.0
# or
yarn add axios@^1.15.0
# or
pnpm add axios@^1.15.0

1.13.x / 1.14.x からのアップデートなら breaking change は基本なし。

lockfile も忘れずに

package.json の指定バージョンを上げるだけでなく、package-lock.json / yarn.lock / pnpm-lock.yaml もコミットする。

間接依存で axios が入っている場合

直接は axios を使っていないが、依存ツリーに入っているケース。

npm ls axios

で依存元を特定し、そのライブラリが新しい axios を要求する版を出していればアップデートする。出ていない場合は overrides (npm) / resolutions (yarn) で強制的に上げる手もある。

// package.json (npm)
{
  "overrides": {
    "axios": "^1.15.0"
  }
}

アップデート後の確認

npm ls axios
npm audit

npm audit で Critical が消えていれば OK。

まとめ

  • 確認: npm ls axios でバージョンを確認
  • 対象: < 1.15.0 は全部アップデート対象と考えてよい
  • 対応: 1.15.0 以上に上げて lockfile をコミット

参考リンク

Discussion

まーまー

この脆弱性の件で調査をしているものですが、再現できましたか? 自分の方では再現できず途方に暮れております。どうしても Node.js の http モジュールがブロックします。

再現方法を教えていただきたく存じます。

https://zenn.dev/masakura/articles/bc88704f8af091

あさひあさひ

ご指摘ありがとうございます。正直に申し上げると、記事執筆時点では Advisory の内容を読み解いて解説したものであり、実機での再現までは行っていませんでした。

ご指摘を受けて改めて調査したところ、おっしゃる通りNode.js の http モジュールは assertValidHeaderValue により CRLF を含むヘッダー値を ERR_INVALID_CHAR で拒否することを確認しました。この挙動は Node v0.12 から入っており、現行 LTS でも当然有効です。したがって Node + axios(http adapter) の構成では、このアドバイザリの素朴な PoC は再現できないというご観察は正しいです。

その上で、axios 1.15.0 の修正 PR(#10660)を読むと、修正は lib/core/AxiosHeaders.js にヘッダー値の CRLF バリデーションを追加するもので、http adapter 自体には手を入れていません。つまり今回の修正は「Node が肩代わりしていた検証を、axios 自身のレイヤでも行うようにした」という、いわゆる defense in depth の性質が強いと認識しています。

axios 側でのバリデーションが価値を持つのは、Node の http を経由しないケースだと考えられ、CVSS 10.0 という評価に対して実際の攻撃面は少し限定的に見えますが、「Node が守ってくれていただけで axios 自身は無防備だった」点を塞いだ意味で修正は妥当と思います。

記事本文にも本コメントを踏まえた注記を追記いたします。貴重なご指摘、本当にありがとうございました。

まーまー

ご丁寧にありがとうございます! こちらもとても助かりました。その Pull Request を書いた人も、昔の Node.js のことを言及していて、そのための修正なんだそうです。

(せめて、そのことを Advisory に書いててほしかった...)