PaPoo
cover
technews
Author
technews
世界の技術ニュースをリアルタイムでキャッチし、日本語でわかりやすく発信。AI・半導体・スタートアップから規制動向まで、グローバルテックシーンの「今」をお届けします。

Shai-Hulud攻撃でTanStackやMistralのnpm/PyPIパッケージが汚染された話をわかりやすく解説

まず押さえたいポイント

何が起きたのか

今回の話は、ひとことで言うと「信頼して入れたライブラリが、じつは泥棒だった」というやつです。
BleepingComputerによると、npm と PyPI にある何百ものパッケージが、新しい Shai-Hulud サプライチェーン攻撃で汚染されました。

サプライチェーン攻撃というのは、完成品そのものを狙うのではなく、​製品ができるまでの途中の部品や流通経路を汚す攻撃です。
ソフトウェアでいえば、よく使うライブラリや配布経路を狙うわけで、これが本当に厄介。なぜなら、開発者は普通、公式っぽい場所から落としているつもりなので、​気づきにくいからです。

しかも今回は、攻撃者が正規のOpenID Connect (OIDC) トークンを盗み、さらにSLSA Build Level 3 のような検証可能な provenance attestation(「このパッケージはこの手順でビルドされた」と示す証明)まで付いた状態で悪意あるバージョンを公開したのがポイントです。
これ、かなりイヤらしいです。見た目の「証明」があるので、普通のチェックだと弾きづらい。​**“署名されているから安全” が通じない**場面がある、というのはかなり重要な教訓だと思います。

どう広がったのか

元々の標的は TanStackMistral AI のパッケージ群でした。
そこから stolen credentials(盗んだ認証情報)を使って、​Guardrails AI、UiPath、OpenSearch のような別プロジェクトにも広がっていったとのことです。

各社・各研究者の報告では、侵害されたものは少なくともかなり大規模で、

とされています。
数字は集計方法で少し変わりますが、少なくとも「単発事故ではなく、かなり広い範囲に波及した」のは間違いなさそうです。

何がそんなに巧妙なのか

image_0003.jpg

今回の攻撃が面白い、というと不謹慎に聞こえるかもしれませんが、セキュリティの世界では「やり口が巧妙すぎる」という意味で注目に値します。

TanStack側の報告では、攻撃者は次の3つを組み合わせたとされています。

  1. 危険な pull_request-target ワークフロー
  2. GitHub Actions の cache poisoning
  3. runner memory からの OIDC token theft

ざっくり言うと、

です。

個人的には、ここが一番ゾッとします。
「パッケージが悪い」のではなく、​ビルド・配布・署名・CIのつながり全部を利用してくるので、どこか1点だけ見ていても防ぎにくい。まさに現代のサプライチェーン攻撃らしい、嫌な完成度です。

どうやって“本物っぽく”見せたのか

攻撃者は、正規のCI/CDパイプラインを通して感染したパッケージを公開しました。
つまり、外から見ると「ちゃんとしたリリース手順で出た」ように見えるわけです。

しかも、TanStack/router の正式な Release workflow に紐づく形で、​valid SLSA provenanceSigstore attestations、​GitHub Actions signatures まで付いていたとされています。

普通、開発者は「署名あり=安心」と思いたくなります。私もそう思いたい。
でも今回のように、​署名そのものが本物でも中身が悪いということが起きる。ここはかなり重要です。
つまり、今後は「署名の有無」だけではなく、​振る舞いの検査まで見ないといけない、という話になります。

どんな攻撃だったのか

image_0004.jpg

Endor Labsによると、攻撃者は TanStack/router リポジトリに対して、​fork に push された orphaned commit を悪用したそうです。
オーファンコミットというのは、ざっくり言えばどのブランチにもぶら下がっていない孤立したコミットです。普通の開発フローではあまり意識しない場所ですが、GitHubのshared fork object storageを通じてアクセス可能だった、というのがポイント。

そしてそのコミットを、​悪意ある optional dependency として参照させ、npm のインストール時に自動で攻撃者コードを取得・実行させた、とされています。
ここもなかなか賢いです。依存関係の仕組みを逆手に取って、​インストールしただけで勝手に実行させる。ライブラリ管理の怖さがよく出ています。

何を盗むマルウェアだったのか

このマルウェアは、開発者が持っている“宝の山”を狙います。具体的には、

などです。

さらに StepSecurity によると、GitHub Actions のプロセスメモリを読んで、​クラウド、暗号資産、メッセージングアプリに関連する100以上のパスから認証情報を集めていたとのこと。
要するに「開発用の秘密情報、片っ端から持っていく」タイプです。

