Shai-Hulud とは
Shai-Hulud は、2025年9月に観測された npm エコシステム史上初の「自己増殖型」サプライチェーンワームです。攻撃者の手を離れても自動で増殖する点が新しく、CISA も警告を出しました。報告ベースで 数百名の開発者・2万5千を超えるリポジトリに影響したとされ、その年のサプライチェーン攻撃を象徴する事例になりました。
従来の汚染パッケージ攻撃は「攻撃者が1回だけ毒入りバージョンを公開する」ものでしたが、Shai-Hulud は感染した開発者の認証情報を使って次々と別パッケージへ感染を広げるワーム的挙動を持ちます。
自己増殖の仕組み
npm のパッケージは、インストール時に package.json の ライフサイクルスクリプト(preinstall / postinstall など)を自動実行します。Shai-Hulud はここを悪用します。
- 毒入りバージョンに preinstall / postinstall スクリプトを仕込む。
- 開発者や CI ランナーが依存をインストールすると、そのスクリプトが自動実行される。
- 実行環境から npm トークン・GitHub トークン・CI/CD のシークレットを収集する。
- 盗んだトークンで、その開発者が管理する他の正規パッケージを毒入りバージョンとして再公開する。
- 再公開されたパッケージの利用者の環境で 2〜4 が繰り返され、連鎖的に拡散する。
概念的には、毒入りパッケージの package.json はこのような形になります(実害コードは伏せています)。
{
"name": "popular-lib",
"version": "1.2.4",
"scripts": {
"postinstall": "node ./setup.js" // ← install 時に自動実行され、認証情報を収集
}
}盗まれた認証情報の一部は公開 GitHub リポジトリに暴露されるなど、二次被害も伴いました。CI/CD のトークンは権限が強いことが多く、1つの感染が組織全体のサプライチェーンへ波及しうる点が深刻です。
その後の進化
- 第2世代(SHA1-Hulud, 2025年11月頃): 認証情報の収集機能が強化され、ワイパー(破壊)機能も加わったと報告されています。
- CI/CD 適応型の亜種: パイプライン構造を列挙してから増殖方法を選ぶなど、環境に応じた挙動が確認されました。
- 派生(Mini Shai-Hulud 系): npm だけでなく PyPI にも波及するなど、手口が他エコシステムへ拡散しました。
「一度きりの汚染」から「自動で増え続ける感染」へと攻撃モデルが変化したことを示す事例です。
なぜ npm で成立してしまうのか
- ライフサイクルスクリプトが install 時に自動実行される: 任意コードがインストールだけで走る。
- 推移的依存の多さ: 1つのアプリが数百〜数千のパッケージに依存し、すべてを精査するのは困難。
- 信頼の連鎖: メンテナのトークンが盗まれると、そのメンテナを信頼するすべての利用者が危険にさらされる。
- publish の容易さ: トークンさえあれば自動で新バージョンを公開できる。
対策(開発者・チーム側)
- lockfile + クリーンインストール:
package-lock.jsonをコミットし、CI ではnpm ciを使って固定バージョンを再現する。 - ライフサイクルスクリプトの無効化: 信頼できないインストール時は自動実行を止める。
# その場だけ無効化 npm ci --ignore-scripts # 恒久設定(必要な依存だけ個別に許可する運用に) npm config set ignore-scripts true - 新バージョンの即時導入を避ける: 公開直後の取り込みを少し遅らせ、汚染版が撤回される猶予を持つ(バージョンの「冷却期間」)。
- 依存の可視化・監視: Dependabot / Socket などで不審な依存・postinstall・メンテナ変更を検知し、SBOM で「今どのバージョンを使っているか」を即答できる状態にする。
対策(公開者・CI 側)
- npm の 2FA を必須化し、publish にも多要素を要求する。
- 長命トークンを避ける: 粒度の細かい(granular)・短命のトークンを使い、CI では OIDC によるトークンレス公開(Trusted Publishing)+ provenance(来歴)を活用する。
- CI シークレットの最小権限化: ビルドジョブから publish 権限や強い GitHub トークンを切り離し、シークレットスキャンで漏えいを検知する。
- 漏えい時は即ローテーション: npm/GitHub/CI のトークンを失効・再発行し、不審な公開バージョンを確認する。
感染が疑われたら
- npm・GitHub・CI/CD の全トークンを即ローテーションする。
- 自分が管理するパッケージに身に覚えのない公開バージョンがないか確認する。
package-lock.jsonの差分や、依存に追加されたpostinstallをレビューする。- 影響パッケージは安全なバージョンへダウングレード/固定し、環境を作り直す。
まとめ
Shai-Hulud は、「インストールするだけで任意コードが走り、盗んだ認証情報でさらに増殖する」という npm の構造的弱点を突いた自己増殖ワームでした。OWASP でいう A08:2021 - Software and Data Integrity Failures(ソフトウェアとデータの整合性の欠如)に直結するテーマです。
鉄則は (1) lockfile + npm ci、(2) 不要なライフサイクルスクリプトの無効化、(3) 短命・最小権限トークンと 2FA、(4) 依存の可視化と即時ローテーション。サプライチェーンは「信頼の連鎖」であり、その一点を守ることが全体の防御になります。
関連リスクの全体像は OWASP Top 10 入門、同時期のフレームワーク脆弱性は React2Shell(CVE-2025-55182)詳解 も合わせてご覧ください。