axiosの事例で学ぶnpm供給チェーン攻撃のメカニズム

2026-05-15 hit count image

2026年3月にnpmエコシステムを襲ったaxios供給チェーン攻撃の事例を分析します。メンテナーアカウント の乗っ取り、悪意ある依存関係の注入、postinstallスクリプトを通じたRAT配布までの攻撃フローと、 npmの信頼モデルが抱える構造的な脆弱性を解説します。

web

はじめに

2026年3月31日、週間ダウンロード数1億回以上を誇るHTTPクライアントライブラリaxiosが供給チェーン攻撃(supply chain attack)を受けました。インシデントは約4時間で収束しましたが、その短い時間の間に世界中の無数のプロジェクトが潜在的なリスクにさらされました。

この記事は3部作シリーズの第1回で、axios攻撃事例を通じてnpm供給チェーン攻撃がどのように機能するか、そのメカニズムを分析します。続く第2回では実際に適用した防御戦略と実装の詳細を、第3回では防御戦略の有効性と限界を取り上げます。

供給チェーン攻撃とは

供給チェーン攻撃とは、ソフトウェアが依存する外部コンポーネント(ライブラリ、ビルドツール、デプロイパイプラインなど)を通じて最終ユーザーに悪意あるコードを届ける攻撃手法のことです。ターゲットを直接攻撃するのではなく、ターゲットが信頼し使用しているものを先に侵害することで、その信頼の連鎖を伝って侵入します。

代表的な形態は次のとおりです。

  • パッケージレジストリ攻撃: npm、PyPI、RubyGemsなどの公開レジストリにある正規パッケージを侵害
  • ビルドシステム攻撃: CI/CDパイプラインやビルドツール自体を侵害 (SolarWinds3CX の事例)
  • メンテナーの行為: メンテナー本人が意図的に悪意あるコードを挿入 (colors.jsnode-ipc の事例)
  • 長期潜入: 信頼関係を数年かけて構築した後にバックドアを挿入 (XZ Utils の事例)

今回取り上げるaxiosの事例は、このうちパッケージレジストリ攻撃、中でもメンテナーアカウント乗っ取り型攻撃に該当します。

axiosの攻撃事例

概要

項目内容
発生時刻2026年3月31日 00:38 UTC 頃
影響パッケージaxiosplain-crypto-js
悪意あるバージョン[email protected][email protected]
安全なバージョン[email protected][email protected]
収束時間約4時間以内
週間ダウンロード数1億回以上

インシデントの経緯

攻撃者はaxiosのリードメンテナーであるjasonsaaymanのアカウントを乗っ取り、アカウントのメールアドレスを自分のアドレス([email protected])に変更しました。その後、通常のCI/CDパイプラインを迂回しnpm CLIを使って直接、悪意あるバージョンを約39分以内に2つのリリースブランチ(1.x、0.x)に公開しました。

通常のaxiosリリースはGitHub ActionsとnpmのOIDC Trusted Publisherを使用して暗号学的な署名を残しますが、今回の悪意あるバージョンにはその署名がありませんでした。これが今回のインシデントにおける決定的なフォレンジックの手がかりとなりました。

検出自体は非常に迅速でした。npm供給チェーンセキュリティSaaSのSocketがAIベースのパッケージ行動分析により公開後6分で異常を検知し、GitHub ActionsランタイムセキュリティのStepSecurityが続いてアラートを発しました。しかしその間の約4時間、自動更新や新規インストールを通じて悪意あるバージョンを取得してしまったケースが存在する可能性があります。

攻撃メカニズムの分析

今回の攻撃が精巧だった理由は、単に1つのパッケージを改ざんしたのではなく、2段階構造でペイロードを分離した点にあります。

第1段階: 新しい依存関係の注入

攻撃者はまず[email protected]という新しいパッケージをnpmレジストリに公開しました。このパッケージの唯一の目的はpostinstallスクリプトを実行することでした。

そして侵害したaxiosバージョンにこのパッケージを新しい依存関係として追加しました。パッチノートだけ見ると平凡な依存関係の変更のように見えますが、実際にはすべてのaxiosインストーラーが気づかないうちに悪意あるペイロードを一緒にダウンロードするように仕掛けたのです。

[email protected]
└── [email protected]   ← 悪意あり (postinstallのためだけに存在)

第2段階: postinstallスクリプトの実行

plain-crypto-jspostinstallフックは以下の動作をします。

  • ランタイムでデコードされる難読化されたペイロードを埋め込み
  • 動的モジュールローディングで静的解析を回避
  • sfrclak.com(IP: 142.11.206.73)とC2通信
  • OSごとに異なるパスにRAT(Remote Access Trojan)をドロップ
