すべての投稿に戻る
公開日 · 著者 Renaud Deraison

フラグはノーと言った

2026年8月3日、The Hacker News が FaceHugger を報じた。Hugging Face の Diffusers ライブラリ——月間700万ダウンロード——にある3つの欠陥で、細工されたモデルリポジトリが、それを読み込んだマシン上で任意コードを実行できる。trust_remote_code=False を設定していてもだ。根本原因:信頼チェックとコードの読み込みが別々のタイミングで走っていた。コーディングエージェントはパッケージを取るのと同じ感覚でモデルを取るから、嘘をついたフラグが守っていたのは開発者のラップトップだった。Bromure Agentic Coding は境界をプロセスの中ではなく下に置く。読み込みは使い捨て VM の中で走り、手の届くクレデンシャルは囮で、ペイロードの帰宅通信はホストプロキシで死ぬ——悪意あるリポジトリは攻撃者にはペイロードを失わせ、あなたには何も失わせない。

リポジトリには None.py という名前のファイルがあり、それがトリックの すべてだった。安全フラグは設定され、チェックは走り、それでもコードは 実行された。チェックと読み込みが2つの別々の瞬間に起きていたからだ—— そして攻撃者は、2つ目の瞬間にいるだけでよかった。

2026年8月3日、The Hacker News が、Zafran Labs が7月末に公開した 研究を取り上げた。Hugging Face の Diffusers ライブラリにある3つの脆弱性、 総称 FaceHugger。細工されたモデルリポジトリが、それを読み込むあらゆる マシン上で任意の Python コードを実行できる。Diffusers は拡散モデルを動かす 標準の道具だ——月間およそ700万ダウンロード、本番パイプライン、CI ジョブ、 ノートブック、コンテナイメージの中に座っている。ライブラリにはまさに このシナリオのための安全装置がある。trust_remote_code、モデルリポジトリ 由来の未レビューコードがあなたのマシンで走るのを止めるはずのフラグだ。 3つの欠陥はすべて、それが False のまま脇を通り抜ける。

チェックと読み込みは2つの別々の出来事だった

Hub からモデルを読み込むのは1回の操作ではない。ライブラリは2つの HTTP リクエストを順に発行する。1つ目はリポジトリの設定を取得し、2つ目はその 設定が指すコードと重みを取得する。trust_remote_code のゲートは1つ目の リクエストの間に検査をした。ゲートが警戒していた当のものは、2つ目で 届いた。

Zafran の研究者はこの隙間を通る3つの道を見つけた。いまは CVE が 付き、 Diffusers 0.38.0 で修正済みだ。CVE-2026-44827(CVSS 8.8)では、カスタム パイプラインが要求されていないときに文字列フォーマットの癖が None.py というファイル名を組み立てる——そしてそのファイルの存在チェックは それを警告しないコードパスで走るため、None.py という名前のファイルを 同梱したリポジトリはゲートを通過し、読み込み時に実行される。 CVE-2026-45804 は競合だ。2つのリクエストの間には約3分の1秒があり、その間に 変化するリポジトリは、あるものとして検証され、別のものとして実行される。 CVE-2026-44513 はローカルスナップショットの読み込みでゲートを丸ごと飛ばす。 Zafran の研究者は3つを1文に圧縮した。ゲートが見なかったカスタムコードを ローダーに見せる方法は、どれであれバイパスを許す。

このパターンには前歴がある。Transformers——Hugging Face エコシステムの もう1本の柱——にも独自の trust_remote_code=False バイパス (CVE-2026-4372)があり、ごく標準的なモデル読み込み呼び出しで悪用できた。 このバグクラスは設計と一緒にやってくる。監視対象のプロセスの内側に住む セキュリティの約束、というやつだ。フラグは関数の引数で、その強制は コードパス、ファイル名フォーマット、リクエストのタイミングに散らばって いる。そのどれかがフラグと食い違えば、負けるのはフラグで、負けたことを 誰も教えてくれない。モデルは読み込まれ、デモは動く。

あなたのエージェントは火曜日にモデルを読み込む

この話をコーディングエージェントの椅子から読み直そう。「Hub から インペインティングのパイプラインを取ってきて、うちのとベンチマークして」 は、ごく普通の火曜日のタスクだ。プロジェクトは diffusers==0.37 を ピン留めしている。プロジェクトとはピン留めするものだからだ。エージェントは 慎重なエンジニアが書く通りのものを書く—— from_pretrained(..., trust_remote_code=False)——そして慎重な書き方こそが 脆弱な書き方だ。パッケージならインストール前にソースを読める。モデル リポジトリは設定と重みと、ローダーのおかげで、2つ目の HTTP リクエストが 言う通りの何かだ。

エージェントはこの読み込み経路を熱くした。彼らはパッケージを取るのと 同じように、タスクの途中で、名前でモデルを取ってくる。そして攻撃者は すでに、推薦そのものに毒を盛れる ことを突き止めている。読み込み時に起爆するモデルリポジトリは、レジストリを 1つずらした同じ手口で、変装はより上手い。ペイロードは、あなたがコードでは なくデータに分類する成果物の中に座っている。

Zafran の助言は、モデルリポジトリを信頼できないコードとして扱えという ものだ。正しい——ただしレポートが深追いしない前提がある。信頼できない コードが、あなたに何のコストも負わせず走れる場所だ。疑いのポリシーは、 締め切りが騒がしくなるまで維持する規律にすぎない。起爆のために作られた 部屋は、あなたの規律を必要としない。

