Zhipu ZCode Allegedly Uploads Full Git History Silently: What Happened
On September 18, 2026, developer ferstar reported that Zhipu’s official coding app ZCode packages workspaces and full Git history after login. Evidence, Reddit reaction, and how it compares with Grok Build.

On September 18, 2026, developer ferstar published a reverse-engineering write-up claiming that ZCode, Zhipu’s official AI coding desktop app, quietly packages the entire workspace while the user is signed in, encrypts it, and queues it for a direct upload to Alibaba Cloud OSS. The bundle is not limited to the current source tree. It also includes the full .git history, LFS cache, reflogs, and global app settings that cut across workspaces.
What stung developers was not the familiar fact that a cloud coding agent sends task-relevant code to a remote model. That is how these tools work. The fight is over a second layer: a background snapshot that users were not clearly told about, cannot turn off in the UI, and that would take the repository’s entire history with it.
As of publication, we have not seen a formal statement from Zhipu about this mechanism. What follows is limited to ferstar’s public investigation, English- and Chinese-language coverage, and the Reddit thread, covering only what can be checked.
Keep two things apart: GLM is open-weight; ZCode is closed-source
Once the discussion started, it became easy to glue “Zhipu open-weights” to “ZCode uploaded a repo.” Those are not the same claim.
Zhipu has kept releasing GLM-series open weights. GLM-5.3, for example, ships a model card and weights on Hugging Face under an MIT license. Open weights mean you can stand up your own inference, inspect the model files, and plug the model into a harness you choose.
ZCode is not the model. It is Zhipu’s official proprietary product. It is the first-party harness / desktop app for GLM. The installer is not open source, and users cannot audit the full client. The product site zcode.z.ai positions it as the official environment for the GLM Coding Plan, with Goal-mode long tasks, remote control, and deep GLM-5.3 integration.
So this controversy lands on the product layer, not the weights layer:
- Using open-weight GLM with an open-source or self-hosted harness has no direct connection to this snapshot pipeline.
- Installing and signing into official ZCode means handing the repo to an unauditable closed-source client.
That boundary was also the fastest reaction on Reddit. The r/LocalLLaMA post ZCode was allegedly caught uploading workspace/.git records to the cloud opened with “Look like next grok build moment.” The comments that set the tone were blunter: do not use a harness that is not open source.
What ferstar found: a 313MB snapshot stuck in pending
According to the Chinese original and the English version, the start was ordinary. Cleaning disk space, ferstar noticed ~/.zcode taking more than 700MB, with v2/checkpoints/ around 303MB. Inside was a roughly 313MB .enc file plus a state metadata file.
The metadata was specific:
- The workspace pointed at a local commercial project.
- The type was marked
baseline, a full snapshot. - After excluding directories such as
node_modules, the workspace was about 345MB; the encrypted archive was about 313MB. failureCountwas 564, meaning the bundle had been sitting in localpending/and retrying.
One boundary has to stay sharp: what ferstar captured on his own machine was first a packed archive waiting in the upload queue, not a repo copy that had already landed in the cloud and could be downloaded in public. He also unpacked the client’s app.asar, matched logs and live connections, and reconstructed the upload path. Packet capture showed the process holding persistent connections to zcode.z.ai and two Aliyun OSS nodes.
In other words, we can say with fairly high confidence that the client packs, encrypts, requests OSS credentials, and keeps retrying after failure. Public material does not include a global count of how many user machines actually completed the upload.
The upload path: credentials from Zhipu, files straight to OSS
ferstar reconstructed a two-step flow:
- The client asks
https://zcode.z.aifor/api/v1/snapshot/upload-credential. The server returns asnapshot_id, an RSA public key, a size cap, OSS form signatures, and a callback. - Locally, the workspace is packed as
tar.gz, encrypted with AES-256-CTR, and the symmetric key is wrapped with RSA-OAEP. The client then poststar.gz.encdirectly to Aliyun OSS via PostObject. OSS callbacks Zhipu’s backend to register the snapshot.

