Chainguardがnpmグレーウェアを検知し5万2,000件超を遮断
目次
TL;DR
対象 Chainguard Libraries for JavaScriptのnpm upstream fallbackで扱うnpmパッケージ。
2026年6月9日の公式発表では1日10万件超をスキャンし、5万2,000件超をマルウェアまたはグレーウェアとして遮断
差分 公開直後の悪意あるバージョンを遅らせる公開経過時間ゲートや、インストール時スクリプトを止めるnpm v12とは別の層。READMEどおりに動くが、認証情報収集や永続リモートアクセスを含むパッケージの遮断
確認 npmレジストリから直接取っている依存、社内npmプロキシに残った配布アーカイブ、AIエージェントが自動追加したCLI系依存、Chrome・クラウド・トークン・ウォレット周辺を読む小型パッケージ。Chainguard側のnpm upstream fallbackは既定オフなので、自前のnpm fallbackを別に置くとこの保護を迂回する
Chainguardが、従来のマルウェアスキャンを通過するnpmパッケージを「グレーウェア」として遮断し始めた。
公式発表では、1日10万件超のパッケージをスキャンし、すでに5万2,000件超をマルウェアまたはグレーウェアとしてブロックしたと書いている。
ここでいうグレーウェアは、難読化されたペイロード(悪意あるコード本体)を隠すパッケージとは違う。
READMEや公開コードに機能を書いていて、その通りに動く。
ただし中身はChromeのパスワードやCookieを読む、APIキーを集める、第三者サーバーから命令を待つ、といった企業開発環境では許可しにくい機能を含む。
数字と実例は、Chainguard公式のThe expanding threat landscapeにまとまっている。
「あらゆるセキュリティチェックを通過した」というより、難読化や既知IoC(侵害痕跡)を探す従来型のマルウェア検知では拾いにくい公開パッケージを、Chainguard側のポリシーで遮断する話として読むほうが正確だ。
隠れていないから既存検知で拾いにくい
これまでnpmサプライチェーンの記事で多く見てきたのは、正規パッケージの侵害だった。
Mini Shai-Huludの@antv波では、侵害された公開権限から悪意あるバージョンが出て、preinstall とGit依存でペイロードが走った。
Microsoft系Miasmaの記事では、npmではなくAIツールやVS Codeの設定読み込みが入口になった。
Chainguardのグレーウェアは、そのどちらとも違う。
パッケージ名を似せるタイポスクワッティングでも、既存メンテナの乗っ取りでもない。
「Chromeのデータを扱うCLI」「AIアシスタント用CLI」「自律ペンテストフレームワーク」のように、認証情報や遠隔操作へ踏み込む小型パッケージがnpmに置かれている。
公式発表が挙げている例は、chrome-tools、@robinpath/cloud-cli、leobot-cli、noesis-miner、drogonclaw などだ。
chrome-tools はChromeのパスワード、Cookie、クレジットカード、自動入力データを読む機能を公開している。
@robinpath/cloud-cli は第三者サーバーへつながる永続バックドアとして動く、とChainguardは説明している。
2026年6月18日JSTにnpmメタデータを確認すると、5例はいずれも名前解決できる状態だった。
Chainguardが発表内で名指ししたバージョン範囲と、2026-06-18時点の latest は分けて見る。
| パッケージ | Chainguard発表時点の対象範囲 | 2026-06-18確認時のlatest |
|---|---|---|
leobot-cli | 1.0.0〜1.1.6 | 1.1.6 |
@robinpath/cloud-cli | 0.1.1〜0.3.1 | 0.3.1 |
noesis-miner | 0.1.3〜0.1.23 | 0.1.23 |
drogonclaw | 0.3.5〜1.0.2 | 1.0.2 |
chrome-tools | 1.0.3〜1.1.2 | 1.1.5 |
chrome-tools は発表後の2026年6月17日UTCにも1.1.4と1.1.5が公開されていた。
記事やスキャナの例示バージョンだけで終わらせず、実際のロックファイルとnpmメタデータで現在の解決結果を確認する。
この種類のパッケージは、「隠していない」ことが検知を難しくする。
静的スキャンが難読化、既知IoC(侵害痕跡)、怪しいC2(指令サーバー)文字列、インストール時の外部通信を探しても、READMEとコードが一致しているなら「仕様どおりのツール」として通りやすい。
7日待っても残るパッケージがある
前に書いたpnpm 11、Yarn 4.10、npm v11.10のrelease-age gateは、公開直後の悪意あるバージョンを踏む確率を下げる話だった。
Mini Shai-Huludやaxios汚染のように、数時間から十数時間で削除される波を解決対象から外せる。
ただしChainguardの例では、5つの公開例がnpmの一般的な7日クールダウンを通過してもまだダウンロード可能だった。
公開からN日待つルールは、短時間で消える汚染版を解決対象から外す。
長く置かれたグレーウェアでは、公開日を見ても判定材料が増えない。
ここはnpm v12のallowScripts記事とも止める対象が別だ。
npm v12は、未許可の preinstall、install、postinstall、暗黙の node-gyp rebuild を止める。
しかしグレーウェア側がインストール時に何も走らず、利用時にCLIとしてChromeやクラウド認証情報へ触るなら、allowScriptsの外側で動く。
防御層を並べると、役割はこう分かれる。
| 層 | 止めるもの | 残るもの |
|---|---|---|
| 公開経過時間ゲート | 公開直後に削除される汚染版 | 長く残るグレーウェア、既存ロックファイル |
| npm v12 allowScripts | インストール時の自動実行 | 読み込み時・CLI実行時・AIエージェント経由の利用 |
| ワークスペース設定確認 | .claude/、.vscode/ などの自動実行 | npmから取得する通常依存 |
| Chainguardのスキャナ | マルウェアとグレーウェアをリポジトリ提供前に遮断 | 組織が直接npmから取得する依存、許可済み例外 |
Chainguard Librariesを使っている場合は、npm互換のリポジトリエンドポイントを経由して、スキャン済みのパッケージを受け取る形になる。
npm upstream fallback(Chainguardのリポジトリに無いパッケージを本家npmから取り寄せる機能)でnpm本体から取り寄せるパッケージも、Chainguard Repositoryに追加される前にスキャンされる、と公式発表は説明している。
ただし、ChainguardのJavaScript upstream fallbackは既定オフで、設定した場合もnpmから直接プロキシされるパッケージはChainguardが再ビルドした成果物ではない。
Chainguard docsは、cooldownとmalware scanningを補助的な防御と位置付け、上流の配布物を評価する責任は利用側に残ると書いている。
社内Artifact RegistryやArtifactoryでChainguardとは別にnpmjs.orgへのfallbackを置くと、このスキャン経路を通らない。
4つの材料を合わせて判定する
Chainguardはスキャナの判定材料として、メンテナの挙動、パッケージ内容、公開時のシグナル、動的実行の4本を挙げている。
メンテナの挙動では、公開アカウントの移転、リリース履歴、メタデータ、通常と違う公開時刻、公開プロセスやツールチェーンの変化を見る。
これはメンテナアカウント侵害や所有者交代の兆候に近い。
パッケージ内容では、公開された配布アーカイブ自体を見る。
難読化コード、埋め込みC2ドメイン、変更されたバイナリ、新規依存、コードやバイナリサイズの急な変化が対象になる。
公開時のシグナルでは、公開パッケージとソースコードの対応を見る。
タグがないリリース、未知の鍵で署名されたリリース、強制pushされたタグ、イベントログにないコミットハッシュなどが出てくる。
動的実行では、インストール時スクリプトをネットワーク遮断したサンドボックスで実行し、外部サーバーへの通信、システムファイル読み取り、隠れたペイロード起動を調べる。
ここはnpm v12のallowScriptsと重なるが、Chainguard側はリポジトリへ出す前の判定材料として使う。
グレーウェアの扱いでは、パッケージ内容と公開時のシグナルに加えて、機能そのものを業務アプリに入れるかを判定する。
コードが公開され、READMEとも一致していて、npm上で長く残っている場合でも、「この機能を業務アプリの依存として許可するか」という判定が残る。
flowchart TD
A["npmパッケージ"] --> B["公開履歴と<br/>メンテナの挙動"]
A --> C["配布アーカイブ内容と<br/>ソース差分"]
A --> D["サンドボックスでの<br/>インストール時挙動"]
B --> E["マルウェア / 要レビュー / 安全"]
C --> E
D --> E
E --> F["Chainguard Librariesで<br/>提供または遮断"]
C --> G["グレーウェア判定<br/>仕様どおりだが認証情報へ触る機能"]
G --> E
AIエージェントが足した依存はレビューを抜けやすい
Chainguardの発表がAIコーディングに触れている理由は、依存追加の経路が変わったところにある。
人間がREADMEを読み、権限や副作用を確認してから npm install する運用は、もともと大規模依存ツリーでは崩れていた。
そこへAIエージェントが入ると、「要件に合うパッケージを探して追加する」操作が自然言語の作業の中に混ざる。
小さな社内自動化をAIコーディングで作る。
エージェントがクラウドCLI、ブラウザ操作、トークン管理、スクレイピング系のnpmパッケージを提案する。
そのパッケージがREADMEどおりに認証情報を読む。
ここではスキャンの通過と危険性が両立する。
このブログで追ってきたShai-HuludやMiasmaは、攻撃者が発火点を探していた。
インストール時スクリプト、Git依存、.pth、AIツールの SessionStart、VS Codeの folderOpen タスク。
Chainguardのグレーウェア話は、発火点以前に「依存として選んだ時点で認証情報や遠隔操作へ踏み込む」ケースになる。
ロックファイルから社内ミラーまで追う
Chainguard Librariesを使っていない組織では、今回の発表をそのまま「Chainguardなら安心」で閉じず、社内npm経路の確認へ落とす。
確認対象はロックファイルから始める。
社内npmプロキシ、Artifact Registry、Nexus、Artifactory、CIのパッケージキャッシュ、Dockerレイヤーに残った配布アーカイブまで見る。
公開npm上であとから消えても、内部キャッシュに残っていればCIはそこから取る。
依存名で見るときは、公式が例示したパッケージ名だけを探すより、機能の種類で絞る。
Chrome、ブラウザ認証情報、Cookie、トークン、ウォレット、クラウド、CLI、エージェント、遠隔操作、ペンテスト、マイニングあたりの語を持つ小型パッケージは、依存追加の理由と実行権限を確認する。
AIエージェントが作ったPRなら、パッケージ追加の説明が短いことも多い。
package.json の差分では、次のような追加を別枠で見る。
{
"dependencies": {
"some-browser-cli": "^1.0.0",
"some-cloud-agent": "^0.3.0"
}
}
名前よりも、そのパッケージが触る情報を見る。
開発端末やCIランナー上でどの認証情報へ触れるかだ。
GitHubトークン、npmトークン、クラウドCLIの認証ファイル、ブラウザ保存情報、SSH鍵、Kubernetes kubeconfig、Vaultトークンへ触るなら、アプリ依存としての理由をPR上で残す。