そのドキュメントは、誰のものでもないパッケージを名指ししていた
研究者たちが 6,214 の企業ドメインを llms.txt について走査しました。企業がいま AI エージェント向けに公開している、機械可読のあのファイルです。そこで見つかったのは、名指しされているのに誰も登録したことのないパッケージとドメインが 237 件。研究者はそのいくつかを自分で取得しました。Fortune 500 のネットワーク内にいた最初のコーディングエージェントは、四分とかからずそれをインストールしました。攻撃者はメンテナにもレジストリにもリポジトリにも触れていません。Bromure Agentic Coding の年齢ゲートは二日で最初から有効になっており、攻撃者が取得した名前は構造上つねに真新しい公開なのです。
あるベンダーが、自ら公開したことのないパッケージのインストールコマンドを、 自社のドキュメントに書き込みました。その名前は空いたまま、誰でも取れる状態で そこにありました。コーディングエージェントはその文書を読み、信じ、 インストールを実行しました。
ここ二年ほどのあいだに、あなたの開発ツールは新しいファイルを配るようになりました。
それは robots.txt の隣にあり、名前は llms.txt といい、人ではなく機械に向けて
書かれた製品のプレーンテキスト要約が入っています。その API が何をするのか。どの
エンドポイントが重要なのか。始めるにはどのパッケージを入れればよいのか。
コーディングエージェントはそれを取得し、ベンダー自身のドメインから来たという
理由だけで、確定した事実として扱います。
PANDEX という名前で活動する Alon Hertz という研究者が、それらのファイルが
エージェントに何をさせているのかを調べに行きました。手順は三つ、エクスプロイトは
ゼロです。企業ディレクトリから llms.txt と llms-full.txt を取得し、実際の
エージェントをサンドボックス内でそれに当てて何に手を伸ばすかを観察し、そこから
出てきたパッケージ名とホスト名を npm、PyPI、そしてドメインレジストリに照らして
確認する。彼はその道具立てを whatwouldai.do で説明して
います。そこに掲げられた惹句が、そのまま結論になりました。エージェントは何にでも
反応して動く。
走査の対象は、Fortune 500 企業、大手テック、フィンテック、防衛関連企業から集めた 6,214 の稼働ドメインと、8,000 を超えるこれらのファイルでした。そのうち 120 件では、 ファイルがエージェントにインストールさせようとしていたものが存在しませんでした。 コーパス全体では、名指しされたパッケージ名とホスト名 237 件が空いていました。npm、 PyPI、RubyGems、NuGet、crates.io、Packagist で取得可能、あるいは Vercel、Render、 Fly、Netlify のサブドメインとして空いていたのです。サインアップの手間だけで、誰でも 取れました。
そこで研究者たちはそのうちいくつかを取り、インストール時に自分のところへ通信する ビーコンを仕込んだ無害なパッケージをその名前で公開し、待ちました。
最初のコールバックは四分とかからず届きました。二つ目は一時間以内。それに続く 期間で、彼らは数十の組織からのインストールを記録しました。そのいくつかは Fortune 500 の環境で、動かしていたのは Anthropic の Claude、OpenAI の Codex、 Nous Research の Hermes 上のエージェントでした。Bruce Schneier は 9 月 4 日にこの研究を取り上げ、 それにふさわしい読み方をしました。データと実行可能コードの境界が崩れつつある、と。 その記事で引用された研究者はもっと少ない言葉で言います。「信頼モデルは壊れている」。 エージェントは「ベンダーの文書を地の真実として扱い、疑わない」のだと。
Clerk は、出荷したことのないパッケージを文書に書いた
いちばん分かりやすい例は、ある認証ベンダーから出てきました。その文書は読者に こう実行するよう伝えています。
npx clerk-next-fix-auth-protection
Clerk はその名前で単体のパッケージを公開したことがありません。コマンドが略記
だったのかもしれないし、社内の何かを指していたのかもしれないし、書き手が
間違えただけかもしれません。理由はどうでもよいのです。エージェントにとって、
その名前は本物に読めたのですから。別の誰かがそれを登録しました。アドバイザリ
データベースはいまそのパッケージを MAL-2026-11069 として収録しており、それは
偵察のために作るものそのものでした。npm のインストールフックが発火し、
インストールしたアカウントのユーザー名、マシンのホスト名、作業ディレクトリ、
タイムスタンプを送り出したのです。
これは誰かのビルド環境の地図です。しかもそれを、その人のネットワークの内側で、 その人自身のコーディングエージェントが、その人自身のベンダーの文書に従って 集めました。
いつもの助言が、そのままペイロードを指してしまう理由
サプライチェーンの手引きはどれも、パッケージ名を公式ドキュメントと突き合わせろと 言います。ここではその助言が機能しません。悪い名前が出てきた場所こそ、その公式 ドキュメントだからです。
七月に書いた問題を裏返すと、この問題に なります。あちらでは、エージェントがもっともらしいパッケージ名を幻覚し、攻撃者が エージェントの作りがちな名前を登録するので、弱い一手は モデルの推測でした。ここではモデルは何も推測しません。ベンダーのところへ行き、 ベンダーの言うことを読み、それに従う。その丁寧な手順こそが、モデルを捕まえるのです。
レジストリの侵害もまた形が違います。先月 リリースワークフローが実在パッケージの汚染版を十個公開した とき、まず何かが壊れる必要がありました。コメントを信じたワークフローです。ここでは 何も壊れません。テクニカルライターが、公開済みの成果物とわずかに一致しない コマンドを打つ。これはソフトウェアで最もありふれた間違いです。そして名前と成果物の あいだの隙間が、インターネット上の誰でも拾える実行プリミティブに変わります。
これを止める層は、すでに有効になっている
Bromure Agentic Coding は、各コーディングエージェントをあなたの Mac 上の ハードウェア仮想化された Linux VM で動かします。そしてエージェントが取得する パッケージはすべて、その境界のホスト側にあるプロキシを通ります。一バイトでも VM に 届く前にです。そこには複数の層が適用されます。この話については、そのうちの一つだけで 仕事が片づきます。しかもそれは、新しいワークスペースがすでに有効にしている層です。
年齢ゲートは、取得したての名前を無意味にします。 ワークスペースは、しきい値より
新しいパッケージのバージョンを拒否します。既定値は二日です。プロキシは、通過する
レジストリのバージョン一覧を書き換えることでそれを強制します。しきい値より新しい
バージョンを取り除き、latest を生き残ったうち最新のものへ張り替えるのです。今朝
初めて公開されたパッケージには、そのフィルタを生き延びられるだけ古いバージョンが
存在しません。ですからエージェントから見れば、その名前にはインストールできるものが
何もありません。エージェントが新しすぎるバージョンを直接要求した場合、取得は
HTTP 451 で返り、その本文にはパッケージの実際の日数と要求される最小値が書かれます。
npm はその文言をそのまま表示します。
これを踏まえてもう一度この攻撃を読んでください。この手口全体は、攻撃者の選んだ 瞬間に名前が未公開から公開へ移ることに依存しています。その移行こそが、真新しい リリースそのものです。攻撃者が避けようのない唯一の性質が、既定のポリシーが 狙っている当のものなのです。
インストールスクリプトの除去は、ペイロードが使った仕組みそのものを取り除きます。
観測されたパッケージは、npm の preinstall、install、postinstall、prepare
フックで仕事をしていました。スクリプト除去を有効にすると、プロキシは npm の
tarball を流れの中で展開し、package.json からその四つのキーを削除し、npm 自身の
ハッシュ検証が通るようにメタデータから dist.integrity と dist.shasum を消して、
再び圧縮します。パッケージはインストールされ、ビーコンには走る場所がありません。
better-sqlite3 のようなネイティブバインディングのコンパイラなど、フックが必要な
パッケージは、ワークスペースごとの許可リストに載せてフックを残せます。
レピュテーションフィルタは、このパッケージを名前で知っています。
MAL-2026-11069 はマルウェアのアドバイザリです。ワークスペースのパッケージ
フィルタに socket.dev を選ぶと、その侵害パッケージのブロックは、深刻度を問わず
マルウェアおよびタイポスクワットのシグナルで発火します。無料の OSV チェックは、
API キーなしで傍受対象の八つのエコシステムすべてを覆います。レピュテーションの
情報源が判定を出せないとき、レート制限であれ、ネットワーク断であれ、対象外の
エコシステムであれ、Bromure は取得を許すのではなく閉じる側に倒れます。
ダウンロードは一時停止し、パッケージとバージョンごとにあなたに尋ねます。ですから
参照の失敗を誘発できる攻撃者にも、得るものはありません。
集められる偵察情報は VM のものです。 この研究についての見出しはどれも同じことを 言います。エージェントが企業ネットワーク上で未知のコードをインストールしている、と。 ビーコンの収穫は、インストールしたユーザー名、マシンのホスト名、作業ディレクトリ でした。Bromure のワークスペースでは、その三つのフィールドが表すのは、あなたの Mac 上の Linux ゲストであって、標的リストに載せる価値のある内部名を持ったドメイン参加の ビルドホストではありません。その VM にある資格情報はおとりで、本当の値はホスト プロキシのメモリの中にしか存在しません。敵対的なコードがそれを、発行先ではない ホストへ持ち出そうとすれば、プロキシがリクエストを遮断し、VM を飛行中に一時停止 させます。
既定の拒否が、この研究のもう半分に答えます。 空いていた名前のかなりの部分は、 パッケージではなくホスト名でした。失効したドメインや、Vercel、Render、Fly、Netlify の無料サブドメインが、エージェントの取得しに行く文書の中に座っていたのです。 ワークスペースの外向きファイアウォールは、Unmatched traffic の設定を備えた 順序付きルール表です。これを Deny にすれば、VM はあなたが列挙したホストへ、 そしてそれ以外のどこへも、どのプロトコルでも接続を開けません。ゲストの外側で二つの 部品がそれを強制します。仮想ネットワークスイッチが宛先 IP アドレスで各フローを照合し、 ホストプロキシが TLS のサーバー名でもう一度照合します。誰かが先週の火曜に登録した ドメインを狙うビーコンは、マシンから出ていきません。ルールの編集は、再起動なしで 実行中のセッションに届きます。
あらゆる試みが一行になります。 トレースレベル Activity only では、プロキシは
VM から出る各リクエストにつきメタデータのレコードを一件書きます。時刻、ホスト、
ポート、メソッド、パス、ステータス、レイテンシ、バイト数を含み、リクエストの本文は
一切保存しません。bromure-cli trace hostnames my-workspace は、そのワークスペースが
接続した個別のホストをすべて件数つきで表示します。あなたは、自分のエンジニアの誰も
見覚えのないコールバック先ドメインを、それが起きたその日に、自分のマシンの上で
目にします。何か月も後によその人のデータセットで読むのではなく。
すでに有効になっているもの
新しいワークスペースは、最小二日の年齢ゲートが有効な状態で届きます。この攻撃が
ぶつかるのは、まさにその設定です。仕事が待てるなら、ステッパーで最大 90 日まで
引き上げてください。自チームが公開してその時間のうちに入れるパッケージには、
npm:our-package の形で Exempt packages を使ってください。
今日オンにする価値があるもの
ワークスペースの Supply Chain ペインで、インストールスクリプトの除去を 有効にし、パッケージフィルタを選びます。Guardrails では Unmatched traffic を Deny にし、その仕事に必要なホストを列挙します。 Tracing の Activity only は、接続先ホストの足跡だけを残し、中身は 残しません。これらの編集はどれも、すでに動いているセッションに適用されます。
機械向けに書かれたファイルを、誰も校正しない
PANDEX のスキャナはもう一つ探しているものがあります。取得されていないパッケージや
ドメインと並んで、読者ではなくエージェントに向けた指示を探すのです。ファイルに
仕込まれた指令で、ときに Unicode の小細工やゼロ幅文字で隠されています。ベンダーの
ビルドパイプラインが llms.txt を生成し、あなたのエージェントがそれを消費し、
どちらの会社でも、そのあいだを通ったものを誰も読んでいません。
Bromure は、取得したページを信頼できない入力として扱います。エージェントが外から
引き込んだ内容は、ファイルの中身であれ、Web ページであれ、issue の本文であれ、
コマンドの出力であれ、tool_result のスパンとしてモデルに届きます。ソースコード
検出器を有効にすると、あなたの Mac 上で動く PromptGuard モデルが、モデルがそれに
基づいて動く前に、通信路上でそれらのスパンを採点します。記録するか、尋ねるか、
遮断するかはあなたが選びます。走査のためにどこかへ内容が送られることはありません。
私たちは十年をかけて成果物を検証することを学んできました。パッケージに署名し、 ハッシュを固定し、ビルドを証明する。この研究が扱うのは、そのすべての一つ手前の 段階です。エージェントがどの成果物を要求するかを決める段階であり、その拠り所は 署名を持たず、急いでいたテクニカルライターが書いた文書なのです。ドキュメントは 実行可能な入力になり、レジストリは、あるベンダーが言及したと誰かが気づくのを待つ 空き名で溢れています。
自分の llms.txt を、公開したことのない名前がないか grep してください。それは一朝の
仕事で、あなたを誰かの標的リストから外してくれます。それから、四分前に公開された
パッケージをインストールできず、エージェントがどこへ行ったかをすべて見られる
マシンを、エージェントに与えてください。
Bromure Agentic Coding を導入し、インストールの経路をホストの上に
置きましょう。