If ZCode ever ran on a machine with access to your repositories, the scope of the incident is everything those repositories have ever contained, not the code you can see today. Z.ai's coding agent packaged whole workspaces, and 86.6% of one captured package was the .git directory: object history, LFS cache and reflog, meaning deleted files, rewritten commits and unpushed branches. The package was encrypted to a key only Z.ai held, and neither of the product's two privacy toggles stopped the capture. So rotate every credential that ever sat in the git history, and stop approving coding agents because of what their settings page says.
Z.ai has since apologised, removed the upload code and open-sourced ZCode under Apache-2.0. That fixes the client. It does not tell you what already left your network, and nobody outside Z.ai can yet answer that.
What Did ZCode Actually Capture?
It captured a full snapshot of the workspace, and most of that snapshot was git internals rather than source code. On Sept 18 a developer who writes as ferstar published a reverse-engineering write-up after finding ~/.zcode/ using more than 700 MB of disk. One commercial project produced a 313 MB encrypted package of 42,411 files from a 345 MB workspace. By size:
| Captured path | Size | Share of payload |
|---|---|---|
.git/lfs/ |
196.1 MB | 56.8% |
.git/objects/ |
102.2 MB | 29.6% |
.git/logs/ (reflog) |
0.6 MB | 0.2% |
| Source, config, global ZCode settings | remainder | 13.4% |
Figures from ferstar's write-up and Tokenstead's breakdown.
That composition is the whole story for a security team. .git/objects holds every version of every file ever committed, including the .env someone committed in 2023 and removed the next day. The reflog records where branches pointed before a rebase or reset, so a history someone "cleaned" is often still reachable locally. LFS holds the large binaries: datasets, design files, model weights. None of it shows up in a code review of the current tree.
The capture ran before each user prompt, and a single session produced up to 62 snapshot captures. Deleting the checkpoint folder did not help, because the snapshots were recreated within 30 minutes.
Why Didn't the Privacy Settings Stop It?
Neither setting controlled the upload. Each toggle controlled something that happened after the data arrived on Z.ai's side. According to ferstar's analysis, "Optimize Experience" only governed whether the data could be used for model training, and "Repository Snapshot Indexing" only governed server-side indexing once the snapshot was received. The capture process started unconditionally at launch and needed only a valid login token.
RuntimeWire reported the same finding: with both controls off, ZCode "still packaged and attempted to upload workspaces."
The upload path was built so that only Z.ai could read the result. The client fetched credentials from zcode.z.ai, encrypted the package locally with AES-256-CTR, wrapped the key with an RSA public key, and posted it straight to an Alibaba Cloud OSS bucket. The private key never existed on the client. As The Cryptonomist put it, users could neither read nor delete what had been uploaded. The privacy policy mentioned collecting "conversation text, files and code". It did not mention packaging whole repository histories.
This is the lesson that outlives ZCode. A privacy toggle is a statement about how the vendor will use your data, not proof that the data stays on the machine. Your approval checklist probably treats those as the same thing.
What Has Z.ai Fixed, and What Is Still Unknown?
The client is fixed. The history of what was collected is not public. To be fair to Z.ai, it moved quickly: it attributed the uploads to ZCode's codebase indexing feature, removed the Repo Wiki feature and the snapshot workflow in v3.14.0, and said the data "has never been used for model training". Two third parties signed off. China's CAICT confirmed the OSS bucket was in a "zero-data state", and NSFOCUS reported that the bucket and every object in it had been deleted. v3.14.3 shipped on Sept 23 with the open-source repository in sync.
It is also true that ferstar's 313 MB commercial package failed to upload 564 times. Not every capture left the building. But a smaller public repository of 538 files did upload, so the pipeline worked when the payload was small enough.
That is the strongest case for Z.ai. Here is what it leaves open:
- How long uploads ran, and how many workspaces were captured. The Next Web lists both as unknown. ZCode launched in July 2026, so the exposure window could be as long as two months.
- The attestation reports themselves. The full CAICT and NSFOCUS reports have not been published. A deleted bucket says nothing about copies made while the data was being indexed.
- The code that did it. The open-source repository launched with two commits and its development history wiped, so no outsider can audit the version that ran the uploads.
One commercial user, Chengming Technology, alleged that trade secrets were taken from six of its workspaces, then withdrew the letter on Sept 21, admitting errors in its wording. So an attestation is what you have to go on, and it describes the vendor's storage, not your exposure. Plan your response on the assumption that anything packaged may have left.
Why Rotation Has to Cover the Whole Git History
Rotating a credential is the only step that makes a leaked copy useless, and in this incident the copy includes history your scanners were never pointed at. GitHub's own guidance is blunt: when the sensitive data is a secret, "as a first step you need to revoke and/or rotate that secret." Rewriting history comes second, and here it does nothing at all, because the history already left with the snapshot.
The base rates are why this is not paranoia. GitGuardian's 2026 report found internal repositories are roughly six times more likely than public ones to contain hardcoded secrets, and that more than 64% of secrets confirmed valid in 2022 were still valid in January 2026. Private repos are where teams relax, and old secrets do not expire on their own.
There is also a gap in your tooling. Most scanners walk reachable history. Gitleaks, for example, scans patches through git log -p, and a default git log does not reach commits referenced only by the reflog or objects that no branch points to. ZCode copied those as well. git fsck --unreachable lists objects that no ref reaches, and --lost-found writes dangling blobs out as files you can scan. Your normal CI secret scan passing is therefore not evidence that the snapshot was clean.
What Should an Approved Coding Agent Have to Prove?
It should have to prove, on your network, where its traffic goes. A coding agent with filesystem access is a data-egress channel with a chat window attached. ZCode is not the first coding agent this year whose admin controls and actual behaviour disagreed. Google's Antigravity did not honour its own admin URL allowlist, and Alibaba's Claude Code ban was a buyer deciding it could not trust a coding tool's data flows.
The industry has been here before. In 2023 Samsung banned generative AI tools on company devices after engineers pasted internal source code into ChatGPT, citing how hard it is to "retrieve and delete" data on external servers. That leak needed a human to paste something. ZCode needed nobody. The control that would have caught both is the same one: watch what leaves the machine, not what the user or the vendor says leaves it.
The approval question for Cursor, GitHub Copilot, Devin Desktop or anything else is therefore not "does it have a privacy mode?" It is "which hosts did it contact during a two-hour session on a canary repo, and what volume went to each?"
What to Do About It
This Week:
- Find every machine that ran ZCode. Search endpoint telemetry for a
~/.zcode/directory and for connections tozcode.z.ai. Remember BYOD and contractor laptops, since a free-tier agent rarely goes through procurement. - Preserve before you delete. Copy
~/.zcode/v2/checkpoints/, including its manifests and status files. On ferstar's machine the manifest listed every captured file and the status file counted failed uploads. That is the only local evidence of what was packaged and whether it went. - Rotate every secret in the affected repositories' full history, not only the working tree. Scan with reflog and all refs included (
gitleaks git --log-opts="--all --reflog"), recover dangling objects withgit fsck --lost-foundand scan those too, then rotate every hit. Do cloud keys, CI tokens and database credentials first.
This Month:
- Classify the LFS exposure. At 56.8% of the payload, LFS was the largest item. Ask the owning teams whether datasets, customer extracts or model weights lived there, and route the answer to legal and privacy, not only to security.
- Add a network test to agent approval. Run each candidate agent against a canary repository planted with fake credentials, behind your proxy, and record every destination host and byte count. Re-run it on every major version, because ZCode's upload arrived in a routine client build.
- Block unapproved agents at egress, not only by policy memo. Scope the credentials agents can reach on developer machines, so that the next surprise upload carries less.
Before Renewal:
- Put the upload path in the contract. Require disclosure of every server-side copy the client makes, notice of changes before release, and a customer-held right to deletion. Use the six vendor-review questions that actually change an answer. "We encrypt it" does not count when the vendor holds the key.
The Bottom Line
The endpoint-security generation learned that an installed agent is trusted in proportion to what you can observe it doing, not what its console says. AI coding agents are relearning that faster and with more at stake, because they sit on the one directory that holds your source, your history and, too often, your keys. Z.ai's response was faster and more open than most. It still cannot tell you what it took from you.
The settings page is a promise. The packet capture is the evidence.
Continue Reading
- Antigravity's Allowlist Isn't Honored. Use Your Proxy.
- Your AI Coding Tool Is Watching You. Alibaba Just Proved It.
- 182 Credentials Hid in 'Encrypted' Reasoning. Go Rotate.
- 46% of Your AI Now Runs on Chinese Models
- The Pinned Commit Was a Branch. Check Your Git Host.
- OpenAI Cuts Cursor Off Nov 12. BYOK Voids Your ZDR.
