はじめに
2026年3月31日、JavaScript エコシステム史上もっとも広範囲なサプライチェーン攻撃のひとつが発生しました。
週間 1 億ダウンロードを超える axios パッケージが侵害され、悪意あるバージョンが約 3 時間にわたって npm 上で配信されていました。
この記事では:
- 何が起きたのか(攻撃のタイムライン)
- あなたが影響を受けているか確認する方法
- 侵害された場合の対応
- 今後同じ被害を防ぐ方法
を、新人プログラマでもすぐ実践できる形で解説します。
何が起きたのか
タイムライン
| 日時 (UTC) | イベント |
|---|---|
| 2026/03/30 05:57 | 攻撃者が plain-crypto-js@4.2.0(クリーンな囮パッケージ)を公開 |
| 2026/03/30 23:59 |
plain-crypto-js@4.2.1(悪意ありペイロード入り)を公開 |
| 2026/03/31 00:21 | 侵害された maintainer アカウントから axios@1.14.1(latest タグ)を公開 |
| 2026/03/31 01:00 | 同じく axios@0.30.4(legacy タグ)を公開 |
| 2026/03/31 03:15 | npm 側で削除 |
攻撃者は axios のメンテナーアカウントを乗っ取り、latest と legacy の両方のタグを同時に汚染しました。これにより、最新版を使うプロジェクトもレガシー版を使うプロジェクトも被害対象となりました。
攻撃の仕組み
侵害された axios は、隠れた依存関係 plain-crypto-js@4.2.1 を含んでいました。これは axios のコードからは一切 import されない「幽霊依存関係」です。
その目的はただひとつ — package.json の postinstall フックを使って、npm install の実行直後に自動でマルウェアを起動すること。
{
"scripts": {
"postinstall": "node setup.js"
}
}
setup.js は OS(Windows / macOS / Linux)を判定し、それぞれのプラットフォーム用の RAT(Remote Access Trojan)をダウンロード・実行します。
ユーザーの操作は一切不要。npm install を実行するだけで感染します。
攻撃の帰属
Microsoft と Google の脅威インテリジェンスチームは、この攻撃を北朝鮮系の国家アクター(Sapphire Sleet / UNC1069)に帰属させています。
18 時間前から囮パッケージを準備し、3 つの OS 向けペイロードを事前にビルドしていたことから、機会主義的な攻撃ではなく、計画的な作戦だったことが分かっています。
あなたが影響を受けているか確認する
ステップ 1:ロックファイルを検索する
プロジェクトのルートで以下のコマンドを実行してください:
# package-lock.json を使っている場合
grep -r "1.14.1\|0.30.4\|plain-crypto-js" package-lock.json
# yarn を使っている場合
grep -r "1.14.1\|0.30.4\|plain-crypto-js" yarn.lock
# bun を使っている場合
grep -r "1.14.1\|0.30.4\|plain-crypto-js" bun.lockb
ステップ 2:CI/CD ログをチェックする
2026 年 3 月 31 日 00:21 〜 03:15 UTC(日本時間 9:21 〜 12:15)の間に npm install を実行した CI/CD ジョブがある場合、そのパイプラインも侵害された可能性があります。
特に GitHub Actions、CircleCI、GitLab CI などでビルドログを確認し、axios@1.14.1、axios@0.30.4、または plain-crypto-js の文字列を検索してください。
侵害された場合の対応
もし上記のいずれかが見つかった場合、そのマシン(または CI ランナー)は完全に侵害されたものとして扱う必要があります。
やるべきこと
-
すべての秘密情報をローテーション
- API キー(OpenAI、AWS、GCP、Azure など)
- SSH キー
- npm トークン
- GitHub Personal Access Token
- データベース接続文字列
- クラウドサービスのクレデンシャル
-
axios を安全なバージョンにダウングレード
npm install axios@1.14.0 # または npm install axios@0.30.3 -
plain-crypto-jsを完全に削除npm uninstall plain-crypto-js rm -rf node_modules npm ci -
開発者マシンの場合
- ホストマシンの完全な再インストールを推奨
- 最低でもアンチウイルススキャンを実行
-
本番環境の場合
- 該当期間にデプロイされたコンテナ・サーバーを再構築
- アクセスログを確認し、不正なアクティビティを調査
今後同じ被害を防ぐ方法
新人プログラマにこそ知っておいてほしい、サプライチェーン攻撃を防ぐベストプラクティスです。
✅ 1. 厳密なバージョン固定
^ や ~ を使った範囲指定は避け、完全なバージョン固定を使いましょう:
{
"dependencies": {
"axios": "1.14.0"
}
}
✅ 2. CI/CD では npm install ではなく npm ci を使う
npm ci はロックファイルを厳密に尊重し、新しいバージョンを勝手に取得しません:
# ❌ CI で危険
npm install
# ✅ 安全
npm ci
✅ 3. postinstall スクリプトを無効化する
ほとんどのプロジェクトでは postinstall スクリプトは不要です:
npm config set ignore-scripts true
または package.json で:
{
"scripts": {
"preinstall": "npx force-resolutions"
}
}
✅ 4. パッケージのクールダウン期間を設ける
新しくリリースされたパッケージは、最低 3 日間は使わないようにすると、コミュニティが脆弱性を発見する時間が確保できます。
✅ 5. ロックファイルを必ず Git にコミットする
package-lock.json や yarn.lock を .gitignore に入れている人がたまにいますが、これは絶対にやめましょう。チーム全員が同じバージョンを使うことが、サプライチェーン防御の基本です。
サプライチェーン攻撃だけが脅威ではない
axios 攻撃はあなたのマシンを狙う攻撃です。でも、Node.js 開発者にはもうひとつ見過ごされがちなデータ漏洩のルートがあります — LLM API への入力です。
OpenAI、Anthropic、Google にプロンプトを送るたびに、顧客の名前、メールアドレス、ID などがプレーンテキストでプロバイダーのサーバーに到達します。これは攻撃ではなく、自分で作っている漏洩です。
CloakLLM — オープンソースの PII 保護ミドルウェアを使うと、LLM に送る前に PII を自動でトークン化できます:
const cloakllm = require('cloakllm');
const OpenAI = require('openai');
const client = new OpenAI();
cloakllm.enable(client); // これだけ
// 以降、すべての API 呼び出しが自動的に保護される
詳しくは 前回の記事 と 実践チュートリアル を参照してください。
まとめ
axios のサプライチェーン攻撃は、現代の開発者にとって他人事ではないことを示しました。npm install を一度実行しただけで、完全に侵害される可能性があります。
新人プログラマのみなさんへ:
- 🔍 ロックファイルを必ずチェック・コミットする
- 📌 バージョンは厳密に固定する
- 🔒 CI/CD では
npm ciを使う - 🛡️ postinstall スクリプトを無効化する
- 🚨 セキュリティニュースを定期的にチェックする
セキュリティで最も重要なのは、特定のテクニックではなく、「自分が何をインストールしているか、そしてそれは何をするのか」を意識する習慣です。
参考リンク
- Elastic Security Labs: axios supply chain compromise
- Microsoft Security: Mitigating the Axios npm supply chain compromise
- Google Threat Intelligence: UNC1069 attribution
- Huntress: Supply Chain Compromise of axios npm Package
- 前回の記事:新人プログラマがLLM APIを使う前に知っておくべきセキュリティの基本
- 実践チュートリアル:10行でLLMプロンプトからPIIを自動除去する方法