What your AI coding tools actually send off your machine
Check what a coding agent uploads before you point it at real work, and set the controls that keep your source and your credentials from leaving quietly.
on this page · 0 / 0 checked
You installed a coding agent, pointed it at a client repository, and got useful work back. The thing you did not do, because almost nobody does, is check what left the machine while that was happening. There was a toggle somewhere about improving the model. You switched it off and moved on.
That toggle governs one thing: whether the vendor may keep what you send and train on it. It says nothing about how much your machine sends, over which connections, or whether files you explicitly told the agent not to open travelled anyway. Those are separate mechanisms built by separate teams, and they can come apart. This guide is for solo operators and small teams who run agents against real client code with no security team to ask. If your traffic already goes through a company egress proxy with logging, you know most of what follows.
A privacy toggle governs retention, not transmission
In July 2026 a researcher publishing as cereblab put xAI’s Grok Build CLI, version 0.2.93, behind mitmproxy and read the decrypted request bodies [1]. Two outbound channels showed up. The first was the model turn, POST /v1/responses, carrying file contents the agent had actually read. The second was POST /v1/storage, which uploaded the repository as a git bundle in roughly 75 MB chunks, destined for a Google Cloud Storage bucket named grok-code-session-traces [1].
The sizes are the part worth remembering. On a 12 GB test repository, the model channel carried 196,705 bytes across 5 requests. The storage channel carried 5,476,228,005 bytes, about 5.10 GiB, across 82 uploads. That is roughly 27,800 times more data than the visible feature required. The two channels were also independent of each other: 76 of the storage uploads returned HTTP 200 at or after the first 429 came back from the model endpoint, so a quota that stopped the work did not stop the shipping [1].
Then the controls. Switching off “Improve the model” did not stop the upload; the settings endpoint kept returning trace_upload_enabled: true [1]. A canary file planted at src/_probe/never_read_canary.txt, in a session whose entire prompt was an instruction to reply OK and open nothing, came back verbatim from the recovered bundle, along with the repository’s full commit history [1]. Test credentials in a .env file appeared unredacted in both channels [1]. Since publication xAI has disabled the upload server-side with a disable_codebase_upload: true flag and added a /privacy opt-out, and Elon Musk has publicly committed to deleting the data already uploaded, which the author records as not yet confirmed complete [1].
The specific bug is fixed and the specific version is old. The shape of it is not. A product can expose exactly one privacy control, label it honestly, honour it precisely, and still open a second connection that the control was never wired to. An instruction or an exclusion that stops an agent reading a file stops it reading that file into the conversation. Neither is a promise about what a different subsystem in the same binary uploads.
The vendors document this, in different units, in different places
Read the page for the tool you use and the tier you actually pay for, because the answers are not comparable across products.
Claude Code splits its outbound traffic into named pieces. Usage metrics are on by default on the Claude API and “never include your code, prompts, or file paths”; DISABLE_TELEMETRY=1 turns them off. Error reports go to a third-party error tracking service, with known secret patterns, file paths and email addresses redacted first; DISABLE_ERROR_REPORTING=1 turns those off. The /feedback command sends a copy of your conversation history including code, and those transcripts are retained for 5 years. CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC covers the set. Retention for Team, Enterprise and API accounts is 30 days as standard; consumer accounts get 30 days unless you allow your data to be used for model improvement, which moves you to 5 years. Transcripts are also written to your own disk in plaintext under ~/.claude/projects/ for 30 days by default, adjustable with cleanupPeriodDays [3].
Codex documents containment rather than telemetry. The defaults are --sandbox workspace-write --ask-for-approval on-request, and inside that sandbox the agent runs with network access turned off unless you set network_access = true. The other sandbox settings are read-only and danger-full-access, the last aliased as --yolo [6].
Cursor documents storage. With Privacy Mode enabled, “none of your code will ever be stored by us or any third-party”. Every request routes through Cursor’s backend even when you supply your own API key, because that is where the final prompt is assembled. Codebase indexing uploads your code in small chunks to compute embeddings, and while the plaintext “ceases to exist after the life of the request”, the embeddings plus hashes and obfuscated file names stay in Cursor’s database [4].
Gemini CLI documents account tiers. On an individual Google account through Gemini Code Assist, and on the unpaid Gemini Developer API tier, prompts, answers and related code are collected and may be used for training. On Code Assist Standard and Enterprise, the paid Developer API and Vertex AI, they are not. One setting, Usage Statistics, covers the optional collection [5].
Four products, four different axes: telemetry channels, sandbox scope, storage lifetime, account tier. A document tells you what a vendor has committed to. It does not tell you what the binary on your laptop did last Tuesday.
One afternoon with a proxy answers what the settings page cannot
mitmproxy is a free and open source interactive HTTPS proxy, MIT licensed, built to intercept, inspect, modify and replay web traffic. It ships as a terminal tool, as mitmweb, a graphical interface close to the DevTools view you already know from Chrome, and as mitmdump for scripted capture [7]. That is the whole toolkit you need.
The procedure is short. Create a throwaway repository with nothing real in it. Seed it with unique canary strings, including fake credentials in a .env file and a file whose only job is to be the one you tell the agent never to open. Install and trust the proxy’s certificate authority, start the capture, point the agent at the repo through the proxy, and give it a task so small that the honest traffic should be tiny. Then read the capture: the list of distinct endpoints, the byte total per endpoint, and whether your canary strings appear anywhere you did not expect. cereblab’s reproduction harness walks through exactly this sequence, ending by finding the git bundle in the capture, cloning it, and recovering the never-read canary [2].
The ratio is the tell. A task that read 3 small files should not have moved gigabytes. You do not need to understand every request to notice that one channel is four orders of magnitude larger than the work you asked for. That published harness describes itself as version-specific to grok 0.2.93, with behaviour that may change [2], and yours will be the same, which is the argument for repeating the capture after a tool’s next major version rather than treating one clean result as permanent.
Containment is cheaper than trust
The most reliable control is the one that does not depend on a vendor’s intentions at all. Run an unfamiliar agent inside a container or virtual machine whose outbound network is restricted to the model endpoint you expect it to call, and give it a copy of the repository rather than the working tree you actually use. An undisclosed upload channel then fails as a blocked connection you can see, rather than succeeding quietly.
This is not an exotic setup, and the vendors themselves treat it as normal. Codex ships with network access off inside its default sandbox, so a command the agent spawns cannot reach the internet until you say so [6]. Claude Code’s cloud sessions send all outbound traffic through a security proxy for audit logging, and keep your GitHub credentials outside the sandbox entirely by brokering authentication through a proxy [3]. Those are the same two ideas, applied by the people who wrote the tool.
For a small team the practical version is a rule rather than infrastructure: a new coding agent gets its first week on a scratch clone in a restricted environment, and only graduates to the real repository after you have looked at its traffic once.
Secrets should not be in the tree the agent can reach
The most instructive detail of the Grok Build capture is that the instruction not to open any files was honoured where the model could be seen honouring it, and was beside the point for the upload, which took the whole repository regardless [1]. Treat every per-file exclusion, and every sentence in a prompt telling an agent to leave something alone, as a comfort feature. It governs what the model reads. It is not a guarantee about the wire.
The control that does hold is not having the credential in the directory at all. Inject secrets from your environment or a secret manager at run time, keep .env files outside the repository root, and give agents scoped, short-lived tokens rather than the keys you use yourself. If a credential is never on disk under the path the agent operates in, no upload channel can carry it.
History is the other half, and it is the half people forget. What went up in that capture was a git bundle, and cloning it reconstructed the repository including commits and files the agent had never touched [1]. A credential you committed in March and deleted in April is still reachable from history, so it is still in the bundle. GitHub’s push protection is the cheap preventive layer here: it blocks detected secrets in pushes from the command line, commits made in the GitHub UI, file uploads, REST API requests and interactions with the GitHub MCP server. Be aware of the escape hatch, though. By default anyone with write access can bypass a block by giving a reason, the offered ones being “It’s used in tests”, “It’s a false positive” and “I’ll fix it later”, unless you configure delegated bypass so a designated reviewer has to approve the request [8].
Rotate on exposure, not on confirmation
If a tool you ran against a real repository turns out to have shipped more than you thought, the only defensible response is to rotate the credentials that were reachable, immediately. Waiting for a vendor to confirm what was retained gets the sequence backwards. You cannot verify what already left your network, deletion claims are not independently checkable, and the window in which a leaked key is useful to someone else starts the moment it leaves, not the moment you find out.
The reason to do the arithmetic before anything goes wrong is that it is usually the thing that stops people rotating. A repository with a dozen live credentials spread across a payment provider, a mail sender, a database and three deploy targets is not a five-minute job, and if you first work that out during an incident you will start looking for reasons it might not be necessary.
credentials × minutes each, expressed in hours. Computed in the page; nothing is sent anywhere.
If that number is uncomfortable, it is an argument for fewer long-lived credentials rather than for more optimism about tooling.
What still goes wrong
A traffic capture is a snapshot of one version, on one machine, doing one task. It tells you what happened in that session and nothing about the next release. Some clients pin certificates, which defeats a local proxy without extra work, and a tool that batches or delays uploads can look clean during a short capture and send later. A clean result is evidence, not a guarantee, and treating it as a permanent clearance is how you end up surprised by version 0.3.
The redaction that vendors document is pattern-based, so it catches known key formats and misses your own. Claude Code’s error reports redact known secret patterns before sending [3], which is genuinely useful and says nothing about a credential in a house format that no scanner recognises. Retention policies are similar: they are commitments about what a company will do with what it holds, verifiable only by audit, and a 30-day window [3] is a shorter exposure than 5 years [3] rather than no exposure at all.
None of this covers the other half of agent risk, which is what the agent does rather than what it sends. Prompt injection through a fetched page, a command run against production, a dependency installed without you looking, all sit outside a traffic capture. And if you are running a regulated workload, a proxy session on your laptop is not a compliance control. Read your vendor’s terms, use the tiers and agreements that exist for that case, and treat this guide as the floor rather than the programme.
- 01cereblab — What xAI Grok Build CLI actually sends to xAI: a wire-level analysis (grok 0.2.93)gist.github.com
- 02cereblab — grok-build-exfil-repro (reproduction harness)github.com
- 03Anthropic — Claude Code data usagecode.claude.com
- 04Cursor — Privacy and Privacy Modedocs.cursor.com
- 05Google — Gemini CLI: Terms of Service and Privacy Noticegoogle-gemini.github.io
- 06OpenAI — Codex agent approvals and securitylearn.chatgpt.com
- 07mitmproxy — project homemitmproxy.org
- 08GitHub — About push protectiondocs.github.com