ZCode Secretly Uploads Your Entire Git History to the Cloud

A developer freeing up disk space noticed an AI coding app's config folder had ballooned past 700MB. Digging in, he found something worse: his entire Git history was being packaged, encrypted, and quietly shipped to the cloud โ and he couldn't decrypt it himself even if he wanted to.
What's happening
ZCode is Zhipu's official AI coding desktop app โ the Chinese company behind the GLM model family. According to a technical writeup by developer ferstar (blog.ferstar.org, published September 17, 2026, which hit the front page of Hacker News with 231 points and nearly 90 comments), simply being logged into ZCode triggers the app to package the entire workspace โ including .git/objects, .git/lfs, reflogs, and global configs โ and upload it straight to Aliyun OSS.
Ferstar found a 313MB .enc file sitting in ~/.zcode/v2/checkpoints/, alongside metadata showing failureCount: 564 โ the app had retried the upload 564 times and kept trying. The source repo was 10GB total; stripped of node_modules, the remaining 345MB was almost entirely source code and commit history.
The mechanism: the key isn't yours
This is the part worth paying attention to. Ferstar reverse-engineered ZCode's app.asar and reconstructed the flow:
- The client requests upload credentials from
zcode.z.ai - The server returns a
snapshot_id, Aliyun OSS form signatures, and a freshly generated RSA public key for that session - The client archives the workspace, encrypts it with AES-256-CTR, then wraps the symmetric key with RSA-OAEP-SHA256 using the server-supplied public key
- The resulting
tar.gz.encis POSTed directly to Aliyun OSS, which calls back to confirm receipt to Zhipu's backend
This is textbook envelope encryption โ with one deliberate twist. The private key matching that RSA public key never touches the user's machine. It lives exclusively on Zhipu's servers. Ferstar tried unwrapping the file with every local private key available โ it failed, as expected.
In other words: that 313MB of ciphertext sits on your own disk, but only Zhipu can open it. If this were genuinely built for rollback or cross-device sync, the key would live on the user's side โ the way Git and Time Machine both work. A key that only the server holds has exactly one reasonable purpose: letting the server read your code on demand.
The UI toggles don't do what you'd expect
The obvious move is to dig into settings and switch this off. Ferstar cross-referenced both relevant toggles against the source and found neither one works:
| Toggle | What you'd expect | What it actually does |
|---|---|---|
| Optimize Experience | Disable data collection | Only controls whether data is used for model training. Snapshotting still runs |
| Repo Snapshot Indexing | Disable the snapshot feature | Only controls whether the server indexes uploaded snapshots. Local packaging and upload continue |
Looking at the compiled code, the capture/upload pipeline is instantiated unconditionally at app startup โ no gating on user preferences anywhere. The only requirement is a valid login token. Captures fire at two points โ before every prompt, and after a task completes โ and a single active session logged up to 62 capture events.
So what โ why should developers care?
This isn't the usual "AI needs code context to work" trade-off that most people already accept when using an AI coding tool. The problem is scope and key architecture.
Scope: inference needs context relevant to the current task. What ferstar describes is the entire Git history going out the door โ 86.6% of the payload is the .git directory alone, including the full object store and reflogs. That means old API keys deleted in a later commit, unpushed branch names revealing unreleased features, internal hostnames sitting in .git/config. Deleting a secret from a new commit doesn't remove it from Git history โ and ZCode is packaging exactly that history for upload.
Key architecture: a legitimate backup or sync system keeps the decryption key on the user's side. ZCode does the opposite โ the key exists only server-side, there's no disclosure of this behavior in the privacy policy, no UI control turns it off, and deleted files silently regenerate (the retry counter ferstar tracked went from 564 to 565 within 30 minutes of manual deletion). Put those three facts together and this looks a lot more like deliberate data collection than a user-facing feature.
For teams evaluating AI coding tools around sensitive codebases, this is a reminder to check two things before rollout: whether the tool auto-packages and uploads the workspace at all, and if it does, who holds the decryption key. "We encrypt your data" only means something when you โ not just the vendor โ can unlock it.
How to block it (if you still need ZCode)
Ferstar first tried deleting the pending file โ within 30 minutes the app repacked a fresh 313MB archive and kept retrying. Manual deletion is whack-a-mole. The reliable fix is locking write access at the filesystem level:
# macOS
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
chflags uchg ~/.zcode/v2/checkpoints
# Linux
rm -rf ~/.zcode/v2/checkpoints
mkdir -p ~/.zcode/v2/checkpoints
sudo chattr +i ~/.zcode/v2/checkpoints
The kernel blocks any write to that directory. The "checkpoint rollback" UI feature stops working โ but it required uploading your code in the first place anyway, so losing it isn't much of a trade-off. Chat, autocomplete, and other tool calls keep working normally.
What to remember
- ZCode (Zhipu) packages the full
.githistory plus configs, encrypts it with AES-256-CTR/RSA-OAEP, and uploads it to Aliyun OSS on login - The decryption key lives server-side only โ even the user can't open the file on their own machine
- Neither settings toggle stops capture/upload; they only control training data use or server-side indexing
- Captures fire before every prompt and after every task โ up to 62 events per session
- The only current mitigation is locking
~/.zcode/v2/checkpointsat the filesystem level; there's no official fix from Zhipu as of this writing
This is an independent researcher's finding, and Zhipu hasn't issued an official response as of publication. But a key architecture designed so only the server can decrypt, combined with a privacy policy that never mentions this behavior, is reason enough for anyone running ZCode near commercial source code to check right now โ not wait for Zhipu to comment.
Content assisted by AI (Amy ๐ธ). Reviewed by the author.
Related Posts
Friendly Fire: When AI Coding Agents Run the Attacker's Code Instead of Catching It
AI Now Institute just showed that Claude Code and Codex in autonomous mode can be tricked into executing attacker code hidden in a README file.
Miasma Worm: When AI Coding Agents Become the Trigger for Malware
The Miasma supply chain attack compromised 73 Microsoft GitHub repos, weaponizing the setup hooks of Claude Code and Cursor to silently harvest developer credentials.
Baseten's Admin GitHub Token Sat in Docker History for 3 Years
Security firm Strix scanned Baseten in 25 minutes and found a live admin GitHub token from 2023, hidden in a public Docker image's build history.