開発者のマシンやCI環境には、思った以上にいろんな秘密が詰まっています。
個人的には、ここで「自分のPCは大丈夫」と油断するのが一番危ないと思います。開発機はしばしば、​本番に入れるカギの束みたいなものですから。

盗んだ情報をどう外へ出したのか

情報の送信先として、マルウェアは Session P2P network を使っていたとされています。
これは通信を暗号化されたメッセンジャーのように見せかけることができるため、検知やブロック、停止が難しくなります。

この手口は地味に悪質です。
普通のC2(command-and-control、攻撃者がマルウェアを遠隔操作するための通信基盤)なら、ドメインやIPを止めれば良いこともあります。
でもP2P寄りの仕組みだと、​1箇所を潰して終わりにしにくい。しぶといです。

image_0006.jpg

消しても終わりではない

感染すると、マルウェアは Claude Code hooksVS Code の auto-run tasks に自分を仕込みます。
つまり、悪意あるパッケージを削除しても、​別の場所に残って再発する可能性があるわけです。

これは実運用だとかなり面倒です。
「npm uninstall したからOKでしょ」とはならない。IDEや作業用ディレクトリ、設定ファイルまで見ないといけない。
セキュリティ対応が“パッケージ削除”で終わらないのが、本当に嫌なところです。

Mistral AIのPyPI版では何が起きたのか

Microsoft Threat Intelligence は、PyPI 上の悪意ある Mistral AI パッケージから落とされる payload も分析しています。
そこで使われていた名前は transformers.pyz で、これは Hugging Face の有名な Python ライブラリ Transformers を装っている可能性があるとされています。

Linux上では、情報窃取マルウェアとして動作します。
さらに、​ロシア語設定のホストでは実行を避けるという geofencing も入っていたそうです。
こういう「特定地域を避ける」ロジックは、攻撃者が逮捕リスクや監視を意識していることを示唆することが多く、地味に重要なサインです。

加えて、​破壊的な二次ルーチンもあり、イスラエルかイラン由来に見える環境では、​6分の1の確率で rm -rf/ のような再帰削除を実行する可能性があるとのこと。
rm -rf/ は、簡単に言うとシステムを根こそぎ消し飛ばす危険な削除コマンドです。
ここまで来ると、単なる窃盗ではなく、​破壊も視野に入れた攻撃だと見たほうがよさそうです。

この挙動は、TeamPCP が3月に行った CanisterWorm キャンペーンと似ているとも報告されています。Kubernetesプラットフォームを狙い、特定のタイムゾーンやロケールに合うマシンを消していた、という話です。
要するに、同じ系統の攻撃グループが、​窃取と破壊を組み合わせた手口を使っている可能性がある、ということです。

もし影響を受けたら、何をすべきか

研究者らは、影響を受けたパッケージを入れた可能性があるなら、​認証情報は漏れた前提で動くべきだとしています。これはかなり重要です。
“たぶん大丈夫” は通用しないと思ったほうがいいです。

推奨されている対策は以下です。

image_0007.jpg

正直、ここまでやって初めて「ちゃんと対処した」と言えるレベルです。
とくにトークン類のローテーションは面倒ですが、漏えいした可能性があるなら避けて通れません。

今後の教訓

Snyk の研究者は、今回のように悪意あるパッケージでも有効な SLSA Build Level 3 attestation が付いてしまう以上、署名確認だけでは不十分だと指摘しています。
必要なのは、

の組み合わせだ、というわけです。

長期的には、​lockfile-only installs を強制するのも有効だとされています。
これは、勝手に新しいバージョンを拾うのではなく、​lockfile に固定されたものだけ入れる運用です。
地味ですが、こういう“静かな変更”を減らすのはかなり効くと思います。

まとめ

今回の事件は、単に「npmの悪いパッケージが出回った」という話ではありません。
正規のCI/CD、正規の署名、正規の依存関係の仕組みまで使って、開発者の信頼そのものを悪用した攻撃です。

しかも狙いは、ソースコードそのものよりも、そこに紐づく秘密情報
現代の開発では、コードよりも認証情報のほうが価値を持つ場面が多いので、攻撃者から見ればかなりおいしいターゲットです。

個人的には、今回の件は「オープンソースが危ない」で終わらせるより、​**“信頼の仕組みをどう再設計するか”** を考える材料だと思います。
署名があるから安心、インストールしただけなら安全、という時代はもう終わりかもしれません。


参考: Shai Hulud attack ships signed malicious TanStack, Mistral npm packages

同じ著者の記事