2026.10.30

【2026年版】npmのサプライチェーン攻撃と対策|Shai-Hulud・ChainDropの手口と、使う側・公開する側がやること

はじめに

npm(Node.js のパッケージの置き場)で、パッケージを乗っ取って悪いコードを混ぜる攻撃が続いています。2025 年 9 月の「Shai-Hulud」から、2026 年も 5 月、6 月と続き、8 月には「ChainDrop」で 400 を超えるパッケージが乗っ取られました。

こうした攻撃は、自分のコードに問題がなくても、使っているライブラリの、さらにその先のライブラリから入り込みます。この記事では、最近の手口と、パッケージを使う側・公開する側の対策をまとめました。

2026 年 8 月の ChainDrop で何が起きたか

Elastic と Microsoft の分析によると、流れは次のとおりです。

  1. よく使われるライブラリ「keyv」のメンテナーのアカウントが乗っ取られ、悪いコードを混ぜた版が公開された
  2. その版をインストールしただけで、package.json の preinstall スクリプトが動き、悪いプログラムを実行する
  3. パソコンや CI の中から、npm・GitHub のトークン、クラウドの鍵、SSH の鍵、AI ツールの API キーなどを集めて送る
  4. 盗んだ npm のトークンが公開の権限を持ち、2 段階認証を回避できるものなら、そのメンテナーが公開できるすべてのパッケージに悪いコードを入れて、次の版を出す(ワームのように広がる)
  5. 盗んだ GitHub のトークンで、リポジトリのエディタや AI ツールの設定ファイル(.vscode/tasks.json・.claude/settings.json)にフックを書き込み、リポジトリを開いたときにも動くようにする

影響を受けたパッケージは 400 を超え、合わせると月に 13 億回以上ダウンロードされる規模でした。また、GitHub Actions からの「trusted publishing」で公開された悪い版もあり、正しい出どころの証明(provenance)が付いていました。出どころの証明は「どこから公開されたか」を示すもので、「公開した環境が安全だったか」までは保証しません。

使う側の対策

1. lockfile を使い、CI では npm ci

package-lock.json をリポジトリに入れて、CI や本番では npm ci を使います。lockfile に書かれた版だけを入れるので、知らないうちに新しい(悪い)版が入るのを防げます。

bash
# lockfile のとおりに入れる(lockfile と package.json が食い違うとエラーで止まる)
npm ci

2. 新しい版をすぐ取り込まない

乗っ取られた版は、多くの場合数時間〜数日で見つかって消されます。公開されてから数日寝かせてから取り込むだけで、多くの被害を避けられます。

  • pnpm:minimumReleaseAge で、公開されてから指定の時間がたつまで入れない
  • Renovate:minimumReleaseAge で、更新の提案を遅らせる
  • Dependabot:cooldown で、新しい版の提案を遅らせる
pnpm-workspace.yaml
# 公開から 3 日(4320 分)たっていない版は入れない
minimumReleaseAge: 4320

3. インストールスクリプトを止める

今回のように、攻撃の多くは preinstall・postinstall などのスクリプトで動きます。ビルドが必要なパッケージ以外は、スクリプトを動かさない設定にしましょう。

bash
# npm:インストール時のスクリプトを動かさない
npm config set ignore-scripts true

# 必要なパッケージだけ、あとで個別にビルドする
npm rebuild <パッケージ名>
  • pnpm は 10 から、依存パッケージのスクリプトを既定で動かしません。必要なものだけ onlyBuiltDependencies で許可します
  • Elastic によると、npm 12 以降も preinstall フックを既定で止めるようになっています。npm を新しくしておきましょう

4. 署名と既知の問題を確かめる

bash
# 既知の脆弱性・悪いパッケージの確認
npm audit

# 入れたパッケージの署名と出どころの証明を確かめる
npm audit signatures

5. 開発のパソコンと CI に鍵を置きすぎない

  • .npmrc や環境変数に、長く使える強いトークンを置きっぱなしにしない
  • CI では、ジョブごとに必要な権限だけを持つ短い期限のトークンを使う(GitHub Actions の OIDC など)
  • クラウドの鍵は、パソコンに保存せず、一時的な認証情報を使う

公開する側(メンテナー)の対策

  • npm のアカウントに2 段階認証を設定する。できればセキュリティキーやパスキーで(コードを入力する方式は、偽サイトでだまし取られる)
  • 2 段階認証を回避できるトークンを作らない。今回のワームは、こうしたトークンで広がった
  • CI から公開するなら、長く使えるトークンの代わりに trusted publishing(OIDC) を使う
  • ただし trusted publishing でも、公開するワークフローそのものが乗っ取られると悪い版が出せる。公開のワークフローは手動の承認(GitHub の Environments の保護)を通す
  • GitHub Actions のアクションはコミットの SHA で固定し、pull_request_target などの危ないトリガーで公開しない

npm のアカウントや GitHub の 2 段階認証の選び方は、【2026年版】2段階認証の種類と強さを比較にまとめています。

乗っ取られた版を入れてしまったら

  1. 影響を受けたパッケージの一覧(Elastic・Microsoft・各セキュリティ会社が公開)と、lockfile を照らし合わせる
  2. 入れてしまったなら、そのパソコンや CI にあったすべての鍵を取り消して作り直す(npm・GitHub のトークン、クラウド、SSH、AI ツールの API キーなど)
  3. GitHub のリポジトリに、覚えのないコミット(設定ファイルの変更など)や、.vscode/tasks.json・.claude/settings.json への書き込みがないか確かめる
  4. 自分がメンテナーなら、自分のパッケージに覚えのない版が出ていないか確かめ、あれば npm に報告して取り下げる

まとめ

  • npm では、乗っ取ったパッケージから鍵を盗み、ほかのパッケージへ広がるワーム型の攻撃が続いている(2026 年 8 月の ChainDrop は 400 超)
  • 使う側は lockfile と npm ci、新しい版を数日寝かせる、インストールスクリプトを止める
  • 公開する側は 強い 2 段階認証、2 段階認証を回避するトークンを作らない、公開のワークフローを守る
  • 出どころの証明(provenance)は、「安全な版」の証明ではない

Node.js 本体のバージョンアップは【2026年版】古いNode.jsからLTS(24・26)へのバージョンアップ手順をどうぞ。

参考

セキュリティ会社の分析(2026 年 10 月 31 日時点)をもとにまとめています。

Shai-Hulud strikes again: CHAINDROP worm hits 400+ npm packages - Elastic Security Labs

ChainDrop supply chain compromise: Anatomy of a self-propagating worm - Microsoft Security Blog

Ongoing npm Supply Chain Attack Affecting Keyv and Related Packages - CSA Singapore

TFT
soflan122本の記事