三日に一件
StepSecurity は土曜日、悪意あるパッケージによる攻撃の一年分を数え上げた。全 56 件。最初の半年で 6 件、2 月からの六か月半で 50 件、3 月以降はおよそ三日に一件のペースだ。そして報告書は、それらが機能し続ける理由を名指しする。開発マシンと CI ランナー上のシークレット、ピン留めされていない latest、開かれた外向き通信。どれ一つとしてパッケージの性質ではない。三つとも、インストールが走るマシンの性質であり、いま最も多くのパッケージをインストールするマシンには、コーディングエージェントが載っている。
悪意あるパッケージはインストール時に発火する。到達すべき脆弱なコードパスも、書くべき エクスプロイトも、パッチを当てる猶予もない。三日に一件という頻度では、それがどのパッケージ で届いたのかは、もはや問うに値する問いではなくなっている。
土曜日、StepSecurity は オープンソースサプライチェーン攻撃の十二か月分の集計 を公開した。五十六件。「2025 年 8 月から 2026 年 1 月までの六か月間で、私たちは 6 件の インシデントを把握した。2026 年 2 月からの六か月半では 50 件だった」。3 月以降、ペースは 月に約九件、すなわち「およそ三日に一件」で推移している。
StepSecurity はフィルタリング付きレジストリを売っている。何を売っている側の文書なのかを 承知した上で読んでほしい。それでも集計そのものは持ちこたえる。悪意あるパッケージについて 公開されたなかで最も丁寧な数え上げであり、その背後にある定義は意図的に狭い。
この数字が数えているもの
報告書は脆弱性を除外している。CVE も、あとから unsafe だと判明したブロックも数えない。
誰かが意図的に汚染したパッケージだけを数えている。
だからこそこの数字は使える。脆弱性には第二の出来事が要る。誰かがあなたのインスタンスを 見つけ、該当のコードパスに到達し、そこから何かを得なければならない。脆弱なバージョンを 一年動かし続けても何も起きないことがある。悪意あるパッケージはそれを全部飛ばす。報告書の 言い方を借りれば、それは「開発マシンや CI ランナーがインストールしたその瞬間に走る」。 インストールが、そのまま攻撃の成立である。公開と修正の間の猶予は決して訪れない。誰も何も 公表しておらず、誰もパッチを出していないからだ。手元に残るのはバージョン番号ひとつと、 誰がそれを取得したのかを突き止めるための慌ただしい作業だけだ。
2026 年 3 月は 13 件。4 月 9 件、5 月 9 件、6 月 10 件、7 月 6 件。3 月のわずか五日間で、
Team PCP として追跡されている作戦は、Trivy の GitHub Action の 77 個のタグのうち 76 個と
いくつかのビルド時コンポーネントを汚染し、
2,186 の組織から 78,330 件のシークレットを奪った。
うち 92 社は上場企業である。週間ダウンロード数一億超の axios は、クロスプラットフォーム
のリモートアクセス型トロイの木馬を積んだ悪意あるバージョンを二つ出した。この一年でワームは
六つ現れている。Shai-Hulud が二度、CanisterWorm、Mini Shai-Hulud、Miasma、そして今月の
ChainDrop。npm、PyPI、RubyGems、Composer、crates.io、GitHub Actions。「主要なパッケージ
エコシステムと CI/CD プラットフォームは、ことごとく被害を受けている」。
このリストのうち二件がここでは重要だ。報告書は、「AI で動くボット」である hackerbot-claw
が Microsoft、Datadog、CNCF の GitHub Actions を狙ったこと、そして「Miasma ワームは AI
コーディングエージェントを名指しで標的にしていた」ことを記している。
三つの条件、そのどれもパッケージではない
そこから報告書は有益な仕事をする。なぜ攻撃が機能し続けるのかを問う見出しの下で、三つの 答えを挙げるのだ。「CI/CD パイプラインと開発マシン上のシークレット、ピン留めされていない latest、開かれた外向き通信」。
このリストのどれもパッケージを説明していない。難読化も、タイポスクワットの綴りの近さも、 インストールフックの小細工も出てこない。三つとも、インストールを実行するマシンを説明して いる。何を抱えているか、どうバージョンを選ぶか、どこへ接続してよいか。どれか一つを変える だけで、五十六件の大半は採算が合わなくなる。
ピン留めなしの latest
解決の連鎖のどこかが「最新を」と言っている。浮動範囲、推移的依存、作り直された ロックファイル、あなたの代わりにライブラリを足すエージェント。攻撃者に必要なのは、 リゾルバが数分前に公開されたバージョンを選ぶことだけだ。
マシン上のシークレット
~/.ssh、~/.aws、~/.kube、~/.npmrc、環境変数の GH_TOKEN、
~/.docker/config.json のレジストリログイン。どれ一つビルドのものではないのに、
ビルドがいま起動したものはそのすべてを読める。
開かれた外向き通信
盗んだデータは外へ出なければならず、第二段階のバイナリは入ってこなければならない。 どちらも、どこへでも外向き接続を許すマシンからの、ごく普通の外向き接続である。
いま最も多くのパッケージをインストールしているのは誰のマシンか
誰もが頼りにしてきた防御は、注意力だった。差分を読む。キャッシュ用ライブラリが、日付 フォーマッタの名前を一文字だけ変えた依存を拾っていることに気づく。
それを二つのものが追い越した。まず頻度だ。三日おきに推移的依存をレビューする人はいない。 次に、誰がインストールしているかである。コーディングエージェントは、あなたが何かを作れと 頼んだからライブラリを足し、依存ツリーを解決し、インストールを走らせ、テストが通ったと 報告する。あなたが読むのはそれが生んだ差分で、そここそ時間を割く価値のある部分だ。tarball は差分には決して現れない。StepSecurity のリストには、まさにこの働き方を探しにいったワームが すでに載っている。
エージェントはそのままでいい。制御を、その速さが問題にならない場所へ移すのだ。
三つの条件、三つの制御、いずれも Mac 側に
Bromure Agentic Coding はエージェントを、Apple の Virtualization フレームワーク上の 使い捨て Ubuntu VM で動かす。中にマウントされるのはあなたが選んだフォルダだけで、外への 唯一の経路はホスト側のプロキシである。この配置により、StepSecurity の三つの条件はそれぞれ、 ビルドが手を触れられない制御の前に置かれる。
ピン留めなしの latest は時計になる。 パッケージ取得はすべてまずホストのプロキシを通る。
npm、PyPI、Cargo、RubyGems、Maven、NuGet、Go モジュール、Packagist。経過日数ゲートは
既定で二日に設定されて有効になっている。浮動参照は基準時刻より古い最新版に解決されるので、
latest は動き続けたまま「あなたがこれを読んでいる間に公開された版」を意味しなくなる。
新しすぎるものへのピン留め参照は、Bromure のエラーを載せた 451 で返る。その上で、任意の
深刻度しきい値で OSV 照会を有効にし、socket.dev の評判データベースや Delpi のフィルタリング
レジストリ経由でパッケージを取得し、npm の tarball から preinstall、install、
postinstall、prepare をその場で取り除くこともできる。Bromure は tarball を書き換え、
レジストリのメタデータのハッシュも更新するので、npm 自身の検証は変わらず通る。VM 内の
.npmrc と pip.conf は、これらの設定をどれも厳しくはできるが、緩めることはできない。
マシン上のシークレットはダミーである。 本物の認証情報が VM に入ることはない。プロキシが
通信路の上でプレースホルダを本物のトークンに差し替える。ゲスト内の kubeconfig は使い捨ての
クライアント証明書を持つ合成物だ。AWS には credential_process ヘルパーが用意され、SDK には
四十文字の偽物を渡す一方、ホストが本物の鍵材で SigV4 を署名し直す。だからプロキシを迂回した
ものは Amazon から InvalidSignatureException を受け取るだけになる。~/.aws/credentials を
読むインストール時コードは、ファイルを見つけ、読み取り、おとりを持ち出す。各認証情報には
さらに、ホストのプロキシで強制される書き込みポリシー(オフ、破壊的操作をブロック、読み取り
専用)と、使用時に承認を要求 が付く。後者は一回の使用を同意ダイアログに変え、五分、一時間、
またはセッション終了までの許可を与える。
開かれた外向き通信は、あなたが書いた規則に従う。 ガードレールの下にある「外向き接続」の
表は、プロファイルごとのファイアウォールだ。規則ごとに一行で、それぞれに動作、プロトコル
(tcp、udp、web、any)、ホストまたは CIDR、ポート、そして web では HTTP メソッドの
一覧を持つ。規則は上から順に照合され、最初に一致したものが勝つ。一致しない通信 は、許可か
拒否に設定するスイッチだ。同じ規則群を二つの層が強制する。仮想スイッチは宛先 IP と、ゲスト
自身の DNS 応答を覗いて学習したホスト名で。プロキシは TLS の SNI で。透過的な傍受は既定で
有効なので、ビルドスクリプトが HTTPS_PROXY を解除しても、外へ出る接続は何も変わらない。
先週の crates.io の攻撃は、この規則が何を捕まえるかを示している。StepSecurity の分析に よれば、ドロッパーのビルドスクリプトは base64 の URL を復号し、素の IP のポート 9089 からプラットフォーム別のバイナリを取得 していた。証明書検証は無効化され、Cargo が待たないように子プロセスを切り離していた。一致 しない通信を拒否していれば、その取得は完了しない。そしてビルドスクリプトの終了コードは、 もはや興味深い問いではなくなる。
八十六分
時計が判断力に勝つ理由を、同じ攻撃に戻って見てみよう。汚染された arrayref、internment、
append-only-vec の各リリースは、crates.io が取り下げるまで 86 分、90 分、107 分だけ
生きていた。リゾルバをそちらへ誘導するため、攻撃者は健全な版 0.3.9 から 0.3.5 までを
十六秒のうちに一気に yank し、誰も取り下げていないリリースを一つだけ残した。この件に関する
StepSecurity の最も鋭い一文はこうだ。「攻撃者はレジストリ自身の安全機能を配送経路に変えた」。
そして arrayref 自体には悪意あるコードは含まれていなかった。ペイロードは、ビルド時に
使われる proc-macro2 のタイポスクワットに乗って入ってきたのである。
二日の経過日数ゲートは、そのどれ一つ見分ける必要がない。八十六分前の版は基準より新しく、 インストールできる年齢に達する頃には、crates.io がすでに削除している。攻撃者は、ゲートが そもそも無視する窓よりも短い窓を組み立てたことになる。
五十七件目
報告書は、覚えておく価値のある一文で締めくくられる。「12 か月で 56 件の攻撃。57 件目の攻撃は すでに作られつつある」。
それがどのパッケージで届くのかをあなたは知らないし、読みもしない。あなたのエージェントも 読まない。三日に一件が五か月続くというのは、誰かがレビューできる周期をはるかに超えており、 それを不注意と呼んでも誰の役にも立たない。しかしそれが何の上に着地するかは、あなたが決め られる。それが必要とする版をあなたのリゾルバが受け入れるかどうか、それが探しに来る シークレットが本物かどうか、それが到達したいアドレスへあなたのマシンが経路を持つかどうか。 三つの設定、そのすべてが境界のあなた側にある。
出典: StepSecurity, "The State of Open Source Supply Chain Attacks" (2026 年 8 月 22 日) · StepSecurity, "Rust Supply-Chain Attack: arrayref, internment, and append-only-vec Poisoned by the proc-macro1 Build-Time Dropper" (2026 年 8 月 20 日) · StepSecurity, "Team PCP Stole 78,330 Secrets From 2,186 Organizations" (2026 年 8 月 13 日)