Axiosが乗っ取られた — npm史上最大級のサプライチェーン攻撃の手口と2行でできる防御策

はじめに

2026年3月31日、週間1億ダウンロードを超えるnpmパッケージ「Axios」が、わずか3時間だけ乗っ取られた。影響を受けたバージョンをインストールした開発者のマシンには、クロスプラットフォーム対応のリモートアクセス型トロイの木馬(RAT)が仕込まれた。攻撃の背後にいたのは、北朝鮮の国家支援型脅威アクター「UNC1069(Sapphire Sleet)」だ。

この記事では、攻撃がどのように実行されたかを時系列で追い、なぜ既存の防御が突破されたのかを技術的に分析する。そして、.npmrcにたった2行追加するだけで同種の攻撃を防げる具体的な対策を解説する。

ソーシャルエンジニアリングから始まった侵入経路

今回の攻撃で特筆すべきは、コードの脆弱性ではなく「人間」が突破口になった点だ。

2週間にわたる信頼構築

攻撃者はAxiosのリードメンテナーに対し、約2週間かけて周到なソーシャルエンジニアリングを仕掛けた。企業ブランディングを模倣したWebサイト、偽のLinkedInプロフィール、他のOSSメンテナーを装った偽のSlackワークスペースまで構築し、正規の企業からの連絡であるかのように見せかけた。

RAT感染とnpmアカウント奪取

Teams会議を通じて「ルーティンなシステムアップデート」としてマルウェアのインストールを誘導。実体はクロスプラットフォーム対応のRATで、これがメンテナーのマシンに常駐した。RATはスクリーンキャプチャ機能を持ち、TOTP(時間ベースワンタイムパスワード)による2FAすら突破。メンテナーの端末から直接npm publishが実行された。

攻撃のタイムライン

時刻(UTC)出来事
3月17日頃メンテナーへのソーシャルエンジニアリング開始
3月30日 05:57悪意あるパッケージ plain-crypto-js@4.2.0 がnpmに公開
3月31日 00:21axios@1.14.1 が侵害された依存関係付きで公開
3月31日 ~01:00レガシー版 axios@0.30.4 も同様に侵害
3月31日 01:38コミュニティの通報でnpmが対応開始
3月31日 03:15悪意あるパッケージが削除(公開から約3時間)

攻撃の技術的メカニズム

Axiosのソースコード自体は一切改変されていない。攻撃者が行ったのは、package.jsonに1行の依存関係を追加しただけだ。

"dependencies": {
  "plain-crypto-js": "^4.2.1"
}

開発者やCIが npm install axios@1.14.1 を実行すると、npmは依存ツリーを解決し、plain-crypto-js@4.2.1 をダウンロード。このパッケージのpostinstallフックが自動的に node setup.js を実行し、RATのデプロイが始まる。

npmのライフサイクルスクリプトは、パッケージのインストール時に任意のコードを実行できる正規の機能だ。ネイティブモジュールのコンパイルやバイナリのダウンロードに使われるが、今回はこの仕組みが攻撃ベクトルとして悪用された。RATはmacOS、Windows、Linuxのすべてで動作するクロスプラットフォーム仕様で、感染したシステムは完全にリモート制御可能な状態になった。

なぜ既存の防御は機能しなかったのか

この攻撃が成功した背景には、複数のセキュリティ上のギャップがある。

TOTP 2FAの限界: ハードウェアキー(FIDO2)であればリモートからの窃取は不可能だが、TOTPはスクリーンキャプチャや入力キャプチャで突破できる。npmアカウントの2FAとしてTOTPだけに依存していたことが致命的だった。

ローカルからの直接パブリッシュ: CI/CDパイプラインを経由せず、開発者のローカルマシンから直接npm publishできる運用だった。CI経由での公開を強制していれば、侵害されたマシンからの不正公開を防げた可能性が高い。

自動監視の不在: 3時間の公開期間中、不正を検知したのはコミュニティの目だった。依存関係の変更を自動監視する仕組みが整備されていなかった。

.npmrcの2行で実現できる防御策

この攻撃は、プロジェクトの.npmrcにたった2行を追加するだけで防げた。

ignore-scripts=true
min-release-age=3

ignore-scripts=true

npmのライフサイクルスクリプト(preinstallpostinstallなど)の自動実行を無効化する。今回の攻撃はpostinstallフックが起点だったため、この設定だけで侵害を完全にブロックできた。

ただし、ネイティブモジュール(bcryptsharpなど)のようにpostinstallでのコンパイルが必須なパッケージもある。その場合は個別に明示的にリビルドすればよい。

npm rebuild bcrypt --ignore-scripts=false

min-release-age=3

公開から3日未満のパッケージバージョンをインストール対象から除外する設定だ。今回の悪意あるバージョンは約3時間で削除されたため、この設定があれば自動的にスキップされていた。

この機能はnpm v11.10.0(2026年2月リリース)以降で利用可能だ。多くのサプライチェーン攻撃は「公開→短時間で削除」というパターンを取るため、この「検疫期間」の設定は非常に効果的である。

2つの防御層の意味

どちらか一方だけでも今回の攻撃は防げた。しかし、両方を設定することで異なるタイプの攻撃に対する多層防御が実現する。ignore-scriptsはスクリプト実行型の攻撃を、min-release-ageは短期公開型の攻撃をそれぞれブロックする。

エンジニアが今すぐ確認すべきこと

影響の確認

まず、自分のプロジェクトが影響を受けたか確認しよう。

grep -E "axios@(1\.14\.1|0\.30\.4)|plain-crypto-js" package-lock.json yarn.lock

該当するバージョンが見つかった場合、そのマシンは侵害された可能性がある。パッケージの削除だけでなく、認証情報のローテーションを含む包括的な対応が必要だ。

組織レベルでの対策

  • npmアカウントにFIDO2ハードウェアキーを設定する — TOTPだけでは不十分
  • CI/CDからのみパブリッシュを許可する — ローカルマシンからの直接公開を禁止
  • OIDCベースのパブリッシュプロトコルを導入する — GitHub ActionsのOIDCトークンなど
  • 依存関係の変更を自動監視するnpm auditやSnykなどのツールを活用

まとめ

  • Axiosの侵害は、コードの脆弱性ではなくソーシャルエンジニアリングによるメンテナー個人への攻撃が起点だった
  • npmのpostinstallフックという正規機能が攻撃ベクトルとして悪用された
  • .npmrcignore-scripts=truemin-release-age=3を設定するだけで、同種の攻撃の大半を防げる
  • 根本的な対策として、FIDO2キーの導入とCI/CD経由でのパブリッシュ強制が重要

週間1億ダウンロードのパッケージでさえ、「人」が最も脆弱なリンクになりうる。まずは今日、自分のプロジェクトの.npmrcを確認することから始めてほしい。

ソース