セキュリティ対策
npm install 一発で認証情報が抜かれる — サプライチェーンワームからの守り方
2026年8月のChainDropは、4時間弱で444パッケージ・2,212バージョンを汚染し、正規の署名(provenance)付きで配布されました。インストール時のフックでnpm・GitHub・クラウド・CIの認証情報を回収し、盗んだトークンでプライベートリポジトリを公開リポジトリとしてコピーする——この一連の流れと、実際に効く防御(インストール時のスクリプト無効化・依存を寝かせる・トークンの寿命と範囲・感染疑い時の正しい順序)を手順で解説します。
対象:npm / pnpm を使って開発している人、GitHub にコードを置いている人、CIで自動デプロイしている人。本記事は公開情報(研究機関・ベンダーの分析)にもとづく解説で、攻撃の再現手順や検体そのものは扱いません。
何が起きたのか(ChainDrop / 2026年8月)
2026年8月4日
広く使われるキャッシュ系パッケージのメンテナのGitHubアカウントが侵害される。攻撃者は既存のリリース用GitHub Actionsワークフローを起動して、汚染版をnpmへ公開。4時間弱の間に
444パッケージ・2,212バージョンが汚染。合算で週5億回超ダウンロードされる規模のパッケージ群が含まれた。インストールされると
インストール時フックが動き、npm・GitHub・クラウド(AWS/GCP/Azure)・SSH鍵・Kubernetes・CI/CDの認証情報を回収。CIランナーのメモリから短命のOIDCトークンまで拾う挙動が報告されている。そして
盗んだ認証情報で被害者が公開権限を持つパッケージを次々と汚染して再公開(=ワームとして自己増殖)。回収した秘密は攻撃者が作った公開GitHubリポジトリへ持ち出される。
この系統の“本命の被害”=プライベートリポジトリが公開される
Shai-Hulud系のワームは、盗んだGitHubトークンを使って被害者のプライベートリポジトリを公開リポジトリとしてコピーします(末尾に -migration を付けた名前が報告されています)。GitHubが破られたわけではありません。あなたの端末やCIから盗まれたトークンが、あなたの権限で正規の操作として実行するのです。だから「GitHub側の対策待ち」では守れません。
なぜ止められなかったのか
依存を追加 / CIでインストール
↓ preinstall / postinstall が自動実行
端末・CIランナー上で任意コード実行
↓ npm / GitHub / クラウド / SSH / CIの秘密を回収
盗んだトークンで“正規の操作”
privateリポジトリを公開コピー/パッケージを再公開して増殖
効かなかったもの
- 署名・provenance:メンテナ権限で正規に発行されたため、検証を通過した
- 「有名なパッケージだから安全」:汚染されたのはまさに超大手だった
- バージョン固定だけ:新しく入れ直す・依存が更新される場面で結局取り込む
- GitHub側の対策待ち:使われたのは正規のトークンと正規のAPI
効くもの
- インストール時スクリプトの既定無効化:実行そのものが起きない
- 依存を数日寝かせる(cooldown):最も危険な「公開〜取り下げ」の窓を外す
- トークンの短命化と範囲限定:盗まれても使える範囲と時間が小さい
- CIの外向き通信の制限:持ち出しの経路を塞ぐ
今日やる5手順
自分のロックファイルを検索する
汚染が報告されたバージョンが入っていないか、まずロックファイルを直接検索します(例:keyv@6.0.0 / flat-cache@6.1.24 / file-entry-cache@11.1.6)。該当が無ければひとまず安心、ですが手順2以降は「次の波」に備える話なので、続けてください。
インストール時スクリプトを既定で止める
CIの npm ci を npm ci --ignore-scripts にする。pnpm なら .npmrc に ignore-scripts=true を置き、本当にビルドが必要な依存だけを onlyBuiltDependencies のように明示的に許可する。これが今回の攻撃の実行段階そのものを止める、最も効く一手です。
依存を“寝かせて”から採用する
公開直後の版を即座に取り込まない(3〜7日の cooldown)。今回のように公開から取り下げまで数時間〜数日というケースでは、寝かせるだけで丸ごと回避できます。更新の自動PRを使っている場合は、その待ち時間を設定に入れる。
トークンを棚卸しして、寿命と範囲を絞る
GitHubのPersonal Access Tokenはclassicをやめてfine-grainedへ、期限は短く、対象リポジトリは必要なものだけに。npmの publish 用トークンはCIに置きっぱなしにしない。鍵と秘密の扱いは .envとAPIキーの基礎 と SSH鍵の最小権限 にまとめています。盗まれる前提で、盗まれても効かない状態を作るのが目的です。
自分のGitHubアカウントを点検する
身に覚えのない公開リポジトリが増えていないか(-migration が付いたもの、見覚えのない説明文のもの)。あわせて、追加された覚えのないGitHub Actionsワークフロー、.vscode/tasks.json や .claude/ に置かれた実行系の設定ファイル、見覚えのないAPIキーとSSH鍵。依存側の既知脆弱性の機械監視は osv-scannerの導入と使い方 をどうぞ。
感染が疑われるときは「順序」を間違えない
研究者が指摘している重要な点があります——端末に残った常駐(トークン監視の類)を先に取り除いてから、トークンを失効させること。順序を逆にすると、失効を検知した常駐側が次の動きを起こし得ます。おおまかな流れは、①ネットワークから切り離す ②常駐と不審ファイルを除去 ③npm → GitHub → クラウド → SSH → k8s の順で失効・再発行 ④node_modules とキャッシュを破棄して入れ直す ⑤公開リポジトリとパッケージの公開履歴を点検、です。ログが無い場合の答えは「無かった」ではなく「分からない」——その場合は侵害された前提で進めてください。
当サイトの視点:署名は“出所”の保証であって“安全”の保証ではない
サプライチェーン対策として署名や provenance の導入が推奨されてきましたが、今回はその正規の仕組みを通って汚染版が配られました。当然です——署名が保証するのは「誰が出したか」であって、「中身が安全か」ではないからです。侵害されたアカウントから出た正規署名は、正規のまま危険。だから当サイトは、署名を「入れれば安心なもの」ではなく「事故のあとで影響範囲を特定するための道具」として位置づけています。予防の主戦場はあくまで、インストール時に他人のコードを走らせないことと、秘密をその場に置かないことの2点です。
出典(公開記録)
- Unit 42(Palo Alto Networks)— ChainDrop: Inside a Self-Propagating npm Worm(伝播の仕組み・回収される認証情報・指標)
- StepSecurity — ChainDrop npm Worm(検知指標と復旧手順・失効の順序)
- Elastic Security Labs — CHAINDROP worm hits 400+ npm packages
- SecurityWeek — Over 400 NPM Packages Infected in ChainDrop Supply Chain Attack(規模と経緯)
- Wiz — Shai-Hulud npm Supply Chain Attack(プライベートリポジトリの公開コピーという手口)
次に読む
よくある質問
Qなぜ npm install しただけで認証情報が盗まれるのですか?
多くのパッケージは、インストール時に自動実行されるスクリプト(preinstall / postinstall)を持てるためです。つまり依存を1つ追加することは、そのコードを自分のユーザー権限で実行させることと同じです。ChainDropはこの仕組みを使い、npm・GitHub・クラウド・SSH・CI/CDの認証情報を回収していました。
Qプライベートリポジトリが公開されるとはどういうことですか?
この系統のワーム(Shai-Hulud系)は、盗んだGitHubトークンを使って、被害者のプライベートリポジトリを公開リポジトリとしてコピーします。名前の末尾に -migration を付けたものが報告されています。つまり『GitHubが破られた』のではなく、あなたの端末やCIから盗まれたトークンが、あなたの権限でそれを行います。
Q署名やprovenanceがあるパッケージなら安全ではないですか?
今回はそこが突破されました。攻撃者はメンテナの権限で既存のリリース用ワークフローを起動し、正規の署名(provenance)が付いた状態で汚染版を公開しています。署名は『誰が出したか』を保証するもので、『中身が安全か』は保証しません。侵害されたアカウントから出た正規署名は、正規のまま危険です。
Q今日できるいちばん効く対策は?
インストール時スクリプトを既定で無効化すること(`npm ci --ignore-scripts` / pnpm の `ignore-scripts=true`)と、依存を最新即採用にせず数日寝かせること(cooldown)の2つです。前者は攻撃の実行そのものを止め、後者は『公開から取り下げまでの数時間〜数日』という最も危険な窓を避けます。