コーディングエージェントが実際にアップロードするもの
- すべてのコーディングエージェントが持つ2つの egress チャネルを区別する — そして、なぜそのうち一方だけが見えるのかを理解する
- Grok Build のワイヤーキャプチャを読み解く: 同一セッションからのモデルトラフィック 196 KB 対 リポジトリアップロード 5.10 GiB
- 権限拒否と「自分のデータで学習しない」トグルが両方守られていても、なぜリポジトリがマシンから出ていけるのかを学ぶ
- mitmproxy とカナリアリポジトリで自分のエージェントを盗聴し、エンドポイントごとのバイト数を自分で数える
- Claude Code、Cursor、Gemini CLI、Codex がそれぞれ何を送ると文書化しているか — そして文書がどこで途切れるかを比較する
あなたはおそらく、コーディングエージェントのプライバシーをこう捉えているでしょう: 読んだものを送る。ファイル読み取りを承認すればそのファイルはモデルへ行き、拒否すれば行かない。あなたのプロンプトとコンテキスト内のファイルがペイロードで、それ以外はすべてメタデータ、と。
そのモデルは、少なくとも出荷済みのあるエージェントについては間違っており、いくつかの他のエージェントについても構造的に不完全です。2026年7月、ある研究者が xAI の Grok Build CLI にプロキシを向け、12 GB のリポジトリが git バンドルとして — 全履歴、一度も読まれていないファイル、.env の中身を含めて — マシンから出ていったことを発見しました。それは、エージェントが読んだ内容とは無関係のチャネルを通じてのことであり、一方で、ユーザーがそれを止めようと手を伸ばす設定はまったく別のものを制御していました。
このページは実のところ Grok についてではありません。Grok が露呈させたチャネルについてであり、それはほとんどのエージェントが何らかの形で持っているものです。そして、マーケティングページを信じる代わりに、一晩で自分のものを確認できるという事実についてです。
2つのチャネル
ホストされたモデルと通信するすべてのエージェント CLI はチャネル A を持ちます。一部はチャネル B も持ちます。
チャネル A — モデルターン。 あなたのプロンプト、システムプロンプト、ツール定義、そしてエージェントが実際に読んだファイルの中身。これはあなたの直感が追っているチャネルです。権限プロンプトがゲートし、.gitignore 形式の拒否ルールが影響し、トランスクリプトからおおよそ予測できるものです。そしてこれは小さい: 作業セッションでキロバイトから低いメガバイト程度が動きます。
チャネル B — アンビエントチャネル。 クライアントが自分の判断でアップロードするもので、あなたのターンに答える一部としてではありません: コードベースのインデックス化、セッショントレース、クラッシュレポート、利用状況の分析、フィードバックバンドル。モデルの推論ではなく、クライアントのスケジュールで動きます。トランスクリプトには現れません。確認も求めません。そして LLM の判断ではなくコードパスに駆動されているため、どれだけプロンプトを工夫しても影響しません — エージェントに「どのファイルも読むな」と伝えるのはチャネル A を制約するだけで、チャネル B については何も言っていません。
チャネル B は本質的に邪悪なわけではありません。Cursor のサーバー側インデックスはチャネル B であり、詳細に文書化されています。危険なのはその存在ではなく — ユーザー向けの制御がほぼ常にチャネル A 向けに設計されていることです。だから人々は、出口が1つしか見えていないのに、出口が2つあるシステムについて推論してしまうのです。
ワイヤーキャプチャ
cereblab として公表している研究者が、Grok Build CLI 0.2.93(macOS arm64、コミット f00f96316d4b)を、信頼済み CA を使って 127.0.0.1:8080 の mitmproxy を通し、仕込んだカナリア文字列を含む使い捨てリポジトリに対して実行しました。ハーネス、キャプチャされた証拠、SHA-256 チェックサムは再現用リポジトリとして公開されているので、これは信じるしかない主張ではなく、自分で再実行できる主張です。
キャプチャが示したもの:
2つのエンドポイント、まったく異なる容量。 12 GB のリポジトリに対する単一セッションで:
| チャネル | エンドポイント | バイト数 | リクエスト数 |
|---|---|---|---|
| A — モデルターン | POST cli-chat-proxy.grok.com/v1/responses | 196,705 | 5 |
| B — リポジトリアップロード | POST cli-chat-proxy.grok.com/v1/storage | 5,476,228,005(5.10 GiB) | 82、すべて HTTP 200 |
およそ 27,800倍 の比率です。この差こそが議論のすべてです: これほどの容量が、モデルが読んだものから生じることはありえません。それはコードベースそのものから生じています。アップロードは約 75 MB のチャンクとして送られ(ログに残った実行では73個)、キャプチャはそれらがまだ成功している最中に打ち切られました。つまり 5.10 GiB は総量ではなく下限です。
一度も読まれなかったカナリア。 エージェントには平易な言葉で Reply exactly OK, do not read any files とプロンプトが与えられました。ユニークなマーカーを含む src/_probe/never_read_canary.txt のファイルは、どの /v1/responses ボディにも現れませんでした — チャネル A は指示どおりに振る舞いました。しかしそれは、傍受された /v1/storage リクエストから復元された git バンドルの中に現れました。研究者はキャプチャしたバンドルを git clone し、マーカーと全履歴が無傷のままリポジトリを取り戻しました。別のカナリア、.env ファイル内の偽の DB パスワードは、両方のチャネルに逐語的かつ非マスクで現れました。
送信先は名前付きバケットだった。 バイナリ内の文字列とステージされたアップロードのメタデータは、Google Cloud Storage のバケット grok-code-session-traces を指しており、オブジェクトパスは gs://grok-code-session-traces/repo_changes_dedup/v2/… の形式でした。CLI のセットアップ資料にはこれを説明するものは何もありませんでした。
修正と、その対応の形。 2026-07-13、同じ変更されていない 0.2.93 バイナリが、6回の再テストにわたって /v1/storage リクエストの発行を止めました — クライアントの更新ではなく、サーバー側のフラグ切り替え(disable_codebase_upload: true)です。xAI は正式なアドバイザリではなく X 上で対応しました: エンタープライズのゼロデータ保持顧客は影響を受けないとされ、個人サブスクライバーは /privacy コマンドを案内され、以前アップロードされたデータは削除されたとされました。現在の状態は「今のところ修正済み」と扱い、このクラスのバグは恒久的なものとして扱ってください。
これが崩す、あなたがおそらく信じていた3つのこと
★ 「エージェントは読んだものしか送らない」。 チャネル B が存在するときはいつでも偽です。読み取りは LLM の判断ですが、インデックス化はコードパスです。両者は同じサブシステムではなく、同じゲートを共有していません。
★ 「ファイルを拒否したから安全だ」。 権限拒否はツール層で作用します — エージェントがそのファイルをコンテキストに引き込むのを止めます。ネットワーク egress ルールではありません。Grok のケースでは、拒否されたファイルが git バンドルの中で依然として送られました。もしあなたの脅威モデルがあるファイルをマシンから出さないことを必要とするなら、強制ポイントはエージェント自身の権限プロンプトではなく、ファイルシステムかネットワークでなければなりません。
★ 「自分のデータで学習しない」≠「自分のデータを送信しない」。 これらは2つの異なる制御であり、ベンダーは日常的に前者だけを公開します。Grok の「Improve the model」トグルは学習への同意にマップされていました。それをオフにしても、サーバーは依然として trace_upload_enabled: true を返し、リポジトリのアップロードは変わらず続きました。Anthropic のドキュメントは Claude Code について同じ区別を明示的に描いています — 学習データの設定とテレメトリ/フィードバックのスイッチは、別々の環境変数を持つ別々のつまみです。すべてのプライバシートグルを 「保持してよいか?」 に答えるものとして読み、決して 「取得するか?」 に答えるものとは読まないでください。
自分のエージェントを盗聴する
誰の文書も — このページも含めて — 信じる必要はありません。15分とプロキシがあれば、あなたが動かしているどんなエージェントについても地に足のついた真実が得られます。偽の秘密を含む使い捨てリポジトリで、自分のマシンで実行してください。
- mitmproxy は初回実行時にローカル CA を生成します。それをシステムの信頼ストアにインストールし、エージェントの TLS 呼び出しが失敗するのではなくプロキシで終端されるようにします。これがすべての肝です — エージェント CLI は普通の HTTPS クライアントであり、ほとんどが標準のプロキシ環境変数を尊重します。
- 使い捨ての git リポジトリを作ります。.env ファイルにユニークなマーカー(偽の資格情報)を仕込み、エージェントに決して開くなと明示的に伝えるファイルに2つ目のユニークなマーカーを仕込みます。両方をコミットします — コミット済みファイルが git バンドルのアップロードで運ばれるものです。マーカーは自然には出現しえない文字列でなければならず、キャプチャに対する grep が曖昧さなく機能するようにします。
- HTTPS_PROXY をリスナーに向け、まったく何も読む必要のないタスクをエージェントに与えます。エージェントがチャネル A しか使っていないなら、ほぼ空のセッションはほとんどバイトを動かさないはずです。
- リクエストボディのサイズをホストとパスでグループ化して合計します。これが重要な測定です。何も読まないのに数百メガバイトを動かすセッションは、ドキュメントが何と言おうとチャネル B を持っています。
- 生のフローを検索し — 見つかったアーカイブやバンドルは展開して — 両方のマーカーを探します。決して読まれなかったマーカーがキャプチャのどこかに現れれば、それは陽性の結果です: 何かが、モデルが読んだ内容とは独立にファイルをアップロードしています。
- 今度は学習への同意、テレメトリ、分析、インデックス化 — ベンダーが公開するすべてをオフにして繰り返します。2回の実行の差分が、それらのトグルが実際に何を制御するのかを正確に教えてくれます。それはトグルのラベルがめったに答えない問いです。
最小限の盗聴ハーネス
# 1. proxy + CA (macOS; on Linux use your distro's trust store)
brew install mitmproxy
mitmdump -w flows.mitm --set confdir=~/.mitmproxy &
sudo security add-trusted-cert -d -r trustRoot \
-k /Library/Keychains/System.keychain ~/.mitmproxy/mitmproxy-ca-cert.pem
# 2. canary repo
mkdir -p /tmp/canary/src/_probe && cd /tmp/canary && git init
echo 'DB_PASS=CANARY-AAAA-ENVSECRET' > .env
echo 'CANARY-BBBB-NEVERREAD' > src/_probe/never_read.txt
git add -A && git commit -m "canary"
# 3. run the agent through the proxy, asking it to read nothing
HTTPS_PROXY=http://127.0.0.1:8080 HTTP_PROXY=http://127.0.0.1:8080 \
<your-agent-cli> "Reply exactly OK. Do not read any files."
# 4. bytes per endpoint — the number that matters
mitmdump -nr flows.mitm \
--set console_eventlog_verbosity=info \
-s <(echo 'def response(f): print(f.request.pretty_host, f.request.path,
len(f.request.raw_content or b""))')
# 5. did a file you never opened leave the machine?
strings flows.mitm | grep -c 'CANARY-BBBB-NEVERREAD'ステップ5が 0 以外の何かを返したら、あなたはチャネル B を見つけたことになります — しかも自分で見つけたのです。それは、時間が経っても色褪せない唯一の種類の発見です。
主要な各 CLI が文書化しているもの
ドキュメントは主張であり、ワイヤーキャプチャは証拠です。両者のギャップこそがこのページ全体の教訓です。それでも、主張の違いは知っておく価値があります — そしてそれらを知ることが、キャプチャを実行するときに何を探すべきかを教えてくれます。
Claude Code。 リポジトリ全体のインデックス化やバンドルアップロードのチャネルは、文書化されたデータフローには現れません。エージェントはツールで検索し、ファイルの中身をモデルターンの一部として送るため、出ていくファイルの中身はコンテキストに引き込まれたものです。運用テレメトリは別で、Anthropic のドキュメントによれば「コードやファイルパスを一切含まない」(DISABLE_TELEMETRY=1)。Sentry のエラー報告はさらに別です(DISABLE_ERROR_REPORTING=1)。コードを運ぶチャネルは明示的でオプトインです: /feedback はコードを含む会話履歴を送り(DISABLE_FEEDBACK_COMMAND=1)、セッション品質調査のトランスクリプト共有ステップは、あなたが能動的に Yes を選んだ場合にのみ、既知のキーとトークンのパターンを先にマスクしたうえでトランスクリプトをアップロードします。CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC はそれら一式の単一のキルスイッチです。保持期間: 商用(Team/Enterprise/API)は30日、モデル改善をオフにした消費者は30日、オンにした人は5年。ゼロデータ保持は適格なエンタープライズアカウントに存在します。Anthropic は、組織がオプトインしない限り、商用条件で送られたコードで学習しません。
Cursor。 教科書どおりの文書化されたチャネル B: コードベースのインデックスは、リポジトリをチャンク化し、チャンクを埋め込み、埋め込みと暗号化されたファイルパスを Cursor のサーバーへ送ることで構築されます。ドキュメントによれば、コードの中身はインデックス化中はメモリ上に保持され、その後は平文で保存されるのではなく破棄され、チャンクはエージェントが取得するときにクライアント側で復号されます。これは派生成果物の本物のリポジトリ全体アップロードであり — 生の git バンドルとは実質的に異なるリスクプロファイルで、Claude Code の「必要なものを読む」モデルとも実質的に異なります。3つのうちどれが欲しいかは判断の問題です。自分がどれを動かしているか知らないというのは、そうではありません。
Gemini CLI。 利用統計はデフォルトでオンで、settings.json の privacy.usageStatisticsEnabled: false で無効化します。ドキュメントは、プロンプトとレスポンスの内容、および読み書きしたファイルの中身はログに記録されないと述べています。OpenTelemetry の計装は別で、あなたが管理するコレクターに向けられます(telemetry.enabled: false でオフ)。
Codex CLI。 匿名のクライアント分析はデフォルトでオンで、分析設定フラグで無効化します。OTel エクスポートは自分のコレクターにルーティング可能で、プロンプトのログ記録(log_user_prompt)は有効にしない限りオフです。セッションのトランスクリプトは CODEX_HOME 配下にローカルで永続化されます — 下記参照。
誰も確認しない半分: あなた自身のディスク
egress は一方向にすぎません。これらのエージェントはどれも、あなたのセッション — プロンプト、ファイルの中身、ツール出力、時には秘密 — をローカルディスクに平文で書き込み、それらのファイルはセッションより長く残ります。
Claude Code はトランスクリプトをデフォルトで30日間 ~/.claude/projects/ 配下に保存します(cleanupPeriodDays で調整)。Codex は履歴を CODEX_HOME 配下に永続化します。Grok Build はアップロードを ~/.grok/upload_queue にステージしました — 報告によればターンあたりギガバイト単位で、負荷がかかるとディスクを埋め尽くすまで増大しうるものでした。これはプライバシーバグの中に潜むサービス拒否バグです。
帰結: ラップトップのバックアップ、同期フォルダ、あるいはホームディレクトリへの読み取りアクセスを持つ第2のプロセスは、あなたがたった今計装したネットワークスタックに一切触れない流出経路です。セッションに入ったどんな秘密も、今やあなたが置いた覚えのない場所のディスク上に平文で存在します。
実際に持ちこたえるハードニング
Hacker News の議論の繰り返されるテーマ — 両スレッドにまたがる数百のコメント — は、markdown レベルの指示はセキュリティ境界ではないということでした。CLAUDE.md やその同等物はモデルへのガイダンスであって、バイナリに対する強制ではありません。もし制御がクライアントに対して持ちこたえる必要があるなら、それはクライアントの下位に存在しなければなりません。
- 作業リポジトリだけをマウントしたコンテナや devcontainer で実行します。これが単一で最もレバレッジの高い変更です: ~/.ssh、~/.aws、シェル履歴、他のクライアントのリポジトリ、パスワードボルトを見られないエージェントは、文書化されていようがいまいが、どのチャネルからもそれらをアップロードできません。別の OS ユーザーでも、少ない手間で同じことの多くを達成できます。
- エージェントのコンテナからの送信をデフォルトで拒否し、必要なモデル API ホストだけを許可します。あなたが承認していないチャネル B は、閉じた egress ポリシーを通じて外部に発信できません。おまけに、これは将来のあらゆる未文書化のアップロードチャネルを、インシデントからログ上の接続エラーへと変えます。
- 作業ツリーの中の .env は、エージェントが漏らしうる最も価値の高い単一ファイルであり、コミットされてバンドル型アップロードで運ばれる可能性が最も高いものです。秘密は実行時に秘密マネージャーや環境から注入し、リポジトリの外、マウントされたツリーの外に保ちます。
- 前節のキャプチャを、すべてのプライバシー設定を最大にして一度実行します。15分が、主張の代わりに事実を買ってくれます — そしてそれは、このインシデントを研究者より先に捉えられた唯一のステップです。
- 何がアップロードされ何がされなかったかを再構成しようとしないでください。SSH キー、クラウド資格情報、API トークンが、露出期間中にエージェントがアクセスできたディレクトリで到達可能だったなら、開示されたものとして扱いローテートします。資格情報のローテーションは安価で、どのバイトが動いたかについての法医学的議論はそうではありません。
- ゼロデータ保持と商用条件は、上記の制御の代替ではありませんが、ベンダーが何を保持してよいか、あなたにどんな救済があるかを変えます。漏らすわけにいかないコードベースでエージェントを動かしているなら、消費者向けの階層は間違った階層です。
Check yourself
0/4これがどこへ向かうか
このインシデントについてモデル固有のものは何もなく、目新しい攻撃も必要としませんでした。必要だったのは、もっともらしく聞こえること — エージェントに良いコンテキストを与えるためにリポジトリをサーバー側にキャッシュすること — を、それを表に出さずに行ったクライアントと、その語彙(「Improve the model」)がユーザーが実際に尋ねていた問いにマップされていなかった設定画面でした。
その両方は極めてありふれています。エージェント CLI というカテゴリは生後18か月、速く動いており、コードをアップロードする機能を出荷しています。コードをアップロードすることが製品を良くするからです。もっとこうしたことが起きると予想してください。守れる立場は、最良のプライバシーページを持つベンダーを選ぶことではありません。測定する習慣を築き、間違った答えがもたらすコストを制限する箱の中でそれを動かすことです。
同じ問題の敵対的な側面 — すでにあなたの権限を持つエージェントを操る信頼できないコンテンツ — が欲しいなら、コーディングエージェントが武器化されるときと自律実行のハードニングを読んでください。データフロー以外のすべてで CLI がどう異なるかは、コーディングエージェント CLI 比較を参照してください。
ソースと参考資料
- cereblab — "What xAI Grok Build CLI actually sends to xAI: a wire-level analysis (grok 0.2.93)" — 一次キャプチャ: エンドポイント、バイト数、カナリア手法、バイナリハッシュ。
- cereblab/grok-build-exfil-repro — mitmproxy ハーネス、カナリアリポジトリ、証拠ディレクトリ。自分で再現してください。
- Hacker News — "Grok CLI uploaded the whole home directory to GCS" — 400以上のコメント、主に隔離戦略について。
- Hacker News — "xAI's Grok Build CLI Uploads Git Repositories to a Google Cloud Bucket" — ワイヤーレベル分析についてのスレッド。
- The Hacker News — "Grok Build Uploaded Entire Git Repositories to xAI Storage" — 経緯と xAI の対応。
- Anthropic — Claude Code data usage — テレメトリ、フィードバック、保持、それぞれを制御する環境変数。
- Cursor — Codebase indexing — インデックスが何をアップロードし、何を保存しないか。
- Gemini CLI — configuration and telemetry —
usageStatisticsEnabled、OTel ルーティング。 - mitmproxy — プライバシーの主張を測定に変えるツール。