TanStack含む416件のnpmパッケージにワーム感染

TanStack含む416件のnpmパッケージにワーム感染

週間1200万ダウンロードのJavaScriptルーティングライブラリが今日、CIシークレットを盗み自律的に拡散するワームに感染した。攻撃は現在も進行中で、Mistral AIやUiPathにも被害が広がっている。


GitHub Actionsの信頼を逆手に取った侵入経路

今日(日本時間2026年5月12日)午前4時台、npmレジストリに異常が発生した。TanStack名前空間の42パッケージに対し、84バージョンが立て続けに公開されたが、それらはいずれも悪意あるコードを含んでいた。

攻撃者の手口は三段階で構成される。まずGitHubアカウント「voicproducoes」がTanStack/routerにフォークを作成し、2.3MBの難読化されたJavaScriptペイロードを含むコミットを追加。次に、フォークからのPRに対しても本リポジトリの権限で動く pull_request_target トリガーを悪用し、GitHub Actionsのキャッシュにマルウェアを混入させた。

正規のPRがマージされると汚染されたキャッシュが復元される。その後、ワークフロー実行中にランナープロセスのメモリから OIDCトークン を直接読み取り、npmへの公開権限を奪取。npm側の認証情報は一切流出していないにもかかわらず、正規のパブリッシュパイプラインとして認証された形でワームが展開された。

TanStackの創設者タナー・リンズリー(Tanner Linsley)は次のように述べている。

攻撃者は孤立したコミットを使ってOIDCトークンを保持するワークフロー実行にアクセスし、既存のパブリッシュ保護を実質的に迂回した。チーム全員に二段階認証が有効だったにもかかわらず、だ。

OIDC(OpenID Connect)によるトークンレス公開は「サプライチェーンの銀の弾丸」として普及してきたが、今回の攻撃はその前提を根底から揺るがした。

Mini Shai-Hulud 攻撃フロー
1
フォーク&キャッシュ汚染GitHub Actions
攻撃者が TanStack/router にフォークを作成し、
悪意あるコミットで pull_request_target ワークフローを
トリガー。Actions キャッシュを汚染する。
2
OIDC トークン窃取メモリ読み取り
正規 PR のマージ後、汚染キャッシュが復元。
Runner プロセスのメモリから OIDC JWT を直接抽出し、
npm パブリッシュ権限を取得する。
3
ワーム埋め込みパッケージを公開Sigstore 証明付き
盗んだ OIDC トークンで 84 バージョンを一斉公開。
有効な SLSA プロバナンス証明が自動付与されるため、
見た目は正規リリースと区別がつかない。
4
インストール時にデーモン起動npm install
router_init.js(2.3 MB)が実行され、
切り離しプロセスとしてバックグラウンドに潜伏。
ターミナルには何も表示されない。
5
認証情報の一斉収集CI・クラウド・K8s
GitHub Actions シークレット・AWS キー・HashiCorp Vault
トークン・Kubernetes サービスアカウントを横断的に窃取。
Claude Code と VS Code にも永続化して再起動後も生存。
6
P2P ネットワーク経由で流出+自己増殖Session Network
収集した情報を Session(分散型 P2P メッセージング)
で送信。ネットワーク監視では検出困難。
さらに別パッケージにも感染版を公開し連鎖が続く。

感染したパッケージが自力で増殖する仕組み

今回の攻撃が一般的な改ざんと異なるのは、ワームとして自律増殖する点だ。

感染パッケージをインストールすると、埋め込まれた router_init.js(2.3MB)が実行される。まず __DAEMONIZED 環境変数を確認し、未設定なら自分自身を切り離しプロセスとしてフォーク。stdio['ignore', 'ignore', 'ignore'] に設定することでターミナル出力から完全に隠れ、npm install の画面には何も表示されない。

その後、開発者の環境に永続化する。注目すべきは .claude/settings.json への書き込みだ。

Claude Codeは hooks 設定によりファイル編集やbash実行などのツールイベントに対してシェルコマンドを実行できる仕組みを持つ。この仕組みを悪用することで、元のnpmパッケージを削除した後でも、開発者がClaude Codeを使うたびにワームが再実行され続ける。

永続化先はClaude Codeの .claude/ ディレクトリと、VS Codeの .vscode/tasks.json(フォルダオープン時に自動実行)の2箇所。npm uninstall だけでは除去できない。

盗まれる認証情報の規模

認証情報の収集範囲は、現代のクラウドネイティブ環境のほぼすべてをカバーしている。

GitHub Actionsのシークレット一覧(1リクエストで最大100件)、AWS環境変数(AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY)、EC2インスタンスメタデータサービス(IMDSv2に対応。無効化された環境でも突破する実装)、HashiCorp Vaultのトークン(Kubernetes内部DNS vault.svc.cluster.local:8200 を直接狙う)、Kubernetesサービスアカウントトークン——と続く。

