axiosで発見された重大な脆弱性 - 2026.04.12
概要
- 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.2 〜 1.14.x
|
部分修正だが公式には "patched" 扱いされていない |
>= 1.15.0 |
安全 |
直接 axios を入れていなくても、依存先のライブラリが axios を使っているケースは多い。npm ls axios で依存ツリー全体を確認するのがおすすめ。
何が起きる脆弱性なのか
CWE-113 (CRLF Injection) × プロトタイプ汚染 のコンボによる HTTP Request Smuggling。
攻撃の流れ
- 依存ツリーのどこか(
qs,minimist,body-parserなど)でプロトタイプ汚染が発生 -
Object.prototypeに CRLF (\r\n) を含むヘッダー値が仕込まれる - アプリが
axios.get(...)を呼ぶ - axios が config マージ時にプロトタイプ由来のプロパティも取り込む
- ヘッダー値の CRLF を検証せずソケットに書き込む
- 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 モジュールがブロックします。
再現方法を教えていただきたく存じます。
ご指摘ありがとうございます。正直に申し上げると、記事執筆時点では Advisory の内容を読み解いて解説したものであり、実機での再現までは行っていませんでした。
ご指摘を受けて改めて調査したところ、おっしゃる通りNode.js の
httpモジュールはassertValidHeaderValueにより CRLF を含むヘッダー値をERR_INVALID_CHARで拒否することを確認しました。この挙動は Node v0.12 から入っており、現行 LTS でも当然有効です。したがって Node + axios(httpadapter) の構成では、このアドバイザリの素朴な PoC は再現できないというご観察は正しいです。その上で、axios 1.15.0 の修正 PR(#10660)を読むと、修正は
lib/core/AxiosHeaders.jsにヘッダー値の CRLF バリデーションを追加するもので、httpadapter 自体には手を入れていません。つまり今回の修正は「Node が肩代わりしていた検証を、axios 自身のレイヤでも行うようにした」という、いわゆる defense in depth の性質が強いと認識しています。axios 側でのバリデーションが価値を持つのは、Node の
httpを経由しないケースだと考えられ、CVSS 10.0 という評価に対して実際の攻撃面は少し限定的に見えますが、「Node が守ってくれていただけで axios 自身は無防備だった」点を塞いだ意味で修正は妥当と思います。記事本文にも本コメントを踏まえた注記を追記いたします。貴重なご指摘、本当にありがとうございました。
ご丁寧にありがとうございます! こちらもとても助かりました。その Pull Request を書いた人も、昔の Node.js のことを言及していて、そのための修正なんだそうです。
(せめて、そのことを Advisory に書いててほしかった...)