The crypto itself is ordinary envelope encryption. The argument is not about the algorithm. It is about who holds the key. The public key is issued dynamically by the server; the private key never leaves the cloud. ferstar tried every local private key against the envelope and failed, as expected. The hundreds of megabytes of ciphertext on disk cannot be opened by the user or by the ZCode client. Only Zhipu’s backend can unwrap it.
If this were checkpoint rollback or cross-device sync for the user, the keys would usually live on the user side, or at least the user would hold a recovery key. A key only the server can use looks more like a guarantee that the cloud can read the archive than a guarantee that the user can restore it.
What is in the snapshot: more than 80% is Git history
The ciphertext cannot be opened, but the Manifest left during packing is plaintext. ferstar’s inventory covered 42,411 files:
| Content | Size | Share | What it contains |
|---|---|---|---|
.git/lfs/ | 196.1 MB | 56.8% | LFS cache: large files and binaries pulled over the repo’s life |
.git/objects/ | 102.2 MB | 29.6% | Full commit / tree / blob object store |
.git/logs/ | 0.6 MB | 0.2% | reflogs, including local branch moves and unpushed work |
| Remaining source and docs | ~46.2 MB | 13.4% | Current workspace code and config |
.git alone is 86.6%.
If that archive reaches the cloud, the server does not only get “the files open right now.” It gets traces the repo may have kept since day one: secrets later deleted, unpushed branch names, and internal GitLab hostnames and paths in .git/config. The code also includes repo_snapshot_extra_manifest, which folds in global ZCode settings such as settings.behavior.json.
For a commercial repo, that is a much wider cut than “send the current file to the model for completion.” Git history often still holds a .env, an internal URL, or a throwaway key that someone committed and later removed. It is gone from the working tree. It is still in the object store.
The settings do not stop it, and the privacy policy does not describe this layer
ferstar lined the UI toggles up against the client logic:
| Toggle | What a user might think it does | What the reverse engineering says it does |
|---|---|---|
Optimize Experience (optimizeAgentExperienceEnabled) | Turn off collection / telemetry | Whether data may be used to train models. Snapshots are still captured and uploaded when it is off |
Repo Snapshot Indexing (repoSnapshotIndexingEnabled) | Turn off snapshots | Whether the server indexes a snapshot after it arrives. Local packing and upload continue |
The capture / upload sidecar is instantiated unconditionally at startup. There is no preference check in the code; the only gate is a JWT after login. Triggers include captureBeforePrompt before each prompt, and repo-wiki-update when a task ends. In the logs, a single active session produced as many as 62 capture events.
On the privacy policy, ferstar is explicit: it says the product collects “text, files, and code submitted during conversations,” which matches how cloud coding agents feed a model. Across the policy, FAQ, and changelog, he found no mention of silently packing the whole workspace plus full Git history. The closest line is the generic “optimization program is off by default; inputs are not used for training unless you opt in.”
“Not used for training” and “does not leave the machine” are different controls. That split already showed up two months earlier in the Grok Build incident.
This is not the first time: Grok Build walked almost the same road in July
In July 2026, a researcher publishing as cereblab ran a wire-level analysis of xAI’s Grok Build CLI 0.2.93. The Hacker News then reported that the tool did more than send files the agent had read into model requests. It also packed the entire Git repository as a bundle and uploaded it on a separate storage channel to an xAI Google Cloud Storage bucket named grok-code-session-traces.
A few comparisons still cut cleanly:
- In a test where the model was told in plain language not to read any files, the captured git bundle still reconstructed a never-opened canary file, plus the full commit history.
- On a roughly 12GB repo the model never read, the model channel was about 192KB while the storage channel moved about 5.10GiB.
- With “Improve the model” turned off, whole-repo upload continued. That toggle governs training consent, not whether code leaves the machine.
On July 13, the same 0.2.93 client stopped calling /v1/storage, and the server began returning disable_codebase_upload: true. That was a server-side switch, not a new binary users had to install. Elon Musk then said on X that, as a precaution, user data previously uploaded to SpaceXAI would be completely and utterly deleted. The Register also recorded what followed: enterprise zero data retention (ZDR), a /privacy command, and the harness being open-sourced a few days later.
The overlap with ZCode is clear: a closed-source harness, whole-repo / full-history collection, and a training toggle that does not stop the upload. The differences are just as clear:
- Grok Build was caught on storage uploads that already returned HTTP 200. In ferstar’s public write-up, his own sample was stuck on 564 failed retries.
- After disclosure, xAI flipped a server flag quickly, and Musk publicly promised deletion. As of September 18, 2026, Zhipu had not issued a comparable public response.
- Grok Build later open-sourced its harness. ZCode is still a proprietary desktop app.
People put the two stories next to each other not because every byte of the implementation matches, but because developers now share the same lesson: the default behavior of a high-privilege coding agent cannot be judged by a training switch labeled “optimize experience.”
What Reddit is actually arguing: the model, the harness, or default collection
The mood on that r/LocalLLaMA thread is more useful than the headline. The discussion split into three layers.
The first is the trust boundary. /u/Voxandr said this is why they never use a harness that is not open-sourced. /u/mikael110 split “malicious model” from “malicious harness”: if the harness is open and audited, the session log is worth trusting; a closed-source harness is a different class of risk.
The second is how you would even notice. Someone asked whether local models might be trained to upload in secret. Later comments pointed out that if the model is not requesting the upload — if the harness sends the workspace on boot and never writes it into the session log — reading the session log is not enough. You need network inspection, or you run the harness with no internet.
The third is the “everyone does this” shrug. /u/Minute_Attempt3063 argued that Cursor and Claude index codebases too, for grep and context. That analogy only goes halfway. A cloud agent reading and indexing some files for the current task is not the same as a background job packing .git/objects, the LFS cache, and reflogs into an archive only the server can decrypt. In cereblab’s Grok Build comparison, Claude Code and Codex showed no whole-repo bundle in the tests described.
Some comments also tied discounts to incentives: the official harness is cheaper with GLM, which nudges people toward the closed-source client instead of a self-hosted open workflow. That is not proof the upload exists in order to train. It does explain why the official desktop app draws extra suspicion.
What users can do now
Until the vendor ships a product toggle that actually stops this, ferstar’s workaround is to lock the directory, not to delete the pending archive by hand. He tried deletion. Within half an hour the client packed a fresh 313MB archive, and the failure count went from 564 to 565.
macOS
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
chflags uchg ~/.zcode/v2/checkpoints
# Expected: Operation not permitted
touch ~/.zcode/v2/checkpoints/test
Linux
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
sudo chattr +i ~/.zcode/v2/checkpoints
# Expected: Operation not permitted
touch ~/.zcode/v2/checkpoints/test
Per ferstar: once the kernel blocks writes, there is no local artifact, so the OSS upload has nothing to send. The cost is that checkpoint rollback / timeline stops working. Chat, completion, and tool calls keep running. To undo it, run chflags nouchg or chattr -i.
The more durable product choices are still:
- Do not hand a closed-source, unauditable client a repo that holds secrets, customer code, or unreleased work.
- If you want GLM, prefer open weights plus a harness you control, rather than installing the official desktop app by default.
- Anyone who already opened a commercial repo in ZCode should assume Git history may have entered the packing queue, and rotate credentials that ever appeared in old commits.
That is the same stance we took in Is OpenClaw Safe? Officially Documented Risks and Hardening Advice: an agent that can read the repo, run a terminal, and touch Git is not a low-privilege editor plugin.
What the public record still cannot support
Several claims are still too thin:
- Whether Zhipu uses snapshots for training, human review, or checkpoint indexing only: neither ferstar nor we have server-side evidence.
- How many users worldwide completed an OSS upload: no official number.
- Whether this is product design, lagging docs, or deliberate concealment: the combination of “cannot be turned off + server-only key + policy silence” is enough for a risk call, not enough to write a confirmed malicious backdoor.
- Whether Zhipu will, like xAI, flip a server flag, update the privacy text, or ship a real off switch: that waits on an official response.
Writing unverified motives as fact does not help readers. Writing the reconstructed client behavior clearly does.
This kind of fight is no longer isolated. Claude Code already pushed “what else is the agent doing locally” into public view this year through hidden markings and a source-map leak. See The Claude Code Backdoor Controversy and What Was Claude Code's 'Source Leak' Really About?. How Chinese labs time open-weight releases against official products is a parallel thread, covered in China’s LLM Landscape in 2026.
FAQ
If ZCode is accused of uploading Git history, does that mean the GLM model is stealing data?
Those are different layers. GLM-series open weights can run locally. What was reverse-engineered here is snapshot-upload logic in the closed-source ZCode client. Skipping the official desktop app and using an open-weight model with your own toolchain does not inherit this packing pipeline.
Does this prove the code already sits on Zhipu’s servers?
For the sample ferstar published, the accurate wording is: the client finished a full pack and encrypt, and logged 564 failed retries. The upload path and OSS connections were reconstructed, but that sample itself was still pending. “The mechanism exists” is not the same sentence as “every user’s repo has already been stored.”
Does turning off Optimize Experience help?
Not according to ferstar’s reading of the code. That switch is training consent. Snapshot capture and upload still run after login.
Compared with Grok Build, which is worse?
The overlap is whole-repo / full-history collection, a useless training toggle, and a closed-source harness. Grok Build had wire-level successful uploads, then a server-side shutoff and a deletion pledge. ZCode still lacks an official explanation. Severity depends on what happens next, not on which headline is louder.
What if you still want to use ZCode?
At minimum, lock ~/.zcode/v2/checkpoints, keep it away from repos that hold secrets, and wait to see whether the vendor ships a verifiable off switch. Treat checkpoint / timeline as a feature that requires sending the codebase to the cloud, then decide if that convenience is worth it.
Takeaway
The September 18, 2026 controversy is not about whether Zhipu ships open-weight models. It is about whether the official coding client disclosed whole-repo snapshots to the cloud, and whether users can turn that off.
ferstar’s evidence chain is already enough to raise the alert: background packing after login, encryption only the server can unwrap, Git history making up more than 80% of the snapshot, and UI toggles that do not stop it. It is not enough to write “confirmed nation-state theft,” and it should not be waved away with “Cursor indexes code too.”
Grok Build showed two months earlier that once this kind of mechanism is on the table, a vendor can change the default, add a switch, even open-source the harness. ZCode is now sitting with the same question. Developers are not asking for a mood. They are asking for behavior that can be turned off, audited, and matched to the privacy policy.
Related links
Source Notice
This article is published by merchmindai.net. When sharing or reposting it, please credit the source and include the original article link.
Original article:https://merchmindai.net/blog/en/post/zcode-silent-git-history-upload