読み込みは箱の中で起きる

Bromure Agentic Coding がその部屋であり、FaceHugger のフラグが失敗した 地点から始まる。境界はプロセスの下に座り、ローダーの内部が口出しできない 環境にあって、プロセスが協力してもしなくても強制される

攻撃をプロファイルに通してみよう。あなたのエージェントはピン留めごと ベンチマークのタスクを受け取り、悪意あるリポジトリに対してローダーを呼ぶ。 None.py が実行される——使い捨て Linux VM の中、macOS からハイパーバイザ 1枚を隔てた場所で。ペイロードがいま手に入れたマシンは、このタスクのために 存在し、このタスクのワークスペースを持ち、作業がマージされたら破棄される マシンだ。

ペイロードの最初の本当の一手は外向きだ。そうするしかない。第2段を取りに 行くか、見つけたものをオペレーターに送るか。そのどのリクエストもホスト プロキシを横切り、宛先はこのプロファイルのためにあなたが承認したリストと 照合される。huggingface.co はリストにある——モデルはそうやって届いた。 攻撃者のドロップ先はない。ワイヤが拒む。ゲートがそうすべきだった ように——ただしこの拒否は、 ライブラリのコードパス同士が一致していることに依存しない。プロキシは どの Python ファイルがリクエストしているのか知らないし、気にもしない。 宛先を照合し、承認済みのものが見つからず、接続を落とす。

ペイロードがネットワークを諦めて、環境変数やキーのファイルを漁りに 行ったとしよう。見つかるのはブローカーの囮だ。 本物の値はホストに住み、承認済みの宛先に対してだけワイヤで注入される—— パスワードは最初から VM の中にない のだから盗みようがない。滞在を永続化しようとしても——設定を書き換える、 何かをオフにする—— 破壊的な形はホスト上のガードレールダイアログ で一時停止するし、寿命がタスク1つ分のマシンでの永続化は、どのみち割に 合わない取引だ。

その間に、タスクは成功する。ベンチマークは走り、数字は返り、あなたは diff を読む。攻撃者はサプライチェーン上のポジションを、盗むもののない、 家に電話する手段もない部屋で実行されたペイロードに費やした。あなたは 何も費やしていない——注意力すらも。趣味でプロキシのログを読むのでなければ。

プロセスの内側 — フラグの住処リクエスト1 · 設定取得trust_remote_code はここで検査判定:「カスタムコードなし」✓~0.3秒 — 再チェックなしリクエスト2 · コード取得None.py が届く — そして実行ゲートは見ていない (CVE-2026-44827)約束と強制は、同じプロセス内の別々の瞬間だった。プロセスの下 — Bromure プロファイルの検査点使い捨て Linux VMエージェント · ローダー · None.py — 全部、フラグ不問手の届くクレデンシャル: 囮タスク終了時に破棄全リクエストホストプロキシhuggingface.co → 許可攻撃者のドロップ先 → 拒否本物のキーはワイヤで注入
チェックが走った場所と、走るべきだった場所。Diffusers の信頼ゲートは1つ目の HTTP リクエストで設定を検査した。コードは2つ目で届き——実行された。Bromure プロファイルはローダーの内部を審判しない。プロセス全体が使い捨て VM の中で走り、外向きのリクエストは誰が発したものであれ、あなたが承認した宛先のリストとホストプロキシで照合される。

ライブラリにはパッチを、部屋はそのままに

Zafran のレポートの修正ノートは、組織はアップグレードし、それから狩りに 出ろと言う。古い Diffusers リリースをピン留めしたアプリケーション、 ノートブック、推論サービス、コンテナイメージを探せと。この狩りに ゴールラインはない——依存ツリーのどこかで、どこかのプロジェクトが隙間の あるバージョンをピン留めしていて、次の FaceHugger は別のライブラリの フラグと別のバイパスだ。ガードとシェルは食い違った はコマンド許可リストにおけるこの失敗で、サンドボックスは1つの文 だったはプロンプトにおけるこの失敗 だった。いずれの場合も、チェックは自分が検査する当のものの内側に住み、 そして当のものが勝った。

プロファイルの境界はその運命を共有しない。閉じ込める対象のプロセスに 参加しないからだ。VM はパイプラインの設定をパースしない。プロキシに None.py のコードパスはない。彼らのただ1つの仕事——このマシンは使い捨て、 このワイヤはリスト外の宛先を拒む——は、バイパスが公表された日も、パッチが 当たった日も、同じ仕事だ。Sumo Logic の CISO は、Bromure など念頭に ないままこの研究にコメントし、持ちこたえる防御を名指しした。 「地味なやつです。イグレス制御、セグメンテーション、クレデンシャルの 衛生管理」。 私たちはその地味なやつを、クリックひとつのプロファイルに組み込んだ。

モデルは引き続き取ってくればいい——テコはそこにあり、あなたの エージェントはあなたの代わりに試すべきだ。関数の引数ひとつを、Hub と あなたのラップトップの間にある唯一のものにしておくのはやめよう。 Bromure Agentic Coding をインストールし、ルールが ワイヤで守られるプロファイルをエージェントに与えれば、次にローダーの 約束が破れたとき——破れるときは来る——ニュース記事は誰か他の人のものの ままだ。