はじめに
2026年3月31日、JavaScriptエコシステムに衝撃が走りました。
週間ダウンロード数1億回を超える超定番ライブラリ「Axios」のnpmパッケージに、リモートアクセストロイの木馬(RAT)が埋め込まれていたことが判明したのです。
メンテナアカウント侵害という形で「信頼されていた存在」そのものが攻撃の起点になったケースです。
侵害されていた時間は約3時間。
その間に世界中の開発者が npm install を実行し、知らずにマルウェアを取り込んだ可能性があります。
今すぐすべき3ステップ
# 1. プロジェクトで使っているaxiosバージョンを確認(npm v8以上)
npm list axios --all
# npm v6の場合: npm list axios --depth=9999
# 2. 悪性の依存関係が混入していないか確認
npm list plain-crypto-js
# 3. 影響バージョンを使っていた場合は即座に安全バージョンへ移行
npm install axios@1.7.9
# 0.x系を使用している場合は axios@0.29.0 を使用
本記事では以下をカバーします。
- 攻撃の全体タイムラインと技術的メカニズム
- 自分のプロジェクトが被害を受けているかの判断方法
- 即時対処手順(インシデントレスポンス)
- 再発防止のベストプラクティス
- 攻撃者帰属と組織への提言
攻撃のタイムラインと全体像
攻撃の全体像を時系列で整理します。
| 日時(UTC) | 出来事 |
|---|---|
| 2026-03-30 頃 | AxiosメンテナJason Saayman のnpmアカウントが侵害される |
| 2026-03-31 00:21 UTC | 悪性バージョン axios@1.14.1(latestタグ)がnpmにpublish |
| 2026-03-31 00:35 UTC | 悪性バージョン axios@0.30.4(legacyタグ)がnpmにpublish |
| 2026-03-31 03:29 UTC | セキュリティ研究者が悪性コードを検知・報告 |
| 2026-03-31 03:29 UTC | npmレジストリから悪性バージョンが削除される |
| 2026-03-31 以降 | Google Threat Intelligence Group が北朝鮮APT UNC1069への帰属を発表 |
侵害ウィンドウは約3時間(00:21〜03:29 UTC)。
この間に npm install axios または npm install axios@latest を実行したプロジェクトは、悪性バージョンをインストールした可能性があります。
北朝鮮APT UNC1069 帰属
Google Threat Intelligence Groupの分析により、本攻撃は北朝鮮政府に関連するAPTグループ UNC1069 によるものと帰属が発表されています(信頼度: Medium、根拠: TTPs・C2インフラ・攻撃目的の類似性)。
目的は金銭窃取ではなく、SSHキー・AWSクレデンシャル・npmトークンなど開発者の認証情報の収集です。
サプライチェーン攻撃を通じた大規模な認証情報ハーベスティングは、近年の北朝鮮系APTの特徴的な手口です。
詳細は後述の帰属・APT分析セクションで解説します。
本攻撃の報告はSnyk、The Hacker Newsをはじめとする複数のセキュリティ機関から報告されています。
影響範囲の評価(自分は被害者か)
まず「自分のプロジェクトは対象か」を正確に把握しましょう。
影響を受けるバージョン
| バージョン | タグ | 状態 |
|---|---|---|
axios@1.14.1 |
latest | 悪性(削除済み) |
axios@0.30.4 |
legacy | 悪性(削除済み) |
上記2バージョン以外は影響を受けません。
axios@1.7.9 などその他のバージョンは安全です。
影響を受ける/受けない条件
| 条件 | 影響 |
|---|---|
侵害ウィンドウ(00:21〜03:29 UTC)に npm install axios を実行した |
影響あり(要調査) |
npm-shrinkwrap.json / package-lock.json に axios@1.14.1 または axios@0.30.4 が記録されている |
影響あり(要調査) |
| CI/CDパイプラインが当該時間帯にビルドを実行した | 影響あり(要調査) |
--ignore-scripts オプション付きでインストールした |
ペイロードは実行されていない可能性あり |
| 侵害ウィンドウ前後にインストール・ロックファイルが更新されていない | 影響なし |
| 上記2バージョン以外のaxiosを使用している | 影響なし |
自分は対象外か確認するチェックリスト
以下のすべてに「はい」と答えられれば対象外と判断できます。
-
package-lock.jsonの axios バージョンが1.14.1でも0.30.4でもない - 2026-03-31 の 00:21〜03:29 UTC(日本時間 09:21〜12:29)にビルド・インストールを実行していない
-
npm list plain-crypto-jsの結果が空(または該当なし)
攻撃の技術的メカニズム詳解
今回の攻撃は4つのフェーズで構成されています。
ここでは「どのように攻撃が機能するか」を概念レベルで解説します(悪用可能な完全なコードは記載しません)。
フェーズ1: アカウント侵害
攻撃者は Axiosのメンテナである jasonsaayman のnpmアカウントを侵害しました。
フィッシングや認証情報スタッフィング攻撃などによって取得されたと考えられています。
侵害されたアカウントを使えば、正規の署名でパッケージをpublishできます。
セキュリティ機関各社がこの侵害の経緯を調査・報告しています。
フェーズ2: ファントム依存関係の注入
悪性バージョンには、Axiosのソースコード本体では一切使われていない依存関係が追加されました。
-
plain-crypto-js@4.2.1(ファントム依存関係)
この見慣れない依存関係こそが、攻撃の足がかりです。
「ソースには書いてないのに依存関係に入っている」という状態は、侵害の典型的なサインです。
ファントム依存関係とは
通常、package.json の dependencies に記載されているパッケージは、ソースコード内で import または require されています。
ファントム依存関係とは、dependencies には存在するが、ソースコード内では実際に使われていない依存関係のことです。
サプライチェーン攻撃では、悪性ペイロードを別パッケージに分離してファントム依存として注入する手法がよく使われます。
フェーズ3: ドロッパーの実行
postinstall フックとは
package.json の scripts.postinstall に設定されたコマンドは、npm install を実行した直後に自動的に実行されます。
悪性パッケージはこの仕組みを悪用し、インストール時点でドロッパーを起動させます。
plain-crypto-js@4.2.1 の postinstall スクリプトから setup.js が実行されます。
このスクリプトには難読化が施されており、概念的には以下のような処理を行います。
1. 難読化されたデータをBase64デコード(方向が逆のリバースBase64)
2. XOR復号(キー: OrDeR_7077)
3. 復号されたコードをevalまたは動的実行
4. ターゲットOSを判定してRATペイロードを取得・配置
実際の難読化実装は記載しませんが、「Base64を逆順にした後XOR復号する」という2段階難読化によってスキャナ検知を回避しています。
フェーズ4: C2通信とRAT動作
配置されたRATはC2(コマンド&コントロール)サーバーに接続し、攻撃者の指令を受け取ります。
C2サーバー情報(IOC):
| 項目 | 値 |
|---|---|
| C2ドメイン | sfrclak[.]com |
| C2ポート | 8000 |
| C2 IP | 142[.]11[.]206[.]73 |
OS別RATファイル名:
| OS | ファイル名 | 備考 |
|---|---|---|
| macOS | com.apple.act.mond |
LaunchAgent風の偽装名 |
| Windows | wt.exe |
Windows Terminalと同名で偽装 |
| Linux | ld.py |
システムリンカと類似した名前 |
wt.exe の注意点
wt.exe はWindows Terminalの正規プロセス名とまったく同じです。
タスクマネージャーで wt.exe を発見しても、それが正規のWindows Terminalか悪性ファイルかは、ファイルパスを確認しないと判断できません。
C:\Program Files\WindowsApps\ 以外のパスに存在する場合は要注意です。
収集される情報(目的):
- SSHプライベートキー
- AWS認証情報(
~/.aws/credentials) - npmアクセストークン(
~/.npmrc) - CI/CDシークレット(環境変数)
- ブラウザに保存された認証情報
- gitの設定情報
完全なIOCリスト:
| IOC種別 | 値 |
|---|---|
| 悪性パッケージ | axios@1.14.1 |
| 悪性パッケージ | axios@0.30.4 |
| ファントム依存 | plain-crypto-js@4.2.1 |
| ドロッパー |
setup.js(postinstall経由) |
| 難読化キー | OrDeR_7077 |
| C2ドメイン | sfrclak[.]com |
| C2ポート | 8000 |
| C2 IP | 142[.]11[.]206[.]73 |
| RATファイル(macOS) | com.apple.act.mond |
| RATファイル(Windows) |
wt.exe(偽装) |
| RATファイル(Linux) | ld.py |
侵害確認手順(Incident Response)
「もしかしてやられているかも」と思ったら、以下の手順で確認してください。
Step 1: axiosバージョンの確認
# プロジェクト全体のaxiosバージョンを確認(npm v8以上)
npm list axios --all
# npm v6の場合: npm list axios --depth=9999
1.14.1 または 0.30.4 が表示された場合は侵害の可能性があります。
Step 2: ファントム依存関係の確認
# 悪性依存関係が存在するか確認
npm list plain-crypto-js
# node_modules内に直接確認
ls node_modules/plain-crypto-js 2>/dev/null && echo "FOUND - POTENTIAL COMPROMISE" || echo "Not found"
plain-crypto-js が存在する場合は侵害されている可能性が高いです。
npm list は「まだ自己削除されていない場合」のみ有効
plain-crypto-js の setup.js(postinstall)には、実行後に自身のディレクトリをファイルシステムから消去する自己削除処理が含まれています。
そのため、すでに postinstall が実行された環境では npm list plain-crypto-js が何も表示しない(偽陰性)ケースがあります。
npm list で見つからなくても、侵害の可能性を排除してはいけません。
以下の代替確認方法を合わせて実施してください。
自己削除後の代替確認方法:
# 1. node_modules内のディレクトリ残骸を確認
# 自己削除が不完全な場合、空ディレクトリや一部ファイルが残ることがある
ls -la node_modules/plain-crypto-js 2>/dev/null || echo "Directory not found"
# 2. postinstall実行痕跡をnpmログで確認
# npm-debug.log(プロジェクト直下またはホームディレクトリ)
cat npm-debug.log 2>/dev/null | grep -i "plain-crypto-js"
# 3. npmの詳細ログを確認(~/.npm/_logs/ 配下)
ls ~/.npm/_logs/ 2>/dev/null
grep -r "plain-crypto-js" ~/.npm/_logs/ 2>/dev/null | head -20
# 4. ネットワークログでC2通信の痕跡を確認
# sfrclak.com または 142.11.206.73 への通信が記録されていれば侵害確定
grep -r "sfrclak" /var/log/ 2>/dev/null
grep -r "142\.11\.206\.73" /var/log/ 2>/dev/null
# macOSの場合(unified log)
log show --predicate 'process contains "node"' --last 7d 2>/dev/null | grep -i "sfrclak"
上記のいずれかで痕跡が見つかった場合、または「ログが残っていないが侵害ウィンドウ中にインストールした」という状況であれば、Step 3 以降の確認を必ず実施してください。
最終的な判断はRATアーティファクトの存在確認(Step 4)が最も確実です。
Step 3: C2サーバーへの通信ログ確認
# Linuxでのネットワークログ確認
grep -r "sfrclak" /var/log/ 2>/dev/null
# macOSでのネットワークログ確認
log show --predicate 'process contains "com.apple.act.mond"' --last 7d 2>/dev/null
# DNS解決履歴の確認(nscdキャッシュ)
nscd -g 2>/dev/null | grep sfrclak
Step 4: RATアーティファクトの探索
macOSの場合:
# RATファイルを探す
find / -name "com.apple.act.mond" 2>/dev/null
# LaunchAgentとして永続化されていないか確認
ls ~/Library/LaunchAgents/ | grep -i "act.mond"
ls /Library/LaunchAgents/ | grep -i "act.mond"
Windowsの場合(PowerShell):
# 偽装wt.exeを探す(正規パス以外に存在するか確認)
Get-Process wt -ErrorAction SilentlyContinue | Select-Object Path
# 正規パスは C:\Program Files\WindowsApps\ 配下
# AppData等の不審なパスに存在するか確認
Get-ChildItem -Path $env:APPDATA, $env:LOCALAPPDATA, $env:TEMP -Recurse -Filter "wt.exe" -ErrorAction SilentlyContinue
Linuxの場合:
# ld.pyを探す
find / -name "ld.py" 2>/dev/null
# cronやsystemdへの永続化を確認
crontab -l | grep ld.py
ls ~/.config/systemd/user/ 2>/dev/null
Step 5: CI/CD環境での確認
# GitHub Actions: 該当時間帯のワークフロー実行を確認
gh run list --created 2026-03-31 --limit 50
# 実行ログを確認(RUN_IDは上記で取得)
gh run view <RUN_ID> --log | grep -i "plain-crypto\|sfrclak\|setup.js"
actions/cache で node_modules をキャッシュしている場合は、当該時間帯のビルドのキャッシュが残っていないか合わせて確認してください。
即時対処手順(Remediation)
侵害が確認された、または疑われる場合の対処手順です。
フェーズ1: 隔離・封じ込め
# 影響を受けたマシンをネットワークから隔離(チームの判断に基づく)
# C2サーバーへのアクセスをブロック
sudo iptables -A OUTPUT -d 142.11.206.73 -j DROP
echo "0.0.0.0 sfrclak.com" | sudo tee -a /etc/hosts
侵害が確認された場合は直ちにインシデントレスポンスチームに報告し、関係するシステムを隔離してください。
フェーズ2: シークレットのローテーション
侵害が疑われる場合は、以下のシークレットをすべてローテーションしてください。
# npmトークンのrevoke
npm token revoke <token-id>
# 既存トークンのリストアップ
npm token list
# SSHキーの削除と再生成
# GitHub等に登録済みのSSHキーを削除後、新しいキーペアを生成
ssh-keygen -t ed25519 -C "your-email@example.com"
# AWS IAM認証情報のローテーション
aws iam create-access-key --user-name <username>
aws iam delete-access-key --access-key-id <old-key-id> --user-name <username>
CI/CDシークレット(GitHub Actions Secrets、CircleCI Environment Variables等)も忘れずにローテーションしてください。
シークレットのローテーションは妥協しないこと
「多分大丈夫だろう」で済ませるのは危険です。
RATが実際に実行されたかどうかに関わらず、該当バージョンをインストールした形跡がある場合は全シークレットをローテーションすることを強く推奨します。
フェーズ3: 安全バージョンへの移行
# 安全なバージョンに更新
npm install axios@1.7.9
# package.jsonのバージョン指定も確認・更新
# "axios": "^1.7.9" となっていることを確認
axios@0.x系を使用している場合は npm install axios@0.29.0 に移行してください。
# 特定バージョンにピン留めしてlockfileを更新
npm install axios@1.7.9 --save-exact
# 0.x系の場合: npm install axios@0.29.0 --save-exact
npm install axios@1.7.9 を実行すると package-lock.json は自動的に更新されます。
他の依存関係も含めてすべて最新にしてよい場合のみ、rm package-lock.json && npm install を実行してください。
フェーズ4: クリーンビルドの実施
# キャッシュを完全にクリア
npm cache clean --force
# node_modulesを完全に再作成
rm -rf node_modules
npm ci
Dockerを使っている場合は、コンテナイメージも必ず再作成してください。
# キャッシュなしでイメージを再ビルド
docker build --no-cache -t your-image:latest .
# 影響を受けた可能性のある古いイメージは削除
docker image rm <image-id>
再発防止・ベストプラクティス
今回の事件を教訓に、サプライチェーン攻撃に強い開発体制を整えましょう。
1. npm ci --ignore-scripts のCI標準化
最も即効性のある対策です。
--ignore-scripts オプションにより、postinstall などのスクリプトが実行されなくなります。
# CI/CDパイプラインでは常にこれを使う
npm ci --ignore-scripts
.npmrc に設定して全プロジェクトに適用することもできます。
ignore-scripts=true
--ignore-scripts は postinstall スクリプトに依存する一部のパッケージ(node-gypによるネイティブモジュールビルドなど)を壊す可能性があります。
プロジェクトの要件に応じて導入可否を判断してください。
2. lockfileの厳格管理
package-lock.json の変更は必ずレビューしましょう。
# PRマージ前にlockfileの差分を確認
git diff origin/main -- package-lock.json
# 予期しない依存関係が追加されていないか確認する
# 特に見慣れないパッケージが増えていたら要確認
lockfileをgitignoreに含めているプロジェクトは、今すぐ .gitignore から外してコミットすることを推奨します。
3. 依存関係監視ツールの導入
自動的に悪性パッケージを検知するツールを導入しましょう。
| ツール | 特徴 |
|---|---|
| Socket.dev(socket.dev) | サプライチェーン攻撃に特化した行動分析 |
| Snyk | 脆弱性・ライセンス・サプライチェーン監視 |
| Aikido Security | 開発者向けセキュリティプラットフォーム |
4. publishアクセス制御の強化
npm パッケージのpublishをGitHub Actions OIDCに限定することで、個人アカウント侵害によるpublishを防げます。
jobs:
publish:
runs-on: ubuntu-latest
permissions:
id-token: write # OIDC用
steps:
- uses: actions/setup-node@v4
with:
registry-url: 'https://registry.npmjs.org'
- run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
npm側でも「Automation token以外からのpublishを拒否」する設定を有効化しましょう。
5. SBOM(ソフトウェア部品表)の整備
どのパッケージのどのバージョンを使っているかを記録・管理することで、侵害発生時の影響範囲特定が迅速になります。
# SBOM生成例(CycloneDX形式)
npx @cyclonedx/cyclonedx-npm --output-file sbom.json
# または GitHub の依存関係グラフを活用する
攻撃者帰属・APT分析と組織への提言
北朝鮮APT UNC1069 への帰属
Google Threat Intelligence Groupの分析により、本攻撃は北朝鮮政府に関連するAPTグループ UNC1069 によるものと帰属されています(信頼度: Medium、根拠: TTPs・C2インフラ・攻撃目的の類似性)。
帰属の根拠として報告されている要素は以下の通りです。
- C2インフラの構築・通信パターンが既知のUNC1069の手口と一致
- 収集ターゲット(開発者の認証情報)が北朝鮮APTの典型的な目的と合致
- マルウェアの実装スタイルが過去のキャンペーンと類似
MITRE ATT&CK マッピング:
| テクニック | ID | 説明 |
|---|---|---|
| Software Supply Chain | T1195.002 | OSS供給チェーンを通じた悪性コード配布 |
| Command and Scripting Interpreter | T1059 | postinstallスクリプト経由での実行 |
| Obfuscated Files or Information | T1027 | リバースBase64+XOR難読化 |
| Credentials from Password Stores | T1555 | 認証情報の収集 |
類似事例との比較
今回の攻撃は単発ではなく、サプライチェーン攻撃という大きなトレンドの一部です。
| 事例 | 年 | 手口 | 規模 |
|---|---|---|---|
| xz-utils CVE-2024-3094 | 2024 | 2年かけてメンテナの信頼を獲得し、バックドア挿入 | SSH全体に影響する可能性 |
| event-stream | 2018 | メンテナ引き継ぎ後に悪性コードを注入 | 週800万DL |
| axios(今回) | 2026 | メンテナアカウントを侵害してRAT埋め込み | 週1億DL |
xz-utils のケースは2年という長期間の潜伏を経た攻撃でしたが、今回は3時間という短時間で攻撃・検知・削除が完了しました。
コミュニティの監視体制が機能したと言えますが、それでも3時間は十分すぎる侵害ウィンドウです。
組織への行動指針
今すぐ(24時間以内):
- 影響バージョンの使用有無を全プロジェクトで確認
- 侵害が疑われる場合はシークレットをローテーション
- 安全バージョン(
axios@1.7.9)への更新をトリアージ
短期(1週間以内):
- CI/CDへの
npm ci --ignore-scripts標準化 - lockfileのgitレビュープロセス導入
- インシデントレスポンス手順書の更新(本記事の対処手順を参考に)
中期(1ヶ月以内):
- 依存関係監視ツール(Socket.dev、Snyk、Aikido等)の導入評価・検証
- npm publishアクセス制御の見直し(OIDC化)
- SBOM生成・管理プロセスの整備
長期(四半期以内):
- ソフトウェアサプライチェーンセキュリティポリシーの策定
- 依存関係の定期監査サイクルの確立
- 開発者向けサプライチェーン攻撃トレーニングの実施
まとめ
今回の Axios npmサプライチェーン攻撃から学べる教訓をまとめます。
- 影響を受けるのは
axios@1.14.1とaxios@0.30.4のみ。まずnpm list axiosで確認しよう - 侵害が疑われる場合はシークレットのローテーションを妥協しない
-
npm ci --ignore-scriptsをCIに導入するだけで多くのpostinstall攻撃を防げる - lockfileをgitで管理し、差分を必ずレビューする習慣が重要
- 信頼されたメンテナのアカウント侵害は防ぎようがない。だからこそ多層防御が必要