Here’s an unpopular take: the scariest part of the Grok Build CLI story isn’t the privacy angle. It’s that the same background upload mechanism that shipped your .env to a Google Cloud bucket also happens to hoard multi-gigabyte snapshots on your local disk. One bug, two blast radii. The security crowd is arguing about training data. Meanwhile, your laptop is quietly filling up.
If you ran grok in the last week, this post is for you. We’ll walk through what the wire analysis actually proved, which config flags kill the upload, and how to verify it yourself in about ten minutes. This is the practical version – not the hot take.
The scenario: you ran Grok in your home directory
Picture this. You’re trying Grok Build for the first time. The quickstart says to cd into a project directory. You cd ~ instead, because you want Grok to see “everything.” You type: “Explain what’s in this folder.”
According to an independent replication of the wire-level analysis, one comment on the gist reported 339 repo_state.upload.enqueued events across four repos – including one session where repo_path was the user’s entire home directory – before any mitigation. SSH keys. Password manager exports. Browser profiles. Whether that represents a worst-case configuration or default behavior, the mechanism to make it happen was real and confirmed across multiple machines.
What the wire capture actually showed – the numbers
The primary source is a public GitHub Gist by researcher cereblab, who routed Grok Build CLI 0.2.93 through mitmproxy on macOS (July 12, 2026). Two channels, running at once:
| Channel | Endpoint | Traffic on a 12 GB repo |
|---|---|---|
| Model turn | POST /v1/responses | ~192 KB |
| Background upload | POST /v1/storage → GCS | 5.10 GiB in 73 chunks |
On that 12 GB test repository, the model-turn channel moved 192 KB while the parallel /v1/storage channel moved 5.10 GiB across 73 chunks of about 75 MB each, all returning HTTP 200 – roughly a 27,800× ratio between what the model needed and what shipped off the machine. The destination is a Google Cloud Storage bucket named grok-code-session-traces, under paths of the form gs://grok-code-session-traces/repo_changes_dedup/v2/…
The most damning test wasn’t the size. It was the intent test. With the prompt “reply OK, do not read any files”, Grok still uploaded the entire repo as a git bundle; cloning that captured bundle recovered a file the agent was told not to open – src/_probe/never_read_canary.txt – with its unique marker verbatim, plus the full git history. That closed the “maybe it’s just caching context” argument.
Why the opt-out toggle didn’t work – and what actually does
Every tutorial about privacy in AI tools tells you to look for the “don’t use my data for training” checkbox. Grok has one. It’s labeled Improve the model. It does not do what you think.
Disabling “Improve the model” did not turn off the upload – /v1/settings still returned trace_upload_enabled: true. The training toggle governs whether xAI can use your data to train future models. The upload happens separately, for what the vendor describes as session continuity and debugging telemetry. Two different systems. One checkbox.
The community found two undocumented flags that actually stop it. Drop this into ~/.grok/config.toml (or %USERPROFILE%.grokconfig.toml on Windows, per the official settings docs):
[features]
telemetry = false
[telemetry]
trace_upload = false
mixpanel_enabled = false
[harness]
disable_codebase_upload = true
Or the equivalent env vars, which the community also surfaced:
export GROK_TELEMETRY_TRACE_UPLOAD=0
export GROK_TELEMETRY_ENABLED=0
Neither disable_codebase_upload nor trace_upload appears in official documentation – both were identified through community reverse-engineering on Hacker News. The mixpanel_enabled line was also flagged by community analysis but has no official docs entry. Treat all three as “observed to work in 0.2.93” – not a guaranteed contract. Run grok inspect after editing to confirm the config actually loaded (as of July 2026; the available settings may have changed since).
The reliability trap nobody’s talking about
Here’s where the story gets weirder. Even ignoring privacy, the upload mechanism has a plain old bug: ~/.grok/upload_queue stages roughly 3 GB snapshots per turn and, under load, can grow to tens of GB and exhaust the disk – a real bug independent of whether uploads succeed.
Translation: if you had a long agent session in a chunky repo, your ~/.grok/upload_queue directory could have quietly consumed 20-40 GB before you noticed. Check it. Delete anything stale:
# macOS/Linux
du -sh ~/.grok/upload_queue
rm -rf ~/.grok/upload_queue/*
# Then run inspect to verify the new config picks up
grok inspect
Pro tip: Set
GROK_HOMEto an ignored path outside your home directory before running Grok in anything sensitive. That way, even if a future version reintroduces trace uploads, staging files land somewhere you’re actively monitoring – not buried in~/.grokwhere you’ll find them when the disk fills up.
The July 13 mitigation – read this carefully
Something changed within 24 hours of the report going viral. The same researcher retested the same 0.2.93 client six times and observed zero /v1/storage uploads; the server now returned trace_upload_enabled: false and a new disable_codebase_upload: true. That’s a server-side flip, not a client patch.
Which is good news and bad news. Good: your existing binary probably isn’t uploading right now (as of July 13, 2026 – this may have changed since). Bad: a server-side flag can be re-enabled without a version bump. The official Grok Build changelog listed 0.2.98 as the latest documented release on July 12 but did not mention repository-upload behavior; updating is sensible, but the observed mitigation appears to be server-side and therefore needs a documented product guarantee, not only a version check.
Set the local config flags anyway. Belt, suspenders, and a second belt.
Advanced: verify it yourself with mitmproxy
If you don’t trust vendor blog posts (a reasonable stance this week), spend ten minutes reproducing the test on your own machine. It’s not hard.
- Install mitmproxy and add its CA cert to your OS trust store.
- Create a throwaway directory. Drop in a single fake file:
echo "CANARY-DO-NOT-UPLOAD-$(uuidgen)" > canary.txt. Do not put real code in this directory. - Export your proxy:
export HTTPS_PROXY=http://127.0.0.1:8080. Grok honors standard proxy env vars per the enterprise networking docs. - Run
grok -p "reply OK, do not read any files". - In the mitmproxy UI, filter for
/v1/storage. If you see zero requests, the mitigation is holding on your account. If you see chunks, disable the tool and file a ticket.
Bonus test: grep the captured request bodies for your canary string. That’s the same technique the original researcher used, and it’s the only way to know for sure.
Honest limitations of everything above
A lot of this analysis rests on one researcher, one CLI version, and a handful of independent replications. That’s decent evidence, not conclusive proof. A few things I don’t know and won’t pretend to:
- Whether the mitigation is global or staged per account. The retest was on one account.
- Whether enterprise Zero Data Retention mode blocks the /v1/storage channel specifically. ZDR routes through a dedicated service identity that skips logging at the inference layer, and no prompts, code, or responses are persisted at the inference layer for ZDR organizations (per xAI enterprise docs, as of July 2026) – but the incident happened at a separate storage endpoint, and the docs don’t explicitly cover that path.
- Whether files matching
.gitignorepatterns are always excluded. The published analysis didn’t fully test this. - Whether the
repo_changes_dedup/v2/path prefix means old snapshots persist in the bucket after retention. “Dedup” implies cross-session storage. Nobody outside xAI knows the retention window.
If you ran Grok Build on a real repo before July 12, assume any secrets in that repo – including in git history – may have been transmitted. Revoke and reissue API keys, database passwords, cloud tokens, signing secrets, and webhook credentials. Deleting the local file does not invalidate a credential already exposed.
FAQ
Is my code being used to train future Grok models?
Unknown. The wire analysis proved transmission and storage – not training. xAI’s policy says the “Improve the model” toggle governs training use. Whether the grok-code-session-traces bucket ever fed a training pipeline is unknowable from the outside.
I’m on an enterprise plan with ZDR – am I safe?
Probably safer, but don’t assume you’re fully covered without checking. ZDR is documented as an inference-layer control – it skips logging at the inference layer. The incident, though, involved a separate /v1/storage endpoint that the ZDR docs don’t explicitly address. Before running Grok in a regulated environment, ask your xAI rep in writing: does ZDR block /v1/storage traffic, and what is the retention policy on the GCS bucket? Get the answer in an email. A Slack message won’t hold up in a compliance review.
Should I just switch to a different coding CLI?
Probably not necessary. Every cloud coding agent sends code to a server – that’s how they work. The specific failure here was a background full-repo upload that ignored the training opt-out and wasn’t documented. It appears fixed. Add the config flags, run grok inspect, move on. That said, if you were already on the fence about Grok’s model quality, this is a reasonable moment to spend a week with Claude Code or Cursor and compare. The config fix takes five minutes either way.
Do this next
Open ~/.grok/config.toml right now. Paste in the four flags from the config block above. Run grok inspect. Then du -sh ~/.grok/upload_queue – if the number surprises you, delete it. You just spent five minutes fixing something that most Grok users don’t know is broken.