2026年3月31日、HTTP クライアントライブラリ axios の npm パッケージが侵害されました。攻撃者はメンテナの npm アカウントを乗っ取り、マルウェアを含むバージョン 1.14.1 および 0.30.4 を公開しました。axios は npm エコシステムで週間約1億ダウンロードを誇る主要パッケージです。本記事では公開情報をもとに、事象の概要を記録します。また、対応指針を示します。

TL;DR - 対応指針
- axios への直接依存に限らず、間接依存(transitive dependency)でも
postinstallフックは発火します。 自身のプロジェクトが axios を直接利用していなくても、依存ツリーのどこかに axios が含まれていれば影響を受け得ます。npm ls axiosで確認してください。 npm ls axiosや lockfile により、インストール済バージョンを確認してください。1.14.1または0.30.4がインストール済の場合、マルウェア感染の可能性があります。- 悪性バージョンは
plain-crypto-jsという悪性パッケージを依存に追加しており、postinstallフックで RAT(Remote Access Trojan)をドロップします。 plain-crypto-jsはインストール後に自身の痕跡を消去するため、node_modulesの事後検査では検知できません。実際の通信ログ、端末内の痕跡チェック、あるいはaxios に限らないnpm installの実行時刻との照合が必要です。
- 悪性バージョンは
- 感染した場合、プラットフォーム固有の RAT がバックグラウンドで動作している可能性があります。端末内の全てのデータの漏洩や、その他の攻撃の継続を疑う必要があります。
- 影響を受けたバージョンをインストールしている場合は、
- まずダウングレードしてください(
npm install axios@1.14.0、レガシー利用はaxios@0.30.3)。 - 端末内のクレデンシャルを即座にローテーション してください。
- 各プラットフォームのバックドアファイルを確認・除去してください(後述)。
node_modules/plain-crypto-js/ディレクトリが存在する場合は削除してください。- ネットワークログで
sfrclak[.]com:8000への接続を確認してください。
- まずダウングレードしてください(
- 現在は npm 上で悪性バージョンは削除済です。
plain-crypto-jsも無害なセキュリティスタブに置換済です。
はじめに
本件は StepSecurity 社による整理 や Elastic社のリサーチャーによる分析 をはじめ、多数のリサーチャー・コミュニティが協力して分析・対応を進めています。本記事はエビデンス確認・追加分析の上、日本のコミュニティに向けて整理したものです。予め、方方のリサーチにお礼申し上げます。
また本記事の目的は事態の把握と対応の促進であり、違法行為への加担・助長を意図するものではありません。 ペイロードの動作は手法の理解に必要な範囲で要約して記載しています。 記述の一部には不正確な情報が含まれている可能性があります。 速報性を優先していますので、ご了承ください。
タイムライン
以下に概略を示します。
| 日時 (JST) | イベント |
|---|---|
| 3月31日 08:59 | 悪性パッケージ plain-crypto-js@4.2.1 が npm に公開(悪性 postinstall フック付き) |
| 3月31日 09:21 | 悪性バージョン axios@1.14.1 が npm に公開(latest タグ) |
| 3月31日 10:00 | 悪性バージョン axios@0.30.4 が npm に公開(legacy タグ) |
| 3月31日 ~12:15 | npm が悪性 axios バージョンを削除 |
悪性の axios@1.14.1 の露出時間は約2時間53分、axios@0.30.4 は約2時間15分と推定されます。(これほどまでのパッケージの場合は、速やかにテイクダウンが進みますね。一切テイクダウンされない例もありますから、この件の重要度の高さがうかがえます。)
侵害の仕組み
侵害の起点、侵害先での発火経路、プラットフォームごとの侵害内容に分けて説明します。
侵害の起点
いずれの悪性バージョンも、GitHub 上に対応するタグやコミットは存在せず、メンテナ jasonsaayman のアカウント経由で npm へ直接 CLI アップロードされています。実際に npm registry の manifest を比較すると、正規版(v1.14.0)と悪性版(v1.14.1)で以下の差異があります。
| フィールド | v1.14.0(正規) | v1.14.1(悪性) |
|---|---|---|
_npmUser.name |
GitHub Actions |
jasonsaayman |
_npmUser.email |
npm-oidc-no-reply@github.com |
ifstap@proton.me |
_npmUser.trustedPublisher |
あり(OIDC) | なし |
gitHead |
46bee3dea75e... |
なし |
dependencies |
3個 | 4個(plain-crypto-js 追加) |
maintainers[jasonsaayman].email |
jasonsaayman@gmail.com |
ifstap@proton.me |
正規リリースは GitHub Actions OIDC(trustedPublisher 付き)による短命トークンで行われていたため、trustedPublisher なし・gitHead なしの手動 CLI パブリッシュは明確な異常です。maintainers のメールアドレスが攻撃者管理の ifstap@proton.me に変更されていることも確認できます。
アカウントまたは publish に用いられた NPM_TOKEN がどのように侵害されたか(トークン窃取の経路)は、現時点で定かではありません。なお、v1.x 系には npm trusted publishing(GitHub Actions OIDC)が設定されていましたが、publish workflow が NODE_AUTH_TOKEN 環境変数も併用しており、npm はトークンと OIDC が両方存在する場合トークンを優先します。この構成が今回の侵害の一因となった可能性がありますが、正確な経路は不明です。v0.x 系はそもそもトークンのみでした。
侵害先での発火経路
今回の侵害では、axios 自体のソースコードには悪性コードが注入されていません。代わりに、package.json の dependencies に plain-crypto-js という悪性パッケージが追加されており、そちらの postinstall フックが攻撃の起点になります。
| バージョン | 注入箇所 | 発火条件 |
|---|---|---|
1.14.1 / 0.30.4 |
plain-crypto-js の postinstall フック(setup.js) |
npm install 時(インストール時) |
つまり、axios@1.14.1 または axios@0.30.4 を npm install した時点で(--ignore-scripts を付けていない限り)、悪性コードが実行されます。
plain-crypto-js は axios のソースコードから一切 import されておらず、ランタイム依存としての必然性がありません。依存追加だけで攻撃が成立する手口です。これは古くは event-stream 侵害の際も用いられた、悪性コードを直接侵害先に含めない手法です。(少しでも悪性判定されにくくするための工夫であるものと予想します。)
環境毎の動作差異
環境毎に動作に違いがあります。いずれも C2 サーバ sfrclak[.]com:8000 から Stage 2 のペイロードをダウンロードして実行しますが、ダウンロード手段・配置先・永続化手法がプラットフォームごとに異なります。
また、C2 への通信時に POST ボディとして packages.npm.org/product0(macOS)、packages.npm.org/product1(Windows)、packages.npm.org/product2(Linux)という値が送信されます。packages.npm.org は npm の正規ドメインではなく、攻撃者が C2 通信をネットワークログ上で npm レジストリ通信に見せかけるために使用している偽装文字列です。
| プラットフォーム | 動作内容 |
|---|---|
| macOS | AppleScript 経由で RAT バイナリを /Library/Caches/com.apple.act.mond にダウンロード・バックグラウンド実行。その後スクリプトは削除される |
| Windows | PowerShell を %PROGRAMDATA%\wt.exe にコピーし、VBScript 経由で RAT をバックグラウンド実行。その後スクリプトは削除される |
| Linux | curl で Python RAT を /tmp/ld.py にダウンロード、nohup でバックグラウンド実行。その後スクリプトは削除される |
また、これら挙動をする setup.js も実行後に自身を削除します。また、postinstall フックを含む package.json を事前に配置しておいたクリーンな package.md で差し替えます。結果として、永続化ファイル以外の痕跡が残りにくくなっており、感染後に node_modules/plain-crypto-js/ を検査しても完全にクリーンに見えます。plain-crypto-js/ ディレクトリの存在自体は痕跡となります。
対応指針
以下は公開情報を踏まえた参考情報であり、記録として示すものです。 正確性・網羅性を保証するものではなく、本指針に基づく対応の結果について筆者は一切の責任を負いません。 実際の対応は各組織の判断に基づいて行ってください。
以下は端末単位での対応手順です。npm install がどのディレクトリで実行されたかを正確に把握することは現実的に困難なため、端末内全体を走査する前提で記載しています。
1. 影響有無の確認
以下を参考にして影響有無を確認してください。
なお、今回は 疑わしきは罰する の方向で調査・クレデンシャルローテーションなどの対応することを推奨します。間接依存も含め、axios はいたるところで利用があり、axios にピンと来ないような環境でも影響が及びうるためです。
また、EDRやプロキシなどの入っていない、高権限の認証情報を取り扱う環境も対象にしてください。GitHub Actions などの CI/CD 環境はその最たる例です。
1a. バックドアファイルの確認
まず、プラットフォーム固有のバックドアファイルが存在するかを確認してください。存在すれば、感染確定です。
macOS:
ls -la /Library/Caches/com.apple.act.mond
Windows:
dir "%PROGRAMDATA%\wt.exe" dir "%TEMP%\6202033.vbs" dir "%TEMP%\6202033.ps1"
Linux:
ls -la /tmp/ld.py
1b. 端末内の全プロジェクトを走査
npm ls axios は間接依存(transitive dependency)も表示するため、直接依存していないプロジェクトでも検出可能です。ただし、npm install を実行したディレクトリで実行する必要があります。端末内の全 node_modules を走査するには、以下のようにします。
# 端末内の全 node_modules から plain-crypto-js を検索(存在自体が痕跡) find / -type d -name "plain-crypto-js" -path "*/node_modules/*" 2>/dev/null
plain-crypto-js は自身の痕跡を消去しますが、ディレクトリ自体は残ります。見つかった場合は感染の可能性が高いです。
1c. lockfile の走査
# 端末内の全 lockfile から plain-crypto-js を検索
find / -name "package-lock.json" -exec grep -l "plain-crypto-js" {} \; 2>/dev/null
find / -name "yarn.lock" -exec grep -l "plain-crypto-js" {} \; 2>/dev/null
find / -name "pnpm-lock.yaml" -exec grep -l "plain-crypto-js" {} \; 2>/dev/null
lockfile が再生成済みの場合はこの方法では検知できません。
1d. ネットワークログの確認
C2 ドメイン sfrclak[.]com および IP 142[.]11[.]206[.]73 へのアウトバウンド通信(ポート 8000)がないかネットワークログを確認してください。また、悪性バージョンの露出期間(3月31日 09:21〜12:15 JST)に npm install が実行された形跡がないかも照合してください。
2. バックドアの除去とプロセスの停止
バックドアファイルが存在した場合は削除してください。また、関連プロセスが動作中でないかを確認し、停止してください。
macOS:
# バックドアの削除 rm -f /Library/Caches/com.apple.act.mond # 関連プロセスの確認・停止 ps aux | grep com.apple.act.mond
Windows:
# バックドアの削除 del "%PROGRAMDATA%\wt.exe" del "%TEMP%\6202033.vbs" del "%TEMP%\6202033.ps1" # 関連プロセスの確認 tasklist | findstr wt.exe
Linux:
# バックドアの削除 rm -f /tmp/ld.py # 関連プロセスの確認・停止(ppid=1 で動作している可能性) ps aux | grep ld.py
3. 悪性パッケージの除去とダウングレード
感染が確認されたプロジェクトで以下を実行してください。
rm -rf node_modules/plain-crypto-js npm install axios@1.14.0 --ignore-scripts # レガシー利用の場合は axios@0.30.3
package.json でバージョンをピン留めし、overrides / resolutions での固定も推奨です。
{ "dependencies": { "axios": "1.14.0" }, "overrides": { "axios": "1.14.0" } }
4. クレデンシャルのローテーション
感染が確認された、または否定しきれない端末では、当該端末内のあらゆるクレデンシャルのローテーションを検討してください。特に以下は優先的にローテーションすべきです。
- npm トークン
- AWS / GCP / Azure 等のクラウドクレデンシャル
- SSH 秘密鍵
- CI/CD シークレット
.envファイル内の値
5. CI/CD 環境の確認
CI/CD パイプラインで悪性バージョンの npm install が実行された場合、パイプラインに注入されたシークレットも漏洩している可能性があります。該当する実行ログを確認し、必要に応じてシークレットをローテーションしてください。
推奨:自衛手段の整備
3月中のサプライチェーン攻撃は、Trivy、LiteLLM、Telnyx、そして今回の axios へと波及しています。次にどのパッケージが狙われるかは予測できないため、可能な限りの自衛を推奨します。
npm の min-release-age
npm v11 以降では .npmrc に min-release-age を設定することで、公開から一定期間が経過していないバージョンのインストールを抑止できます。この状況下では 7 日程度を推奨します。急ぐ場合でも 3 日程度は確保してください。
今回の axios のようにエコシステム全体で騒がれる規模の侵害は、数時間でテイクダウンされます。しかし、より小規模なパッケージや依存の深い階層で起こる侵害は発見が遅れ、数日間以上にわたって npm 上に残存することもあります。検疫期間はそうした「気づかれにくい侵害」に対してこそ効果を発揮します。
# .npmrc min-release-age=7
pnpm の trustPolicy: no-downgrade
pnpm には trustPolicy: no-downgrade という仕様があり、パッケージの信頼度が下がるような更新(例:OIDC による trusted publishing から手動パブリッシュへの切り替え)をブロックできます。今回の axios の問題の2バージョンは、この設定を有効化していればブロックされます。 ただし、今後 axios 経由で他のパッケージ(例えば axios の依存パッケージ)が侵害された場合に、trustPolicy: no-downgrade でブロックできないケースが存在する可能性はあります。
Takumi Guard
弊社(GMO Flatt Security)から、セキュアなレジストリプロキシ Takumi Guard の npm エンドポイント をリリースしています。
Takumi Guard は npm(レジストリ)との間に位置するセキュリティプロキシで、悪意あるパッケージがブロックされます。弊社で全ての新規パッケージを検査しています。
導入は registry URL の変更のみで完了し、無料で利用可能です。必要に応じて利用を検討してください。
# npm npm config set registry https://npm.flatt.tech/ # yarn v1 yarn config set registry https://npm.flatt.tech # yarn v2+ yarn config set npmRegistryServer https://npm.flatt.tech # pnpm pnpm config set registry https://npm.flatt.tech/
仮にある時点ではパッケージがマルウェアと判定できず、ブロックされなかった場合も、後日の通知を行う仕組みもあります(本機能も無料です)。 通知のためにはメールアドレス登録が必要となりますので、下記ページよりご登録ください。
なぜ無料なのか、大丈夫なのかとご心配いただくこともありますが、アカウントやダウンロードログの管理など、法人向け有償機能の開発も予定しております。ご興味のある方はお問い合わせください。
さらなる対応
環境ごとに、攻撃途中のTTPsに含まれる実行コマンドの一部を使ったハンティングや検知ルール策定を行うのも効果的です(※この点に関しても、後ほど追記できれば追記します)。同じ攻撃者であれば、TTPsは使いまわされることも多い為です。複数の箇所で検知ポイントを持っておくことを推奨します。
IoCs
筆者が把握できている限りでの、Indicators of Compromise(IoCs)を以下に示します。
ネットワーク
| 種別 | 値 | 備考 |
|---|---|---|
| ドメイン | sfrclak[.]com |
C2 ドメイン |
| IP | 142[.]11[.]206[.]73 |
C2 IP アドレス |
| URL | http://sfrclak[.]com:8000/6202033 |
C2 エンドポイント |
パッケージそのもの
| 種別 | 値 |
|---|---|
| 侵害バージョン | axios@1.14.1, axios@0.30.4 |
| 悪性依存パッケージ | plain-crypto-js@4.2.1 |
攻撃者アカウント
| アカウント | メールアドレス | 備考 |
|---|---|---|
jasonsaayman(npm/GitHub) |
ifstap@proton.me(変更後) |
侵害されたメンテナアカウント |
nrwise(npm) |
nrwise@proton.me |
plain-crypto-js 公開用の使い捨てアカウント |
永続化に関わるもの
| プラットフォーム | パス | 備考 |
|---|---|---|
| macOS | /Library/Caches/com.apple.act.mond |
Apple デーモンを偽装した RAT バイナリ |
| Windows | %PROGRAMDATA%\wt.exe |
Windows Terminal に偽装した PowerShell コピー |
| Windows | %TEMP%\6202033.vbs |
VBScript ローダー(自己削除) |
| Windows | %TEMP%\6202033.ps1 |
PowerShell RAT スクリプト(自己削除) |
| Linux | /tmp/ld.py |
Python RAT スクリプト |