OSペイロード配置パス
macOS/Library/Caches/com.apple.act.mond
Windows%PROGRAMDATA%\wt.exe
Linux/tmp/ld.py

つまり、yarn installまたはnpm installを実行した瞬間に — コードを実行する前から — 開発者のPCやCIサーバーにはすでにバックドアが仕込まれた状態になります。

なぜこの攻撃が危険なのか

影響範囲が広大

axiosはReact、Vue、Node.jsバックエンドなどJavaScriptエコシステム全体で使われている事実上の標準HTTPクライアントです。直接依存していなくても、他のライブラリが依存しているため**間接依存(transitive dependency)**として入り込んでいるケースが圧倒的に多いです。

yarn installを1回実行したときに取得する数百〜数千個のパッケージのうち、たった1つでもこのような形で侵害されれば、即座に影響を受けます。

postinstallがサイレント実行のトリガーになる

postinstallは本来ネイティブモジュールのビルドなど正当な用途で使われるnpmフックですが、開発者の明示的な許可なしに任意のコードを実行できるという性質のため、供給チェーン攻撃において最も魅力的な侵入口となります。

特に危険な環境は次のとおりです。

  • 開発者のPC: ブラウザセッション、SSHキー、クラウド認証情報などの高価値資産が集中
  • CI環境: デプロイ用トークン、シークレットが環境変数として露出
  • プロダクションビルドサーバー: ビルド成果物に悪意あるコードを注入できる位置

検出が早くても露出は防げない

今回のインシデントでSocket AIは6分で検出し、4時間以内にパッケージが削除されました。非常に迅速な対応でしたが、自動更新が走る環境ではこの時間内にすでにインストールが完了していた可能性が十分あります。

DependabotRenovateのような自動PRボットが新バージョンを即座に検知してPRを作成し、CIがそのPRの依存関係を自動インストールするなら — 人がマージしていなくても — postinstallはすでにCI環境で実行されています。

npmの信頼モデルが抱える構造的な限界

axios攻撃は一過性の出来事ではなく、構造的な問題の顕れです。npmエコシステムの信頼モデルは本質的に次の仮定の上に成り立っています。

  1. メンテナーアカウントは安全に管理されている
  2. メンテナーに悪意はない
  3. 新バージョンは検証済みの状態で公開される

この仮定のどれか1つでも崩れれば — そして実際にすべて崩れた事例があります — 自動更新はそれ自体が攻撃ベクターになります。

仮定崩れた事例
メンテナーアカウントの安全性axios (2026)、ua-parser-js (2021)、event-stream (2018)
メンテナーの善意colors.js (2022)、node-ipc (2022)
新バージョンの完全性tj-actions/changed-files (2025) — GitHub Actionsタグの改ざん

npmは基本的にメンテナーを信頼し、semver範囲(^~)はその信頼を将来のバージョンへも自動で拡張するよう設計されています。この自動拡張が攻撃対象領域を生み出しているのです。

私たちへの示唆

axios攻撃から得られる教訓は次のとおりです。

1. 「有名なパッケージだから安全」という前提は崩れた

ダウンロード数が多いほど標的になりやすいというパラドックスが成立します。人気パッケージほど攻撃者にとって大きなリターンをもたらすからです。

2. 自動更新は両刃の剣

セキュリティパッチを素早く受け取るための自動更新が、同時に供給チェーン攻撃を最も素早く受け入れる通路になります。

3. postinstallは疑うべき

インストール時に実行されるスクリプトは本質的にRCE(Remote Code Execution)と同じです。デフォルトで無効化する方向が安全です。

4. 時間が最強のフィルター

悪意あるパッケージはほぼ常に数時間から数日以内に検出・削除されます。つまり、新バージョンが出たらすぐ受け取らないこと自体が強力な防御になります。この点はシリーズの第3回でデータとともに詳しく取り上げます。

まとめ

axiosの事例は「有名でよく管理されているパッケージでさえ、4時間無防備な状態になりうる」という事実を示しています。この事実を受け入れると、次の問いが続きます。

私たちに何ができるか?

次の記事供給チェーン防御戦略と実装では、この攻撃を契機に実際のプロジェクトに適用した3つの防御戦略 — GitHub ActionsのSHAピン固定、Dependabot cooldown、YarnのnpmMinimalAgeGate — をコードレベルで詳しく解説します。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。



SHARE
Twitter Facebook RSS