npmサプライチェーン攻撃「Shai-Hulud」再来、何が脅威か【セルフチェックツール付き】

2026年8月4日、JavaScript開発で広く使われるnpmパッケージ「keyv」をはじめとする一連のライブラリが乗っ取られ、悪意あるコードが仕込まれる事件が発生した。しかも一度の侵害にとどまらず、盗んだ認証情報を使って次々と別のパッケージにも感染を広げる「自己増殖型」の攻撃だった。セキュリティ各社に加え、シンガポール政府のサイバーセキュリティ庁(CSA)も公式アドバイザリを出す事態となっている。何が起きたのか、どれほど深刻なのか、そして自分の関わるプロジェクトが影響を受けているかをどう確認すればよいのかを整理する。

何が脅威なのか

発端は、キャッシュ処理ライブラリ「keyv」のメンテナが持つGitHubアカウントの乗っ取りだった。攻撃者は8月4日、このアカウントを使ってkeyvリポジトリのmainブランチに悪意あるコミットを直接プッシュし、新しいバージョンを公開した。GitHub Actionsによる正規の署名がついた状態でリリースされたため、利用者側からは改ざんに気づきにくい形になっていた。

同時に汚染されたのは、keyv本体だけでなく、同じ開発者・関連エコシステムのパッケージ群である。判明している主なものは以下の通り(バージョンは汚染された版)。

– keyv 6.0.0
– flat-cache 6.1.24
– file-entry-cache 11.1.6
– cacheable-request 13.0.20
– cacheable 2.5.1
– @cacheable/memory 2.2.1
– cache-manager 7.2.10
– @cacheable/node-cache 3.1.2
– @cacheable/utils 2.5.1
– @cacheable/net 2.1.1
– ecto 5.0.1

これらのパッケージには、インストール時に自動実行されるpreinstallスクリプト(setup.mjs)と、728KBにおよぶ難読化されたペイロード(Math_Symbol.js)が仕込まれていた。実行されると、次のような情報を窃取しようとする。

– npmの公開用トークン(~/.npmrcから)
– GitHubトークン(個人アクセストークンやGitHub Actions用のトークンを含む)
– AWSの認証情報(EC2メタデータサービスやSecrets Manager経由)
– Kubernetesのシークレット
– HashiCorp Vaultのトークン
– StripeやSlackのトークン
.envファイルや秘密鍵、Terraformの状態ファイルなど、約200のパターンに一致するファイル

窃取した情報は、「Shai-Hulud: Here We Go Again」という名前のGitHubリポジトリに送信されるほか、npm-cache[.]comというドメインへの通信も予備の流出経路として使われている。

最大の特徴は、このマルウェアが「自己増殖」する点にある。盗んだnpmトークンを使って、攻撃者はそのトークンが公開権限を持つ他のパッケージにも同じ悪意あるコードを仕込み、バージョンを上げて自動的に公開する。盗んだGitHubトークンを使って、他のリポジトリに悪意あるフックをコミットする動きも確認されている。結果として、発覚からおよそ1時間のうちに数百のパッケージへと感染が広がった。

深刻度は高い

深刻度は高いと考えてよい。理由はいくつかある。

第一に、対象となったパッケージは開発現場で極めて広く使われているものばかりだ。flat-cacheはESLintのキャッシュ機構などでも利用され、keyvは様々なアプリケーションのキャッシュ層で使われる。多くのプロジェクトは、これらを直接インストールしていなくても、他のライブラリの依存関係として間接的に取り込んでいる可能性が高い。

第二に、狙っている対象が開発者個人の端末にとどまらない。GitHub ActionsのトークンやAWS・Kubernetes・Vaultの認証情報まで狙う設計は、CI/CDパイプラインを足がかりにして、本番のクラウド環境まで侵害を広げることを意図しているとみられる。

第三に、この攻撃は今回が初めてではない。「Shai-Hulud」と呼ばれる同系統のツールによる攻撃は2026年に入って3回目とされ、今回使われたsetup.mjsというファイル名やフックの手口は、4月に発生したPyPI(Python向けパッケージ)上のPyTorch Lightning侵害とも一致しているという。同じ攻撃者、あるいは同じツールキットを使う攻撃者グループが、エコシステムをまたいで継続的に活動している可能性が高い。

なお、影響範囲の規模については情報源によって数値に幅がある。セキュリティベンダー各社の報告では「440以上のパッケージ・2,200以上のバージョン、合計月間20億インストール規模」とされる一方、シンガポールCSAの公式アドバイザリでは「1,300以上のパッケージバージョン、月間2億ダウンロード相当」とされている。攻撃が発覚後も進行中で、調査時点によって捕捉できた範囲が異なるためとみられる。いずれにせよ、単一パッケージの侵害ではなく、業界を挙げて対応が必要な規模であることは共通している。

