攻撃者は、あなたのサービスを狙っていない
先日、開発パートナーから「これ三つだけやっといて」と頼まれた。
npm、pip、bundler。それぞれのパッケージ取得を、セキュリティチェック付きのプロキシ経由に切り替える設定だ。
正直に言うと、最初の反応は「えっ、それ私もやる必要ある?」だった。
というのも、私はそのパートナーのGitHubにアクセス権を持っていない。一緒に触っているのはごく一部で、向こうのリポジトリやクラウドの本丸には入れない。だったら、仮に何か危ないものが紛れ込んでも、被害が及ぶのは"権限を持っている人"であって、外野の私には大して関係ないのでは——という理屈だ。我ながら、もっともらしい。
それでも、言われた通りにやることにした。トークンはもう渡してあるし、コマンドを数行ずつ打つだけ。テスト用にわざと用意された「悪意のあるパッケージ」を入れてみて、ちゃんと403で弾かれるのを確認して、作業自体は5分で終わった。
そして、終わってから調べはじめて、自分の最初の理屈が見事に的を外していたことを、じわじわと思い知ることになる。
そもそも、この手の攻撃って、何を盗んでいるんだっけ?
「自分はアクセス権を持っていないから」という油断
私の中の素朴な理解はこうだった。「GitHubやAWSのアクセス権を乗っ取って、リポジトリやクラウドを好き放題される」。ニュースの見出しも、だいたいそういう顔をしている。
冒頭の「パートナーのGitHubに入れないから関係ない」も、AWSをほとんど使わない私が「AWSのキーが狙われる、と言われてもピンとこない」のも、根っこは同じだ。アクセス権やサービス名で、自分の危険度を測ろうとしている。
ここに落とし穴がある。そうやって測ろうとした瞬間に、判断を間違えるのだ。後で書くとおり、この攻撃の本質は、「どのサービスに、どんな権限を持っているか」という問いの、外側にあった。
Shai-Hulud という名前のワーム
2025年9月、npmで初めての「自己増殖するワーム」が観測された。Shai-Hulud(シャイ・フルード、砂漠の砂虫の名前だ)。@ctrl/tinycolorという小さなパッケージを起点に、500以上のパッケージへ感染が広がった。
仕組みが厄介だった。メンテナのアカウントを乗っ取ると、マルウェアがそのメンテナの他のパッケージを自動で書き換えて再公開する。人間が一個ずつ仕込むのではなく、勝手に増える。文字どおりワームだ。
そして11月、より凶暴な第二波が来た。リポジトリの説明文に「Sha1-Hulud: The Second Coming(再臨)」と書かれた、Shai-Hulud 2.0だ。集計によっては796個のパッケージが乗っ取られ、それらの週間ダウンロード数は合計2000万を超える。影響を受けたリポジトリは数万規模という推計もある。インストール前(pre-install)の段階で発火するよう変わり、被害範囲はさらに広がった。失敗すると被害者のホームディレクトリを破壊しにかかる、という攻撃的なおまけまでついていた。
そして話は、過去形では終わらない。2026年に入ってこの系統は「Mini Shai-Hulud」として再燃し、5月に一段と大きな波になった。5月11〜12日のわずか48時間で、170前後のパッケージ・400を超えるバージョンが汚染され、@tanstack や @mistralai、@uipath といった広く使われる名前空間にまで及んだ。しかも今度はnpmだけでなくPyPIにも同時に広がって、pip install の世界まで巻き込んだ。下旬には別の波が20分強のあいだに300超のバージョンをばら撒き、6月に入ってからも新たな攻撃が観測されている。さらに厄介なことに、波のいくつかは認証情報を盗むことすらせず、正規のリリースパイプラインを乗っ取って「本物の署名付き」でばら撒かれた。「発行元を信じる」という防御線まで、一部は破られている。
私がこの話を聞いたのも、つい最近だ。それもそのはずで、これは終わった事件ではなく、いままさに燃え続けている。
本質は「サービス」ではなく「環境」を盗むこと
ここが今回いちばん書きたかったところだ。
この攻撃の本質は、「特定のサービスを狙う」ことではない。「環境に置いてある秘密を、片っ端から掻き集める」ことだ。
私はセキュリティの専門家ではないので以下は受け売りだが、ざっくりこういう動きをするらしい。まず process.env(環境変数の一覧)を丸ごとダンプして、そこに入っているトークンを拾う。ディスク上に転がっているクラウドの認証情報ファイルを直接読む。そして極めつけが、TruffleHog という正規ツールをダウンロードして使うことだ。
TruffleHog は本来、開発者が「うっかり漏らしたAPIキーやパスワードがコードに残っていないか」を探すための、まっとうなシークレットスキャナだ。数百種類のサービスの秘密を検出できる。攻撃者はこれを、逆向きに使う。つまり、君の環境に残っている秘密を、サービスの種類を問わず根こそぎ見つけ出す。さらにAWS・GCP・Azureのメタデータエンドポイントを叩いて、クラウドのワークロード認証情報まで奪う。
だから問いの立て方が、最初から間違っていたのだ。「GitHubやAWSが狙われるのか」ではない。正しくはこうだ。「君の .env やCIに置いてあったものは、サービス名に関係なく全部持っていかれる」。
Stripeのキーも、データベースの接続文字列も、SlackトークンもSSHキーも、対象だ。最近の開発環境ならLLMのAPIキーも .env に刺さっているだろうが、それも同じく、ただの「そこに座っていた秘密」として一緒に掻っ攫われる。置いてあれば、取られる。それだけのことだ。
ここで、冒頭の私の理屈が崩れる。たしかに私はパートナーのGitHubには入れない。でも、向こうのプロジェクトを自分のマシンで npm install した瞬間、危ないのは"私の手元"の方なのだ。アクセス権を持っているかどうかは、関係ない。盗まれるのは、私のラップトップに無造作に置かれた、私自身のトークンなのだから。「外野だから安全」どころか、私の環境こそが、そのまま入口になる。
あるかどうかも確かめず、丸ごと持っていく
ここで発想を切り替える必要がある。
我々は普段、セキュリティを「個別」に考える。このサービスのトークンはこう守る、あのAPIキーはこう保管する、と。一つひとつに対策を割り当てるイメージだ。
でも攻撃者は、そんな見方をしない。「このキーがあるか、あの認証情報があるか」を、いちいち確かめたりしない。環境ごと、丸ごと持っていく。中身の品定めは、盗んだ後でゆっくりやればいい。だから「重要なものだけ厳重に守る」という発想は、丸ごと攫う相手には半分しか効かない。
しかも、いちばん中身が詰まっているのがCI/CDだ。ビルドパイプラインは、たいてい本番のシークレットを、強い権限で、無造作に握っている。そしてnpmのインストール時フックは、インストールしたユーザーの権限でコードを走らせる入口になると理解している。npm install 一発で、その環境の秘密が抜かれる経路が、構造として用意されてしまっているわけだ。
バイブコーディングが、その入口を一気に広げる
ここ最近、いわゆるバイブコーディングが当たり前になってきた。AIに「こういうの作って」と頼むと、必要そうなライブラリを見繕って、勝手に pip install や npm install を走らせ、動くところまで持っていってくれる。速いし、楽しい。私もよく使う。
でも、今回の話と重ねると、これはなかなか剣呑だ。
バイブコーディングの気持ちよさは、「自分で吟味しない」ことに支えられている。どのパッケージを、どのバージョンで、どんなインストール時スクリプト込みで入れているのか——そんなことをいちいち確認していたら、あの軽快さは出ない。意識せず、よくわからないまま、とりあえず入れる。それが体験の本体だ。
そこに、さっきの「npm install 一発で発火する」「PyPIにも広がった」という事実を重ねてみる。人間が一個ずつ吟味して入れていた時代ですら、丸ごと攫われていた。それを今は、人間ですらないものが、意識もせず、何十回も叩く。「とりあえず入れといて」が、そのまま一番の弱点になりうる。
皮肉なオチもある。5月のTanStackの波で攻撃者が忍ばせた悪意あるコミットは、あるAIコーディング支援ツールの公式アカウントを装った偽の署名で、しかもCIをスキップさせる小細工まで施されていた。AIに任せる楽さと、AIを騙る攻撃とが、同じ場所で出会っている。
専門家ではないからこそ、構えだけは持っておく
正直に言うと、私はシステムエンジニアではないし、セキュリティが専門というわけでもない。だからここまでの説明も、調べて理解した範囲のもので、詳しい人からすれば粗いところがあるはずだ。話半分、くらいに思っていてもらっていい。
それでも、今回の件で一つだけ肚落ちした構えがある。「自分はそのサービスを使わないから」「そこに入れる権限を持っていないから」式の、アクセス権やサービス名を根拠にした安心は、まるごと筋違いだった、ということだ。守るべき対象が「サービス」ではなく「環境そのもの」だとすると、棚卸しの単位そのものが変わる。
CISAや各社の防御ガイドが口を揃えて言っているのも、シンプルだが厳しい。「感染した時点で、その開発・CI環境にあったシークレットは、全部盗まれたものと仮定して動け」。被害が報じられたサービスのキーだけをローテーションするのではなく、その環境に座っていたトークンを、全部ローテーションする。サービス名で安心しない、というのが唯一まともな構えらしい。
結局、いちばん弱い境界はどこか
冒頭の「これ三つだけやっといて」に戻る。
あのプロキシは、悪意のあるパッケージが入ってくる入口を一つ塞ぐ、いい一手だった。実際、テスト用の悪意あるパッケージはきれいに弾かれた。
でも、本当に守るべきは「入口」だけではない。守るべきは、君のラップトップとCIに、サービス名のラベルすら貼られずに無造作に積み上がった、秘密の山そのものだ。
攻撃者は、あなたのサービスを狙っていない。狙っているのは、あなたの手元の散らかり具合だ。
いちばん弱い境界は、製品のセキュリティ設計ではなく、開発者の机の上だった。
参考リンク
- CISA「Widespread Supply Chain Compromise Impacting npm Ecosystem」:https://www.cisa.gov/news-events/alerts/2025/09/23/widespread-supply-chain-compromise-impacting-npm-ecosystem
- Datadog Security Labs「The Shai-Hulud 2.0 npm worm」:https://securitylabs.datadoghq.com/articles/shai-hulud-2.0-npm-worm/
- Akamai「Mini Shai-Hulud: The Worm Returns and Goes Public」:https://www.akamai.com/blog/security-research/mini-shai-hulud-worm-returns-goes-public
- Snyk「TanStack npm Packages Hit by Mini Shai-Hulud」:https://snyk.io/blog/tanstack-npm-packages-compromised/
- Palo Alto Networks Unit 42「The npm Threat Landscape」:https://unit42.paloaltonetworks.com/monitoring-npm-supply-chain-attacks/
この文章は原案・ディレクション:九頭龍、作文:AIで書いています。