ワームが狙う認証情報:系統別の収集手法
系統 主な取得方法 取得対象 特記事項
GitHub
Actions
環境変数の直接読み取り+
REST API 呼び出し
シークレット一覧
(最大100件/回)
OIDC トークン取得
エンドポイントも窃取
AWS 環境変数+
IMDSv2 メタデータ
サービスへの HTTP リクエスト
アクセスキー・
ロール ARN・
IRSA トークン
IMDSv2 無効化環境
でも突破。
マルチリージョン対応
HashiCorp
Vault
環境変数+
Kubernetes 内部 DNS
への直接接続
VAULT_TOKEN・
VAULT_AUTH_TOKEN・
VAULT_ADDR
K8s SA トークンと
連携して完全な
認証チェーンを構築
Kubernetes ファイルシステムの
クレデンシャルパス
を直接読み取り
SA トークン・
CA 証明書・
名前空間情報
RBAC 設定次第で
cluster-admin 権限
まで到達可能
npm レジストリ OIDC 連携で
パブリッシュトークンを
自動取得
maintainer が管理する
全パッケージへの
パブリッシュ権限
取得後に Sigstore
証明付きで感染版を
自動公開して増殖
※ Socket Threat Research Team および TanStack 公式ポストモーテムの技術分析に基づく整理。IMDSv2 の多リージョン対応・Kubernetes クレデンシャルパスの詳細は Socket の調査レポートより。

奪った認証情報の流出先として選ばれたのは、通常のHTTPSサーバーではなく Sessionネットワーク だ。分散型メッセージングアプリのSessionのプロトコルスタック全体が2.3MBペイロードに組み込まれており、C2トラフィックはエンドツーエンド暗号化された通常のメッセージングトラフィックと区別がつかない。ネットワーク監視での検出は極めて困難だ。

さらに、窃取したOIDCトークンを使って、攻撃対象の維持管理するすべてのnpmパッケージに感染版を公開。GitHubのGraphQL APIでリポジトリに直接コミットし、その際の著者名として [email protected]——正規のClaude Code GitHub AppのID——を詐称する。Claude Codeが承認済みインテグレーションになっているリポジトリでは、このコミットが正常な活動に埋もれる。

「安全の証明」がワームを隠す

今回の攻撃が業界に突きつけた最大の問題は、セキュリティの証明として機能してきた仕組みが逆用されたことだ。

npmのSigstoreプロバナンスバッジは「このパッケージは信頼できるCIパイプラインで生成された」ことを示すものとして普及してきた。しかし感染版パッケージには SLSA の最高位認証であるBuild Level 3プロバナンス証明が有効な形で付与されている。攻撃者はGitHub Actionsで実行できれば正規のSigstoreスタックで有効な証明を生成できることを示した。Sigstoreプロバナンスバッジを持つ悪意あるnpmパッケージとして、初めて記録された事例だ。

PythonのWebフレームワーク「Flask」の作者として知られるアルミン・ロナハー(Armin Ronacher)氏は次のようにXに書いた。

OIDCトラステッドパブリッシングがサプライチェーン問題の銀の弾丸だという考えが、これで終わりになってほしい。

被害はTanStackにとどまらず拡大し続けている。Socketの追跡によれば現時点で 416件 のパッケージアーティファクトが侵害されており、Mistral AIのnpmパッケージ(@mistralai/mistralai 2.2.2〜2.2.4など)、UiPath製品群、OpenSearch Node.jsクライアント、guardrails-aiなどが含まれる。

今すぐ確認すべきこと

5月11日(UTC)に @tanstack/*@mistralai/*@uipath/*@draftlab/* のいずれかのパッケージを npm install した環境は、感染していると想定して対応する必要がある。

まず依存ツリー内のすべての router_init.js に対して shasum -a 256 を実行し、ハッシュが ab4fcadaec49c03278063dd269ea5eef82d24f2124a8e15d7b90f2fa8601266c と一致するか確認する。一致した場合、その環境から到達可能なnpmトークン、GitHub PAT、AWSの認証情報(静的キーとインスタンスロール)、Vaultトークン、Kubernetesサービスアカウントトークンをすべてローテーションしなければならない。

開発者ディレクトリについては .claude/ および .vscode/ 内を確認し、router_runtime.jssetup.mjssettings.json の不審なエントリを削除する。GitHubリポジトリには git log --all [email protected] で偽装コミットが残っていないか確認し、発見した場合は強制プッシュで除去する。

また、トークンを失効させる前に マシンイメージ を取得しておくことを強く推奨する。ペイロードにはトークン失効を検知してマシンをワイプする破壊ルーティンが含まれているとの報告があるためだ。

攻撃は今もリアルタイムで進行中だ。まず今日インストールした依存関係の確認から始めてほしい。


参照元

他参照

関連記事

この記事を共有する