Here’s the thing everyone’s getting wrong about the Grok CLI uploaded home directory to GCS story: the scandal isn’t that a coding agent phones home. Every cloud coding agent does. The scandal is that Grok Build uploaded stuff it was explicitly told not to read, staged multi-gigabyte copies on your local disk while doing it, and hid the whole mechanism behind a settings toggle that never controlled it in the first place.
If you ran grok anywhere near your home folder recently, this walkthrough is for you. What actually happened at the wire level. How to audit your own machine in under ten minutes. And the three concrete things worth doing before Monday.
The scenario: you cd’d into ~ and typed “explain this folder”
Picture how this actually plays out. You install Grok Build to try it. The quickstart says run it in a project directory. You’re impatient, so you cd ~ because you want Grok to “see everything” and help you clean up. You type: “Explain what’s in this folder.”
Under the model-turn channel – the part you’d expect – Grok reads a few files, packages them into a prompt, sends them off. Fine. That’s any LLM API call.
But a wire-level teardown by researcher cereblab, routed through mitmproxy on macOS (as of early July 2026), showed a second channel running in parallel. The client packages the workspace and uploads it via POST /v1/storage. Even with the prompt “reply OK, do not read any files,” Grok uploaded the entire repo as a git bundle – and cloning the captured bundle recovered a file the agent was told not to open, verbatim, plus the full git history. The file-read deny stopped the agent from quoting the file in chat. It did not stop the upload.
Translate that to “I ran it in ~“: your dotfiles, SSH configs tracked in a git repo, notes, side-project .env files. Anything under a tracked git directory in your home tree was fair game.
What the numbers actually say
| Channel | Endpoint | Data moved (12 GB repo) |
|---|---|---|
| Model turn (expected) | POST /v1/responses | 192 KB |
| Background storage (hidden) | POST /v1/storage | 5.10 GiB, 73 chunks, all HTTP 200 |
27,800× more data than the model actually needed – shipped to a Google Cloud Storage bucket named grok-code-session-traces, at paths like gs://grok-code-session-traces/repo_changes_dedup/v2/.... Not AWS S3, not xAI infrastructure the way most users would guess.
The .env problem is real. A tracked .env file containing fake API_KEY and DB_PASSWORD values appeared unredacted – in both the model request and a session-state archive uploaded via POST /v1/storage. No masking, no client-side scrubbing. Straight through.
One more thing the numbers don’t show: the “Improve the model” toggle. Turning it off did nothing. The server still returned trace_upload_enabled: true and the transfer proceeded. That toggle governs training consent. It was never wired to control whether code leaves your machine.
Audit your machine in five minutes
Skip the panic. Someone already built the tool. The MaydayV/grok-upload-audit script is plain Python – reads your local Grok logs, figures out what left your machine.
git clone https://github.com/MaydayV/grok-upload-audit
cd grok-upload-audit
python3 scripts/grok_audit.py
The report comes back in three tiers: confirmed uploaded, attempted-only, and touched-with-no-upload-evidence. That last distinction is the one that matters – it’s the difference between “rotate everything” and “rotate these three credentials.” The tool gets there by parsing ~/.grok/logs/unified.jsonl for upload events, then cross-referencing trace.upload.decision records: if upload was enabled with trace_upload_source: "remote" while every local opt-in field is null, that’s the smoking gun that xAI turned it on server-side, not you. Secret leakage check runs separately – matches your .env values against local Grok data, reports only key names and hit counts, never the values themselves.
Two things worth noting about the design. First, the scanner refuses to treat $HOME as a repository – it won’t sweep your entire home folder, which is a quietly telling choice given the story that inspired it. Second, running the audit before any mitigation matters: if you later file a GDPR or CCPA deletion request, the SHA-256 evidence package is your use. And it depends on those logs still existing.
Before you run any mitigation: snapshot
~/.grok/to a separate directory. The audit tool’s evidence package requires those logs intact.
Prove it yourself with mitmproxy
Audit report ambiguous? Or you want to test whether the mitigation is holding on your account right now – not someone else’s from a July 13 retest. Do what cereblab did.
- Install mitmproxy (
brew install mitmproxyon macOS, or pip). - Run it once to generate the CA cert, then trust it. On macOS:
sudo security add-trusted-cert -d -p ssl -p basic -k /Library/Keychains/System.keychain ~/.mitmproxy/mitmproxy-ca-cert.pem– see the official mitmproxy certificate docs for Linux and Windows. - Make a throwaway directory. Drop in one canary:
echo "CANARY-$(uuidgen)" > canary.txt. No real code. - Export the proxy:
export HTTPS_PROXY=http://127.0.0.1:8080. - Run
grok -p "reply OK, do not read any files". - Filter mitmproxy for
/v1/storage. Zero requests: server-side mitigation is holding for you. Any chunks: disable the tool and file a ticket.
The canary technique is the whole reason we know about this at all. It’s also the only way to keep knowing – because, as the next section explains, the fix isn’t in the client binary.
The mitigation is a flag, not a patch
This is the part almost no coverage is stressing. The same researcher retested the same 0.2.93 client on July 13, 2026 – six runs, zero /v1/storage uploads. The server now returns trace_upload_enabled: false and a new disable_codebase_upload: true. No client update. No version bump. A flag flipped server-side.
Which means: your binary probably isn’t uploading right now. But a server-side flag flips back without a changelog entry, without a notification, without you knowing. The official changelog listed 0.2.98 as the latest release on July 12, 2026 – no mention of repository-upload behavior anywhere in it.
The audit script’s remote-flag detection – checking whether trace_upload_source is "remote" while local consent fields are null – is the durable defense here. Not any specific version number.
The disk bug nobody’s connecting to the privacy story
While the security discussion argues about training data, there’s a second blast radius sitting quietly on your SSD. ~/.grok/upload_queue stages roughly 3 GB snapshots per turn and, under load, can grow to tens of GB – exhausting the disk entirely. This is a real bug, independent of whether uploads succeed or fail.
One background mechanism, two problems. It ships your workspace to a bucket and hoards a staged copy locally. If your MacBook ran out of space after a week of Grok experiments and you couldn’t figure out why – run du -sh ~/.grok/upload_queue. If the number surprises you, delete it.
Honest limitations of this whole story
Most of the analysis rests on one researcher, one CLI version (0.2.93), and a handful of independent replications. Decent evidence. Not conclusive proof across every account and configuration. The researcher was explicit: this is a serious finding, but it does not prove that xAI trained on the code, that every Grok Build account behaves identically, or that untracked files are always swept up.
There’s a live discrepancy nobody’s resolved. Enterprise deployment docs say storage.googleapis.com is needed only for the shell installer and updates – full stop. Consumer analysis observed codebase artifacts routed to a GCS bucket. Those two statements may describe different account paths, or the docs may simply be wrong. Nobody outside xAI can tell you which side of that line your account is on.
FAQ
Does deleting ~/.grok un-upload my code?
No. Local deletion doesn’t touch anything already sitting in the grok-code-session-traces bucket. Rotate any credentials Grok could have touched, then delete the local directory.
I used Grok Build only in a small toy project – am I fine?
Probably, with one real caveat. If your “toy project” happened to inherit a global .gitconfig that pulls in a ~/.env, or if you ever ran grok one directory above where you meant to, the full-bundle upload would have swept in whatever tracked git tree existed above you. Run the audit script – it’ll tell you exactly which repositories were packaged and what the blast radius actually was. That’s the only way to know for sure.
Is Claude Code or another coding agent safer?
Different tools, different risks – and honestly, this question is hard to answer fairly without a similar wire-level audit on each one. What’s specific to Grok Build here is the combination: a git-bundle upload scoped beyond what the agent reads, a storage toggle that doesn’t control egress, and a server-side flag as the only current fix. Whether other agents have comparable hidden channels is an open question.
Do this now
Clone the audit repo, run the script against ~/.grok/logs/unified.jsonl, read the three-tier report. If anything shows up under “confirmed uploaded,” open your password manager and start rotating – API keys, DB passwords, cloud tokens, signing secrets, webhook credentials, in that order. The five minutes you spend on the audit is the difference between guessing and knowing.