自分のプロジェクトが関係するかのセルフチェック方法

Node.js/npmを使っていないプロジェクト(Python、Ruby、Goなど)であれば、今回の攻撃そのものの直接的な対象ではない。まずはその点を確認したい。ただし同じ攻撃者系統が過去にPyPIも侵害しているため、他のエコシステムでも同種の手口への警戒は引き続き必要である。

Node.js/npmを使っている場合は、以下を確認するとよい。

1. ロックファイルを検索するpackage-lock.jsonyarn.lockpnpm-lock.yamlの中に、上記に挙げた汚染バージョンのパッケージ名が含まれていないか検索する。見つかった場合は、該当パッケージを安全な既知のバージョンに固定し直すか、修正版が出るまで利用を停止する。

2. セキュリティスキャンツールを使う:この攻撃は発覚後も対象パッケージが増え続けているため、手作業でのチェックだけでは限界がある。Socket、Snyk、GitHubのDependabotアラートといったツールや、npmのnpm audit signaturesコマンドで、既知の侵害パッケージ一覧との照合を行うことが望ましい。

3. CI/CDのログを確認する:8月4日以降に自動ビルドやデプロイパイプラインでnpm installnpm ciを実行していた場合は、たとえ汚染パッケージが直接見つからなくても、そのパイプラインで使われていた認証情報(npmトークン、GitHubトークン、AWS認証情報など)は漏洩した前提でローテーション(再発行)することが推奨される。

4. 痕跡(IOC)を確認するnpm-cache[.]cometh-mainnet.nodereal[.]ioといったドメインへの通信履歴や、自組織のGitHub上に「Shai-Hulud: Here We Go Again」という説明を含む見覚えのないリポジトリが作成されていないかを確認する。これらが見つかった場合は、侵害の痕跡として扱い、関係するシステムの再構築を検討する必要がある。

npmに代表されるオープンソースの依存関係管理は、便利さと引き換えに、こうしたサプライチェーン攻撃のリスクを常に抱えている。今回のような自己増殖型の攻撃は今後も形を変えて繰り返される可能性が高く、依存関係を定期的に棚卸しし、ロックファイルで固定し、CI/CDの認証情報を最小権限かつ定期的にローテーションする、といった基本的な備えの重要性が改めて浮き彫りになった。

ツールで確認するなら

上記の確認作業をコマンドライン一つで自動化できる、オープンソースのスキャナー「shai-hulud-scanner」を作成したのでよかったら使ってほしい。MITライセンスで、Python 3.9以上の標準ライブラリのみで動作するため、追加のインストール作業は不要。

このツールは主に次の6項目を検査する。

1. 既知の汚染パッケージ・バージョンとの照合(IOCリストとの突合)
2. setup.mjsMath_Symbol.jsなど、今回の攻撃で使われた悪性ファイル名の検出
3. npm-cache.comなど、攻撃者への通信先ドメインの痕跡
4. curl | shのような、不審なインストールフックの検出
5. .vscode/tasks.json.claude/settings.jsonなど、開発ツール設定の改ざん確認
6. (オプション)GitHub上に、自己増殖の痕跡となる不審なリポジトリが作成されていないかの確認

使い方は次の通り。

# リポジトリから取得
git clone https://github.com/tzwada/shai-hulud-scanner.git

# 取得ディレクトリに移動
cd shai-hulud-scanner

取得したディレクトリにて、以下のいずれかを実行。

# ホームディレクトリ全体をまとめてスキャンする(推奨)
python3 scan.py --home
# 特定のプロジェクト(ex. ~/dev/project-a, ~/dev/project-b)だけをスキャンする
python3 scan.py ~/dev/project-a ~/dev/project-b
# GitHub上の自己増殖の痕跡も確認する
python3 scan.py --home --check-github
# CI連携用にJSON形式で結果を出力する
python3 scan.py ~/dev/project-a --json

なお、スキャン結果が「no indicators found(痕跡なし)」と表示された場合でも、それは「既知のパターンには一致しなかった」ことを意味するのであって、感染していないことを証明するものではない。未知の亜種や、このツールの検査範囲外の感染経路までは検出できない点には留意しておきたい。

参考:Keyv and friends compromised in npm supply chain attack(Aikido)シンガポールCSA公式アドバイザリshai-hulud-scanner(GitHub)