TUE, SEPTEMBER 22, 2026
Independent · In‑Depth · Practitioner‑Tested
✎ Code Tools

ZCode Was Uploading Your Whole Git History. The Settings Did Not Stop It.

A 700MB folder on a developer machine led to the finding: ZCode packaged entire workspaces including full Git history into encrypted archives and shipped them to Aliyun OSS at startup. One project came to 42,411 files and 313MB. Two settings that looked like privacy controls governed training and indexing, not capture. Fixed in 3.14.0; harness open-sourced 21 September.

By AIToolsRecap September 22, 2026 7 min read 28 views
Home Articles Code Tools ZCode Uploaded 42,411 Files. No Setting Could T...

This is the second AI coding tool security story in two days. Yesterday it was Plugin4Shell, where four agents made the same checkout mistake. This one is different in kind: nothing was exploited, and nothing went wrong. ZCode worked exactly as built.

How It Was Found

On 17 September a developer ran out of disk on a 256GB MacBook Air and went looking for what was eating it. The ~/.zcode directory held over 700MB. Unpacking app.asar and reading the local metadata revealed what the directory was for: staging workspace snapshots before upload.

The write-up went up at 02:00 UTC on 18 September. Z.ai responded publicly the same day at 17:44.

What Was Actually Sent

One commercial project in the captured set came to 42,411 files and 345.5MB uncompressed, arriving as a 313MB encrypted archive. The composition is the part worth sitting with:

  • 86.6% of the payload was Git data
  • .git/lfs/ alone was 56.8%
  • .git/objects/ was 29.6%
  • The remainder was source, configuration and global application settings

Git objects are not a snapshot of your current code. They are every commit, every branch, every deleted file, and every secret anyone ever committed and then removed. A single active session logged up to 62 capture events.

The Encryption Detail

The archives used textbook envelope encryption: AES-256-CTR for the content, RSA-OAEP-SHA256 to wrap the key with a server-supplied public key.

The private key never touched the machine. The client could not decrypt its own uploads. Only the server could read them.

That is a legitimate design for protecting data in transit. It also means a user auditing their own outbound traffic cannot inspect what left their machine.

Why the Settings Did Not Help

ZCode exposed two toggles that read like privacy controls:

  • Optimize Experience - controls only whether uploaded data may be used for model training
  • Repo Snapshot Indexing - controls only whether the server indexes snapshots after they arrive

Neither governs capture. The pipeline ran unconditionally at startup. Both switches operate on data that has already been uploaded, which is a meaningfully different promise from the one the labels imply.

Where It Went

Upload credentials came from zcode.z.ai at /api/v1/snapshot/upload-credential. The archives themselves went by direct form POST to Aliyun OSS, bypassing Z.ai servers entirely, with OSS holding a callback registration back to Zhipu infrastructure.

What Z.ai Said

Z.ai confirmed the uploads and attributed them to a codebase indexing feature used to build local indexes and generate Repo Wiki summaries. Their position: the data was destroyed immediately after Wiki generation, the feature was on by default during early launch, and it is fixed in version 3.14.0.

On 21 September Z.ai open-sourced the ZCode harness under Apache-2.0, which is a real response rather than a press release. It lets anyone verify the current behaviour.

What open-sourcing cannot verify is the past. Whether encrypted snapshots already sitting in OSS were physically purged is not checkable from outside, and the original researcher said so plainly.

What To Do If You Ran It

Update to 3.14.0 or later first. Then treat it as a credential exposure, because that is what uploading .git/objects/ means:

  • Rotate any secret that has ever been committed to an affected repository, including ones removed in later commits
  • Check .git/logs/ against your own history to see what period was captured
  • Run git log --all --full-history with a secret scanner rather than scanning the working tree only
  • If the repository belongs to a client, the disclosure decision is theirs, not yours

The Wider Point

Every AI coding tool needs your code to be useful. The question is not whether it reads your files - it has to - but what leaves the machine, how far back in history it reaches, and whether the settings page describes it accurately.

Check what your current tool sends before you need to. ~/.zcode was 700MB and nobody looked for months.

Sources

Tags
AI NewsCoding AI2026

Spot an inaccuracy?

We verify facts before publishing and correct errors promptly. If something in this article is wrong or outdated, let us know.

Report an error →