Grok CLIがxAIへ黙って送るもの:AIコーディングエージェントによるデータ流出のワイヤレベル解剖
Grok CLIがxAIへ黙って送るもの:AIコーディングエージェントによるデータ流出のワイヤレベル解剖
AIコーディングエージェントは我々のコードとファイルをどれだけ、どこへ送っているのか — 利便性のためのテレメトリか、制御不能なデータ流出か。
導入
クラウドベースのAIコーディングエージェントは、その性質上、ユーザーのコードをサーバーへ送信する。リモートのモデルがコードを読み修正するには、そのコードがモデルの走るサーバーへ到達しなければならないからだ。この事実そのものは新しくもなく、論争の対象でもない。問題は常に程度と宛先、そして告知の有無にある。どれだけ送るのか、どこにどれだけ長く残すのか、ユーザーはそれを知り同意したのか。この三つの問いへの答えが乖離するほど、「作業のための必須コンテキスト送信」は「制御されないデータ流出」へと滑り落ちる。
2026年7月12日(KST)にHacker Newsで1位に立った記事は、まさにその滑落を実測したレポートである。cereblabという筆名の分析者が、xAIのGrok build CLI(テストバージョン grok 0.2.93)を mitmproxy で中間者傍受し、このツールが実際に回線(wire)へ何を流しているのかをバイト単位で解剖した。538ポイント、229件のコメントが付いたこのスレッドの結論は単純ではない。Grok CLIはエージェントが読んだファイルだけでなく、リポジトリ全体をgit履歴まで含めて、エージェントがそのファイルを実際に読んだかどうかとは無関係に丸ごとアップロードする。.env のようなシークレットファイルもマスキングなしにそのまま送信される。宛先は具体的な名前を持つGoogle Cloud Storageバケットであり、この動作はデフォルトで有効になっている。そしてユーザーが設定でオフにできるオプトアウトは「モデル学習」にのみ関与するだけで、コードのアップロードそのものは止められない。
数日後、この話はさらに一段進む。あるユーザーがホームディレクトリでGrok CLIを実行したところ、ツールが repo_path をホームディレクトリ全体として捉え、その中身をGCSへ押し上げた事件が別スレッド(「Grok CLI uploaded the whole home directory to GCS」、438ポイント)として上がったのだ。利便性のためのテレメトリという名分と、ホームディレクトリ丸ごとアップロードという現実との距離が、この記事の主題である。以下ではまず、ワイヤレベル分析が実際に何を証明したのかを確認し(現象)、AIエージェントテレメトリの構造とそれが崩す信頼モデルを分析したうえで(深層)、実務者が今取り得る選択肢とこの事件が残した示唆を整理する(展望)。
現象:ワイヤレベル分析が明かしたもの
分析の方法論からおさえるべきだ。cereblabのアプローチは推測ではなく、再現可能なキャプチャに基づく。mitmproxy のローカル信頼CAをmacOSキーチェーンに埋め込みTLSをプロキシで終端し、HTTPS_PROXY と SSL_CERT_FILE 環境変数をかけてGrokの全HTTPSトラフィックを復号された状態で観察した。加えて各ファイルごとに固有マーカーを埋めた「カナリア(canary)」リポジトリを用いた。CANARY7F3A9-SECRET、CANARY-XR47P2-NEVERREAD といった一意な文字列がキャプチャされたトラフィックに現れれば、そのバイトが正確にどのファイル由来かを反駁不能に追跡できる。すべてのキャプチャは著者本人のマシンで本人のトラフィックを対象としており、シークレットはすべて偽のカナリアであったため、実際の資格情報が漏洩した事件ではない。
このキャプチャが暴いた送信経路は二つのチャネルに分かれる。チャネルAはモデル推論リクエスト、すなわち POST cli-chat-proxy.grok.com/v1/responses へ出るモデルターンである。ここにはエージェントが読んだファイルの内容が "messages":[…]"model":"grok-4.5" の形のJSONにシリアライズされて載る。チャネルBはコードベーススナップショットのアップロード、すなわち POST /v1/storage へ出る別個のストレージ経路であり、このエンドポイントが実際にルーティングする宛先が grok-code-session-traces という名前のGCSバケットである。二つのチャネルは目的も容量も異なる。
第一の発見はチャネルAに関するものだ。Grokがあるファイルを読むと、その内容がマスキングなしにxAIへ送信される。著者は48,070バイトの復号された /v1/responses リクエストボディから API_KEY=CANARY7F3A9-SECRET-should-not-leave と DB_PASSWORD=CANARY7F3A9-DBPASS をそのまま抽出して示した。.env や secrets.env も他のソースファイルと全く同じに扱われ、シークレット状のキーに対するいかなるリダクション(redaction)も観測されなかった。ただし著者はここで誠実な範囲限定を置く。「ファイルを読むな」というプロンプトを与えた対照実験では、読まれなかったファイルのマーカーはチャネルAのボディに現れなかった。つまりチャネルAの漏洩はエージェントが実際に読んだファイルに限定され、欠陥の核心は「読む行為」ではなく「シークレットファイルをマスキングなしに送信する」ことにある。
第二の発見がこのレポートの重心である。チャネルBはエージェントが何を読んだかとは無関係にリポジトリ全体をアップロードする。これを証明するため著者は、実在の cereblab_api リポジトリに CANARY-XR47P2-NEVERREAD-UNIQUE というマーカーを埋めた src/_probe/never_read_canary.txt を入れ、「正確にOKとだけ答え、どのファイルも読んだり開いたりするな」というプロンプトで実行した。それでもGrokはリポジトリ全体をgit bundleにまとめて POST /v1/storage → 200 でアップロードし、キャプチャされたbundleを git clone すると、開くなと指示したそのファイルがマーカーまでそのまま、しかも4コミットの全git履歴とともに復元された。この実験は別のCloudflare Workerリポジトリ(cereblab_auth)でも同じく再現され、そちらの未読カナリアもverbatimで復旧した。
容量の非対称性がこの主張をさらに固める。100%ランダムなファイルで埋め、エージェントが何も読まなかった12GBのリポジトリを対象としたキャプチャで、チャネルA(/v1/responses)の総送信量は196,705バイト(約192KB)にとどまった一方、チャネルB(/v1/storage)は5,476,228,005バイト、すなわち5.10GiBを押し上げた。約27,800倍の隔たりである。モデルが192KBで5GiB分の内容を飲み込めるはずはないので、この5.10GiBはモデルが読んだものではなくリポジトリスナップショットそのものだ。送信はリポジトリのサイズが大きくなるほど戦略を変えながら続いた。数百MB区間では数MB単位のチャンクで、3GB区間では POST /v1/storage/multipart/init の後 PUT storage.googleapis.com/grok-code-session-traces/multipart/<id> でGCSへ直接PUTする方式で、12GB区間では約75MBのチャンク73個(5.10GiB)がすべてHTTP 200で成功した。失敗したストレージリクエストは一つもなく、唯一の非200レスポンスはモデルエンドポイント側の使用量クォータ(402 Payment Required、429 Too Many Requests)のみだった。言い換えれば、コードアップロードにはサイズ上限がなく、上限がかかるのはモデル使用量だけである。
第三の発見は宛先と持続性だ。バイナリから strings で抽出した文字列には grok-code-session-traces、storage.googleapis.com、そして「Uploading bytes to GCS via proxy」が現れ、アップロード機構は xai-data-collector という1st-party製Rustクレートである。アップロード直前にステージングされた metadata.json は各ファイルに gs://grok-code-session-traces/repo_changes_dedup/v2/…/sha256_… の形の宛先 fileId を付与する。つまりツリー全体が、読まれなかったファイルまで含めて、コンテンツアドレス化され名前の明示されたGCSバケットへ上がる。これは送信後に揮発するコンテキストではなく、特定のバケットに持続(persist)されるデータである。
オプトアウトがこの流れを止められないという点が最後の発見だ。著者が設定で「Improve the model」をオフにして再実行したときも、Grokは依然としてリポジトリ全体をgit bundleで上げ、サーバーがCLIへ返す /v1/settings レスポンスはそのまま "trace_upload_enabled": true、"upload_enabled": true、"session_registry_enabled": true(そしてファイルあたり上限 "max_upload_file_bytes": 1073741824、1GiB)を返した。学習同意をオフにするスイッチと、コードアップロードをオフにするスイッチが、そもそも別物なのだ。Hacker Newsであるユーザーは原文を引用しつつ、読んだファイルの内容をシークレット .env まで含め検閲なしにそのままxAIへ送信するこの動作が「史上最も成功した大規模監視キャンペーン」に近いという趣旨で指摘する。別のユーザーは「リポジトリ全体が、エージェントが何を読むかとは無関係に、コンテンツとgit履歴ごとアップロードされる」という一文をそのまま引き、イーロン・マスクなら後発を追い上げるためこの種のことをやりかねないと予想はしていたが、これほどとは非常に憂慮すべきだという趣旨で指摘する。
深層:AIエージェントテレメトリの構造と信頼の問題
技術的にはリポジトリ全体を上げることにそれなりの理由があり得る。Hacker Newsのある論者は、モデルが「思考(thinking)」段階でクライアントへ戻って実際のツール呼び出しをせずとも、サーバー側でコードベースを直接覗けるようにするためだ、というのが一つの動機かもしれないという趣旨で指摘する。ラウンドトリップを減らせばレイテンシが縮み、エージェントの性能がよくなる。これがネイティブランナーがAPIを直接叩くオープンハーネスより速く滑らかである理由でもある。ここに明白なトレードオフがある。リポジトリをサーバーへ先に丸ごと上げておけば能力と速度を得る代わりに、ユーザーのコード全量がベンダーのストレージに常駐する。問題は、このトレードオフの一方の項をユーザーが知りもせず、選びもしないままデフォルトで強いられた点にある。
著者自身がこの地点で反論を先取りする。「クラウドAIツールがコンテキストを送るのは正常だ」という反駁は正しく、彼も認める。いかなるクラウドエージェントも作業をするにはコードをサーバーへ送らねばならない。彼が指摘する新しい三つのデルタは次だ。第一に、シークレットファイルがマスキングなしに送信される。第二に、その内容が一時的に処理されて終わるのではなく、名前の明示されたGCSバケットに持続保存される。第三に、このアップロード機構がCLIのインストールスクリプトやクイックスタート資料に現れておらず、デフォルトで有効になっている。xAIの消費者向け規約はモデル改善のためのデータ使用を広く告知しオプトアウトを提供するが、「学習にデータを使う」という包括的告知が「あなたのリポジトリが grok-code-session-traces へ常時アップロードされる」という具体的機構の告知と同じではない。広い告知と具体的告知のこの乖離が信頼問題の出発点である。
より深い層の問題は、ベンダーが提供する制御手段が実際の被害とかみ合わない(orthogonal)点だ。事件の後xAIが追加した /privacy オプトアウトを著者が回線で検証してみると、それは送信されたデータの**保存(retention)を調整する設定にすぎず、何が送信(transmission)**されるかを止めるスイッチではなかった。ユーザーの手にあるレバーは「あまり長く保管しない」なのに、当の懸念の本体は「そもそも出ていく」にある。制御手段の意味論と被害の意味論がかみ合わないとき、オプトアウトUIは安心を売りながら危険はそのまま残す。これが「利便性のためのテレメトリ」が「制御不能な流出」へ滑る正確な地点だ。制御が形式上は存在しつつ実効的には作動しない構造である。
ここにプライバシーと無関係な信頼性の欠陥も重なる。著者は ~/.grok/upload_queue が毎ターン数GB規模のスナップショットをステージングし、負荷状況では数十GBに膨れてディスクを枯渇させ得ると報告する。データが出ていくという事実とは別に、出ていくためにローカルへ積むキュー自体がユーザーのディスクを脅かすバグだ。ツールがユーザーの資源をユーザーの制御外で消費するという点で、これはプライバシー問題と同じ根を共有する。
そして数日後のエスカレーションがこの構造の最悪を実演した。あるユーザーがホームディレクトリでGrok CLIを走らせ、repo_path がホームディレクトリ全体として捉えられ、その中身がGCSへ上がった。Hacker Newsの反応は二つに割れた。一方はツールを信頼の問題として見る。ある論者は、リモート推論を使ういかなるAIエージェントもデフォルトで何でも読むと仮定すべきであり、下位ディレクトリへ「制限」したとしてもその仮定を保つべきだという趣旨で指摘する。別の論者は、この種のツールがネイティブ・独占ランナーの形で配布されるためプライバシー面で危険であり、次のアップデートにどんな「秘伝のソース」が加わるか分からないので、opencodeのようなオープンハーネスでAPIを直接叩くほうが安全だ、ただしその場合ネイティブランナーほどの性能は決して出ないというトレードオフを併せて挙げる趣旨で指摘する。さらに別の者は、この種のツールをVM内で走らせる理由がここにあり、curl … | bash には(正当に)懐疑的な人々がなぜこの種のツールはそれほど素直に受け入れたのか訝しいという趣旨で指摘する。
もう一方は責任をユーザーへ返す。ホームディレクトリでエージェントを走らせたこと自体が誤りであり、リモート推論を使う以上コードベースへの完全なコンテキストを与えるのが元々の要点ではないか、という反論だ。この二陣営の対立は結局、信頼モデルの問題へ収束する。今日コーディングエージェントを使うということは、ハーネス、モデル、プロバイダそれぞれに自分のコンピュータ・コード・事業を託すということであり、良い状態ではないが現実がそうである以上慎重に選べ、という論評がこの点を要約する。ただし「慎重に選べ」という助言は、ツールが何をするかをユーザーが検証できるときにのみ実効を持つ。インストール資料に現れずデフォルトで有効な機構の前で、大半のユーザーにとって「慎重な選択」の根拠はそもそも存在しなかった。cereblabのレポートが価値を持つ理由は、まさにその検証の根拠を回線から直接汲み上げた点にある。
展望・実務への示唆
xAIの対応は、圧力が実効を生んだことを示す。原文の2026-07-14の更新によれば、xAIは問題のアップロードをサーバー側で無効化し(disable_codebase_upload: true)、先に述べた /privacy オプトアウトを追加し(ただし著者の検証の結果これは保存設定にとどまる)、イーロン・マスクが既にアップロードされたデータを全削除すると公に約束した(削除完了はまだ確認されていない)。ここで注目すべきは修正の形だ。コード変更ではなくサーバー側フラグの切り替えで動作が変わったということは、同じ方式でいつでも巻き戻せることを意味する。ユーザー信頼の観点で、リモートフラグに制御されるデフォルト動作は根本解決ではなく猶予に近い。
実務者が今取り得る制御手段はいくつかの筋に分かれる。最も直接的なのはクライアント設定で、Hacker Newsのある論者は ~/.grok/config.toml に [harness] disable_codebase_upload = true を入れるのがリポジトリアップロードをオフにする最も単純な方法だという趣旨で指摘する。しかしベンダーが提供するスイッチを信頼できないなら、制御はツールの外に置くべきだ。ある論者はコーディングツールをLLMプロバイダから分離し bubblewrap でサンドボックス化して、作業ディレクトリだけを読ませ .git を読み取り専用に、機微なディレクトリは空ディレクトリとしてマウントして隠し、隔離されたネットワーク名前空間からHTTPプロキシを通してのみインターネットへ出るが特定のLLMプロバイダホストだけを許可しツール自身のホストは除外する構成を紹介する。要するにプロバイダへ向かうトラフィックは許可しつつ、ツールの自前テレメトリホストへ向かうトラフィックは遮断するのだ。別の者は podman コンテナでエージェントを走らせ作業が終わればgitパッチだけをホストへ戻す方式を、他の者はVM隔離を提示する。共通の原則は明確だ。決してホームディレクトリでエージェントを走らせず、ネットワーク流出経路をホワイトリストで制御し、信頼をベンダーの約束ではなく自分が検証可能な境界に置く。
規制の層も残る。Hacker Newsでは、この種の無差別なコード流出がGDPRのような欧州規制とどう両立するのかへの疑問が提起された。企業ユーザーであれば、コードが学習に使われず保存もされないことを契約で保証するZDR(Zero Data Retention)プランの有無とその範囲が、ツール選定の一次基準となるべきだ。しかしこの事件が示したのは、消費者ログインのデフォルトではそうした保証が作動しなかった点である。個人開発者や小規模チームは契約的保護の死角に置かれる。
より広く見れば、この事件はGrokだけの問題ではなくコーディングエージェント全般のガバナンス問題だ。反復されるアンチパターンは「デフォルトで有効 + 実効のないオプトアウト」である。デフォルトが最大収集で、ユーザーに与えられたオプトアウトが当の被害の本体(送信・持続)に手が届かないなら、同意は形式にすぎない。逆方向の設計原則は明快だ。シークレットへのクライアント側リダクションをデフォルトにし、コードベースの持続アップロードはオプトインへ転換し、機構をインストール資料に明示し、ツールの動作をユーザーが回線で監査(audit)できるようにすることだ。cereblabの方法論そのもの — mitmproxy の中間者キャプチャとカナリアマーカー、バイナリ文字列の調査、git bundleの復元 — が、この監査が特殊技術ではなく誰もが再現できるルーチンになるべきことを示唆する。性能のためにネイティブランナーを選ぶにせよ、監査可能性のためにオープンハーネスを選ぶにせよ、その選択はツールが何をするかを検証できるときにのみ合理的である。
結論
リード質問へ戻る。これは利便性のためのテレメトリか、制御不能なデータ流出か。ワイヤレベルの証拠が指す答えは後者にはるかに近い。クラウドエージェントがコードを送信するという事実そのものは正常だが、grok 0.2.93 のデフォルト動作には正常の範囲を外れる三つのデルタがあった。シークレットの無マスキング送信、名前の明示されたバケットへの持続保存、そしてインストール資料になくデフォルトで有効な機構である。決定的に、ベンダーが提供した制御手段(学習オプトアウト、後の保存設定)は被害の本体(送信と持続)とかみ合っていなかった。ユーザーがオフにできるものとユーザーがオフにしたいものが異なるとき、「利便性のためのテレメトリ」というフレームは崩れる。ホームディレクトリ丸ごとアップロードは、その崩壊の極端な一例にすぎなかった。
この事件が残した実務的教訓は、信頼を約束ではなく検証の上に築けということだ。ベンダーのオプトアウトが何をオフにするのか、ツールがどのホストへ何を送るのかを回線で確認できないなら、制御はツールの外のサンドボックスとネットワーク境界に置くべきだ。xAIがサーバーフラグでアップロードをオフにしたという事実は圧力が通じたことを示すが、フラグでオンにしたものはフラグで巻き戻せる。コーディングエージェントが開発ワークフローの基本インフラになりつつある今、必要なのはベンダーの善意ではなく、オプトイン・リダクション・明示的告知・回線監査可能性という構造的なデフォルトである。トレードオフは常に存在する — ネイティブランナーの性能とオープンハーネスの監査可能性、デフォルトテレメトリの利便性と明示的同意の制御。ただしそのトレードオフをユーザーが知り選べるときにのみ、それはトレードオフという名に値する。
出典:
- What xAI’s Grok build CLI sends to xAI: A wire-level analysis (cereblab) — https://gist.github.com/cereblab/dc9a40bc26120f4540e4e09b75ffb547
- Hacker News 議論スレッド (objectID 48877371) — https://news.ycombinator.com/item?id=48877371
- エスカレーション: “Grok CLI uploaded the whole home directory to GCS” (objectID 48892468) — https://news.ycombinator.com/item?id=48892468
- xAI Privacy Policy — https://x.ai/legal/privacy-policy
- xAI Consumer Terms of Service — https://x.ai/legal/terms-of-service