Security1 publisher2 min readPublished
Wire-level teardown puts Grok Build's privacy opt-out downstream of the upload
The independent checker cereblab captured grok 0.2.93 sending a never-read repository to a Google Cloud Storage bucket. The privacy opt-out xAI shipped afterwards governs retention, cereblab says, while the same bytes still leave the machine.
The Watch · Security desk

What happened
- cereblab's wire capture of grok 0.2.93 shows the CLI packaging a workspace and uploading it as a git bundle to POST /v1/storage even when the prompt tells the agent to read no files.
- The user-facing control did not reach it: with "Improve the model" switched off, /v1/settings still returned trace_upload_enabled: true in the captured version.
- xAI has since turned the upload off from its own side with disable_codebase_upload: true and added a separate privacy opt-out for users.
Compiled by The WatchSomething wrong?How this is made
Why it matters
- exposure Any secret a Grok Build session read is disclosed by the transmission itself. A team that ran it on a real repository has to rotate credentials and treat the tracked files and git history as published.
- constraint If an opt-out only scopes retention, the interface cannot tell a customer whether bytes still leave the host. The only check that separates the two is a proxy sitting in front of the binary.
- decision The tool authenticates with a consumer X or SuperGrok login and no API key, so approval sat with individual developers. Security teams now have to decide whether a vendor toggle counts as a control in their own policy.
- precedent The record supporting deletion of the earlier uploads is a public commitment from Musk that the teardown lists as unconfirmed. That unconfirmed commitment sets the bar for what counts as proof when the next vendor promises the same.
The data leaves in two channels. Anything the agent reads goes into the live model turn at POST /v1/responses, and the same content lands in a session_state archive that POST /v1/storage accepted with HTTP 200. The .env file in the test repository went up verbatim and unredacted in both [2]. The second channel does not wait for the agent. Given the prompt "reply OK, do not read any files", grok 0.2.93 packaged the workspace and uploaded it as a git bundle. Cloning the captured bundle returned src/_probe/never_read_canary.txt with its unique marker intact, along with the full git history [3].
On a 12 GB repository of random files the agent never opened, /v1/storage moved 5.10 GiB, every request returning 200. The transfer stopped only because it was truncated mid-stream. The model-turn channel carried 192 KB [4]. That is roughly 27,850 to 1: 5.10 GiB is about 5,347,700 KB, divided by 192 [1]. No storage upload failed in the capture at all, and the only non-200 responses were a model-usage quota on /v1/responses and one unrelated 404 [5]. The destination is the Google Cloud Storage bucket grok-code-session-traces, named in the binary and in a captured metadata.json [6].
xAI's answer arrived server-side. Since the original publication the vendor set disable_codebase_upload: true and added a privacy opt-out [12]. cereblab tested that opt-out on the wire and wrote that it is "a data-retention setting, not a block on what's sent" [13]. In the July capture, the nearest user-facing control did nothing either: turning off "Improve the model" left /v1/settings returning trace_upload_enabled: true [8].
Anyone paying for a SuperGrok login can repeat this. Install is a curl one-liner to x.ai/cli/install.sh and authentication is a browser login to X or SuperGrok, not an API key [10]. Grok does not certificate-pin, so a mitmproxy CA trusted in the login keychain reads the traffic without sudo [11]. The upload code is first-party: strings on the binary returns crates/codegen/xai-data-collector/src/gcs.rs, the bucket name, storage.googleapis.com, and the log line "Uploading bytes to GCS via proxy" [9].
Transmission, acceptance and storage are proven; training on the data is not [15]. The appendix carries SHA-256s for each artifact and a "what we did not prove" list, and section 7 flags observations seen live but not retained as files [16]. The captures were of the author's own traffic against a throwaway repository of fake canary secrets [17]. Elon Musk has publicly committed to deleting all previously uploaded data, which the gist records as not yet confirmed complete [14].
What to watch
- Whether xAI produces evidence that the previously uploaded bundles in grok-code-session-traces were deleted, and who verifies it.
- Whether a later grok release moves the opt-out ahead of the upload, which the same mitmproxy setup would show.
- Whether disable_codebase_upload stays set, given it is a server-side flag xAI controls and can change without a client update.