ssecutils
Security / Browser-native guide

Shai-Hulud詳解 - npm史上初の自己増殖ワームとサプライチェーン対策

10Zero tracking reading surface

Shai-Hulud とは

Shai-Hulud は、2025年9月に観測された npm エコシステム史上初の「自己増殖型」サプライチェーンワームです。攻撃者の手を離れても自動で増殖する点が新しく、CISA も警告を出しました。報告ベースで 数百名の開発者・2万5千を超えるリポジトリに影響したとされ、その年のサプライチェーン攻撃を象徴する事例になりました。

従来の汚染パッケージ攻撃は「攻撃者が1回だけ毒入りバージョンを公開する」ものでしたが、Shai-Hulud は感染した開発者の認証情報を使って次々と別パッケージへ感染を広げるワーム的挙動を持ちます。

自己増殖の仕組み

npm のパッケージは、インストール時に package.jsonライフサイクルスクリプト(preinstall / postinstall など)を自動実行します。Shai-Hulud はここを悪用します。

  1. 毒入りバージョンに preinstall / postinstall スクリプトを仕込む。
  2. 開発者や CI ランナーが依存をインストールすると、そのスクリプトが自動実行される。
  3. 実行環境から npm トークン・GitHub トークン・CI/CD のシークレットを収集する。
  4. 盗んだトークンで、その開発者が管理する他の正規パッケージを毒入りバージョンとして再公開する。
  5. 再公開されたパッケージの利用者の環境で 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 の容易さ: トークンさえあれば自動で新バージョンを公開できる。

対策(開発者・チーム側)

  1. lockfile + クリーンインストール: package-lock.json をコミットし、CI では npm ci を使って固定バージョンを再現する。
  2. ライフサイクルスクリプトの無効化: 信頼できないインストール時は自動実行を止める。
    # その場だけ無効化
    npm ci --ignore-scripts
    
    # 恒久設定(必要な依存だけ個別に許可する運用に)
    npm config set ignore-scripts true
  3. 新バージョンの即時導入を避ける: 公開直後の取り込みを少し遅らせ、汚染版が撤回される猶予を持つ(バージョンの「冷却期間」)。
  4. 依存の可視化・監視: Dependabot / Socket などで不審な依存・postinstall・メンテナ変更を検知し、SBOM で「今どのバージョンを使っているか」を即答できる状態にする。

対策(公開者・CI 側)

  1. npm の 2FA を必須化し、publish にも多要素を要求する。
  2. 長命トークンを避ける: 粒度の細かい(granular)・短命のトークンを使い、CI では OIDC によるトークンレス公開(Trusted Publishing)+ provenance(来歴)を活用する。
  3. CI シークレットの最小権限化: ビルドジョブから publish 権限や強い GitHub トークンを切り離し、シークレットスキャンで漏えいを検知する。
  4. 漏えい時は即ローテーション: 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)詳解 も合わせてご覧ください。

Related reading

関連記事

Security11
MCPのセキュリティ - Tool Poisoning・Rug Pull・サプライチェーンの実例と対策AIエージェントの標準プロトコルMCPの攻撃面を体系整理。ツール説明文に指示を仕込むTool Poisoning、承認後に定義を差し替えるRug Pull(CVE-2025-54136)、偽MCPサーバのサプライチェーン、過剰権限トークン、MCP Inspector RCEなど2025〜26年の実例と、最小権限・人間による承認・サーバ検証の防御を日本語で解説します。
Security11
ClickFix攻撃とは - 偽CAPTCHAで「自分で感染させる」手口とFileFix亜種・対策偽CAPTCHA・偽エラーでWin+RやPowerShellにコマンドを貼り付け実行させ、Lumma/StealCなどを自分で感染させるClickFix攻撃を解説。Run無効化を回避するFileFix亜種、700サイト改ざん(CVE-2026-26980)などの実例、利用者教育・GPO・ASR・ログ監視による多層防御を日本語で整理します。
Security11
AIブラウザの危険性 - Comet/Atlasを乗っ取る間接プロンプトインジェクションPerplexity CometやChatGPT AtlasなどのAIブラウザを狙う間接プロンプトインジェクションを解説。Webページに隠した指示でAIを操り、ログイン中のGmailや1Passwordを横断悪用してOTPを盗むBraveのPoC、Zenityのゼロクリック乗っ取り、Same-Origin Policyが無力化される理由、入力分離・操作ゲート・モード分離による対策を日本語で整理します。
Security11
インフォスティーラーとセッションCookie窃取 - MFAを回避するpass-the-cookie情報窃取マルウェアがMFAを突破ではなく迂回する仕組みを解説。Lumma/StealCが数十秒で全ブラウザのCookieと保存パスワードを盗み、攻撃者がpass-the-cookieで本人になりすます流れ、3.9億件規模の被害、ClickFix等の感染経路、ChromeのDBSC・FIDO2・短命セッション・条件付きアクセス・異常検知による多層防御を日本語で整理します。