AI coding assistants need access to code. That is not exactly a revelation.
You cannot ask a cloud-hosted model to debug a function without eventually showing it the function. You cannot expect it to understand an architecture while hiding every file behind a tiny black privacy rectangle. Some information must leave the computer, because the expensive artificial brain doing the thinking lives somewhere inside a data centre.
That is the deal.
What is considerably less obvious is that installing a coding assistant in a Git repository might cause it to package the entire repository – including files it never opened and the project’s commit history – and upload the result to cloud storage.
Yet that is precisely what an independent analysis of xAI’s Grok Build CLI version 0.2.93 found.
The analysis does not rely on vague bandwidth graphs, assumptions about cache directories, or somebody spotting a suspicious hostname in netstat. Researcher Cerebralab routed Grok’s traffic through mitmproxy, captured the decrypted HTTP requests, inserted unique canary strings into test files, and reconstructed the repository from the data that left the machine.
The result is less “AI assistant requests relevant context” and more “background process quietly performs an off-site backup nobody asked for.”
Two very different data pipelines
The investigation identified two separate ways in which local code was sent to xAI.
The first is the expected model interaction. When Grok reads a file to answer a question, the contents are included in requests to:
POST cli-chat-proxy.grok.com/v1/responsesThis is how most cloud-based coding assistants work. The model cannot reason about code it has never received.
There is still a serious problem here: in the test, a tracked .env-style secrets file was transmitted verbatim. Canary values stored under names such as API_KEY and DB_PASSWORD appeared unredacted in the request body. The same values also appeared inside a session-state archive sent through Grok’s storage endpoint.
The test used fake secrets, and the researcher carefully avoids claiming that Grok lacks every possible secret-redaction mechanism. The canaries were recognisable test strings rather than realistic high-entropy API keys. Nor did the original test establish that a Git-ignored .env file would be included.
What it did establish is that a tracked secrets file read by Grok was sent exactly as written.
That is already enough to make any security engineer reach slowly for the network cable.
The second pipeline is much harder to justify.
Separately from the files selected as model context, Grok Build created a Git bundle representing the repository and uploaded it using:
POST cli-chat-proxy.grok.com/v1/storageThe captured metadata associated objects with a Google Cloud Storage bucket named:
grok-code-session-tracesThis bundle contained tracked files and the repository’s reachable commit history. It was not merely a list of filenames, a hash index, or some local cache that looked scary when viewed out of context. The researcher extracted the upload body, found the Git bundle, and cloned it.
That is about as direct as evidence gets.
“Reply OK. Do not open any files.”
The most important part of the reproduction is its almost comically simple prompt:
Reply with exactly: OK. Do not read or open any files.A unique canary marker had been placed inside:
src/_probe/never_read_canary.txtGrok followed the instruction at the model level. It did not open the file as part of the conversation.
The background upload mechanism apparently had its own interpretation of personal boundaries.
The complete Git bundle was still transmitted through /v1/storage, and the server returned HTTP 200. Cloning the captured bundle recovered the supposedly untouched file, its unique marker and the repository’s commit history. The same experiment was then reproduced against a second, unrelated repository with a different canary.
This distinction matters enormously.
When a coding agent asks to read a file, the user may see a permission prompt. The user can deny access. Grok will then report that the read was blocked by policy.
That looks reassuring.
Unfortunately, the permission controls govern what the agent may read into its conversational context. They do not necessarily govern what the CLI’s separate data-collection and repository-upload machinery may package and transmit.
The reproduction tested this explicitly. A deny rule could prevent Grok from reading secret.txt, while the same tracked file remained present in the uploaded Git bundle.
The security interface therefore protects one path while leaving another path open behind it.
It is the software equivalent of fitting a high-security lock to the front door while a removal company quietly empties the house through the garage.
Five gigabytes of “context”
Someone will inevitably argue that uploading repository data is necessary for an advanced coding agent. Perhaps Grok needs a server-side index. Perhaps remote session restore requires repository state. Perhaps the model has a very holistic approach to answering “OK.”
The volume test makes that defence rather difficult.
The researcher created a repository containing approximately 12 GB of random, incompressible data. During the captured run, the ordinary model-response channel sent a total of about 192 KB. Meanwhile, the storage channel successfully uploaded approximately 5.10 GiB before the test was stopped, using 73 chunks of roughly 75 MB each.
Every captured storage request returned HTTP 200.
The storage traffic was around 27,800 times larger than the model-turn traffic. The upload continued even after model requests began receiving quota-related HTTP 402 and 429 responses. In other words, Grok could no longer provide useful model responses, but it remained remarkably enthusiastic about transferring the repository.
The test was terminated before the entire 12 GB repository finished uploading, so it does not prove that all 12 GB would have completed successfully. It does prove that more than five gigabytes left the computer, that the storage service accepted the chunks, and that the transfer was unrelated to the tiny amount of data actually provided to the model.
That is not conversational context.
That is bulk collection.
Git history makes this considerably worse
Uploading the working tree would already be concerning. Uploading a Git bundle adds another layer of unpleasantness.
Git history frequently contains things that are no longer visible in the current checkout: deleted configuration files, abandoned implementations, internal hostnames, customer references, accidentally committed credentials, private certificates and code that was removed for legal or licensing reasons.
Developers are repeatedly warned that deleting a secret from the latest commit does not remove it from Git history. That advice becomes particularly relevant when a coding assistant silently bundles that history and transfers it elsewhere.
The exact contents of a Git bundle depend on the references and objects included, so this should not be exaggerated into a claim that every unreachable object or local reflog is necessarily uploaded. The captured bundles did, however, contain the tested repositories’ tracked files and full visible commit histories. One reconstructed test bundle contained four commits and 47 files.
For a commercial project, that history may be more sensitive than the current source tree.
It can document how a security feature evolved, reveal code that has not yet been disclosed publicly, expose previous customer-specific modifications, or retain a credential everyone thought had been “removed months ago.”
A coding tool should not treat that history as incidental telemetry.
The consent-shaped hole
xAI can reasonably argue that Grok Build is a cloud service and that users should expect code to be transmitted.
That argument covers files deliberately supplied as model context.
It does not automatically justify uploading every tracked file and the repository’s history, independent of what the agent needs for the requested task.
Meaningful consent requires the user to understand what is happening. A clear first-run message could have said:
Grok Build uploads a complete Git bundle of this repository,
including tracked files and commit history, to xAI cloud storage
for session tracing and repository-state features.
Continue? [y/N]
That would at least provide a recognisable decision.
Instead, the public product page invites developers to run a one-line installer and says Grok Build works with “any codebase.” It describes code search, Git integration, session memory and remote features, yet it does not prominently tell users that starting the tool may trigger a complete repository upload. xAI’s enterprise documentation describes prompts and file content being assembled locally and sent for inference, while its public data-lifecycle description likewise does not clearly explain a separate full-repository Git-bundle pipeline.
The consumer terms are, predictably, broader.
They define input as potentially including code, files, folders and drives. They also grant xAI extensive rights to use, copy, store, process and transmit content submitted through the service. Users are made responsible for having permission to provide that material.
That may provide xAI with contractual arguments. It does not provide developers with a useful description of the CLI’s behaviour.
A paragraph inside general terms of service is not an adequate substitute for telling a developer that a background process is about to upload the complete history of the company repository they happen to be standing inside.
There is also an awkward responsibility problem. The terms tell users that they must possess the rights and permissions required to submit the input.
How can a developer make that judgement when the tool does not clearly identify what it is submitting?
A developer may have permission to send one function to an external model for analysis while lacking permission to upload the entire repository, its third-party components, historical customer code and old commits. Those are very different data-processing decisions.
Turning off model improvement did not stop it
Grok offers an “Improve the model” setting, which sounds like the sort of control a privacy-conscious user might disable before exposing private code.
In the original experiment, turning it off did not prevent the repository upload.
The server continued to report settings such as:
{
"trace_upload_enabled": true,
"upload_enabled": true,
"session_registry_enabled": true
}The researcher then captured another complete Git-bundle upload and recovered the never-read canary from it. The model-improvement setting appears to govern whether data may be used for product development or model training. It does not necessarily prevent transmission or storage required by other product features.
This is a technically defensible distinction and a user-experience disaster.
Most users do not divide privacy into separate philosophical categories of inference, tracing, session persistence, product analytics and training. They see a switch labelled “Improve the model,” turn it off, and reasonably assume the product will become less enthusiastic about retaining their private material.
Instead, the repository continued its cloud migration.
The research does not prove that xAI trained a model on the uploaded repositories. Transmission and storage were demonstrated. Training was not, and pretending otherwise would weaken a case that is already disturbing enough without embellishment.
The current status: paused, perhaps
The findings are specifically tied to Grok Build 0.2.93 on macOS ARM64 in July 2026.
At the time of writing, July 13, 2026, xAI lists version 0.2.98 as the latest release. Its public changelog contains no clear entry explaining the repository-upload behaviour, announcing a privacy incident, or identifying a specific fix for silent Git-bundle uploads.
There is, however, evidence of a remote mitigation.
A second tester independently confirmed the original 0.2.93 behaviour and found hundreds of local repo_state.upload.enqueued events across several repositories. On July 13, the same tester reported that a remote flag was now disabling trace uploads. The client still contained the upload functionality, but the server-provided configuration had apparently paused it.
That is good news in the same way that discovering the tap has finally been turned off is good news after finding your basement flooded.
A remotely disabled feature can potentially be remotely enabled again. There has been no clear public explanation of what data was retained, how long it will remain stored, which users or account types were affected, whether all regions received the same mitigation, or whether previously uploaded repositories will be deleted.
A silent server-side flag change is operational damage control. It is not transparency.
What Grok Build users should do
Anyone using Grok Build with private, commercial, customer-owned or otherwise sensitive code should treat the original behaviour as confirmed for version 0.2.93 and independently verify the behaviour of whatever version and account configuration they currently use.
A community-tested local configuration uses an explicit veto for the repository upload and disables telemetry and trace uploads:
[features]
telemetry = false
[telemetry]
trace_upload = false
mixpanel_enabled = false
[harness]
disable_codebase_upload = trueThe same hardening work recommends setting environment variables as an additional higher-priority layer:
export GROK_TELEMETRY_ENABLED=false
export GROK_TELEMETRY_TRACE_UPLOAD=falseThe independent tester reported that disable_codebase_upload = true prevented repository-state uploads even when another setting attempted to force them on. The telemetry settings blocked the separate session-trace pipeline. Configuration precedence and automatic updates complicate matters, so the accompanying hardening project includes verification probes rather than asking users to trust that a configuration file probably means what it says.
Keeping sensitive files out of Git also reduces what can appear in a repository bundle, but this is basic damage limitation rather than a solution. A secret committed two years ago may remain in history. A sensitive source file may be entirely legitimate inside the repository while still being prohibited from leaving the organisation.
For corporate environments, the safer immediate policy is simple: do not run unverified coding agents inside repositories containing material you are not authorised to upload.
That should have been obvious before the AI era. Apparently, we now need to say it louder because the upload button has become invisible.
Trust needs a diff too
The appeal of CLI coding agents is that they operate where developers already work. They can inspect a project, run tests, modify files and use Git without forcing everything through a browser.
That deep integration also gives them extraordinary access.
A browser chatbot knows what you paste into it. A terminal agent may see source code, shell history, credentials, environment variables, build artefacts, internal documentation and whatever else happens to be reachable from its working directory. It therefore needs stricter boundaries and clearer disclosures than an ordinary chat window.
Grok Build appears to have done the opposite. It presented granular permission controls around individual file reads while a separate subsystem packaged and uploaded the repository outside those controls.
That is the part that damages trust.
The problem is not merely that data reached a cloud service. The problem is that the visible security model did not describe the actual data flow. The user could deny access to a file and watch the agent obey, while the same file travelled inside a background Git bundle.
Security controls that protect only the most visible code path are decorative.
xAI should document exactly what Grok Build uploads, why each category is necessary, where it is stored, how long it is retained, and which controls disable each pipeline. Repository-wide uploads should require explicit opt-in consent. Existing users should be told whether their repositories were uploaded and be given a credible deletion mechanism.
Until then, the most important Grok Build command may be the one that prevents Grok from building itself a private collection of your Git history.
Because an AI assistant should help you push code.
It should not quietly push all of it somewhere else.
I haven’t trusted Musk for some years – this does not exactly make me trust him more.