Three days after a paying subscriber published packet captures of Z.ai’s coding client shipping whole repositories to Alibaba Cloud, ZCode is Apache-2.0 on GitHub, in two commits, with two audits cited and the bucket gone. This is the dated record: what the researcher found, what Z.ai said on September 18 and September 21, what the published code shows, and what no audit taken after the fact can show.
On this page · 10 sectionsOpen
On September 18, 2026 a paying GLM Coding Plan subscriber published packet captures showing that ZCode, Z.ai’s desktop coding agent, packaged the whole workspace of a logged-in user, .git history, LFS cache, reflogs and app configs included, encrypted it and uploaded it to Alibaba Cloud OSS. Roughly 87 percent of the payload was .git. The post passed 1.6 million impressions.
Z.ai open-sourced ZCode at github.com/zai-org/ZCode under Apache-2.0. The repository was created at 12:01 UTC on September 20, the open-source commit landed at 21:14 UTC, and the ZCode account’s statement followed at 01:23 UTC on September 21. The history is two commits: an empty initial commit and one commit of 6,973 files and 1.03 million lines. Pull requests are locked and issues are disabled.
The encryption was the ironic part. The client encrypted each snapshot with AES-256-CTR and wrapped the key with an RSA public key delivered by the server; the private key lived only in Z.ai’s cloud. The ciphertext sitting on the user’s own disk could not be read by the user or by the client.
Z.ai’s first statement, posted to its Feishu user group at 17:44 Beijing time on September 18, said the uploads came from a codebase-indexing feature, that generating a Repo Wiki page may trigger an upload, that the data is destroyed once the page is built, and that the feature was on by default early on. The researcher’s audit of client 3.12.3 found the upload sidecar triggered before every prompt and kept packaging with both relevant toggles off.
The September 21 statement cites two assessments. CAICT confirmed the zcode-prod OSS bucket is in a zero-data state and that client v3.14.0 removed Repo Wiki and disabled the snapshot workflow; NSFOCUS confirmed the bucket and every object in it were deleted and found no remaining path that transmits local files. Z.ai says no such data is retained and none was used for model training, and promises the full report soon.
What the published code answers and what it cannot. The upload endpoint, the OSS PostObject path and the RSA key delivery are absent from the repository; indexing runs on bundled ripgrep and bfs; checkpoints are local git diffs under ~/.zcode/checkpoints/, which undercuts the checkpoint-restore rationale. What a September 20 bucket audit cannot show is what happened to data uploaded before September 18.
For anyone running a coding agent on private code, the lesson is the mirror image of the four Irregular incidents. There an agent reached too far outward from a test box; here the harness reached inward, and a settings toggle was a picture, not a control. The controls you own are where the agent runs, what it can read, and a gate on every command that reaches your world.
§ 01What happened, in order
The story is three days long and every step is dated by something other than a news article. A subscriber to GLM Coding Max, cleaning up disk space on a 256 GB MacBook Air, found ~/.zcode holding more than 700 MB, unpacked the app and traced the traffic. The report he published on the morning of September 18 (git commit “Fri Sep 18 10:35:05 2026 +0800”, 02:35 UTC) said that whenever a user is logged in the client “silently packages your entire workspace”, encrypts it and posts it to Alibaba Cloud OSS. His own state files showed a 313 MB archive from a workspace of 42,411 files stuck in pending after 564 failed attempts.
Z.ai answered the same day in its Feishu user group, at 17:44 Beijing time (09:44 UTC) by the researcher’s account, in a statement later reproduced on V2EX. In our translation: the problem came from the codebase-indexing feature; generating a Repo Wiki page may trigger an upload of repository data; the uploaded data is destroyed as soon as the page is generated; the feature was on by default in the early launch period and some users were affected; it is fixed; ZCode will be open-sourced and reviewed by third parties; every user gets an extra weekly quota reset. The researcher’s September 19 update opened with the line that matters: “The fact that uploads occurred is no longer contested by Zhipu”.
The repository appeared on GitHub at 12:01 UTC on September 20 with an empty initial commit; the commit titled feat: open source landed at 21:14 UTC. At 00:54 UTC on September 21 the first public post announcing the release went up, and at 01:23 UTC the ZCode account posted its statement: “we have completed the necessary remediation and sincerely apologize to all our users”. By 13:02 UTC the repository had 5,033 stars and 1,412 forks.
| When | What | Source |
|---|---|---|
| Sep 18, 02:35 | Researcher publishes the report (his git commit time; the page’s 02:00 Beijing stamp was AI-generated metadata, corrected in his Sep 21 update) | blog.ferstar.org |
| Sep 18, 09:44 | Z.ai statement in its Feishu user group, 17:44 Beijing time | Researcher’s account; V2EX reproduction |
| Sep 18, evening | Chinese tech press carries the statement | IT Home, Sina, per the researcher |
| Sep 20, 12:01 | github.com/zai-org/ZCode created, empty initial commit at 12:06 | GitHub API |
| Sep 20 | zcode-prod OSS bucket and all objects deleted, per NSFOCUS as cited by Z.ai | ZCode statement, Sep 21 |
| Sep 20, 21:14 | Commit feat: open source, 6,973 files | GitHub API |
| Sep 21, 00:54 | First public post announcing the release, id-clocked | X, read in Chrome |
| Sep 21, 01:23 | ZCode account statement with the CAICT and NSFOCUS findings, id-clocked | X, read in Chrome |
| Sep 21, ~13:00 | 5,033 stars, 1,412 forks | GitHub API |
§ 02The statement against the client
The first statement described a feature; the client audit described a sidecar. Both can be true about different builds, which is why the researcher laid the affected build, the remediated build and the statement side by side. Reading his September 19 table, the gaps are specific.
| Point | Statement (Sep 18) | Client 3.12.3 as captured |
|---|---|---|
| What was sent | Repository data, for the Wiki | Full-workspace snapshots, roughly 87 percent .git: objects, LFS, reflogs |
| Trigger | Wiki generation may upload | An upload sidecar resident while logged in, firing before every prompt and on Repo Wiki update |
| Can it be turned off | No switch mentioned | With Optimize Experience and Repo Snapshot Indexing off, the client “still packaged and attempted direct OSS uploads” |
| Cloud handling | Destroyed after generation | Not verifiable from outside |
| Retained data | Not stored after the Wiki | A 538-file snapshot accepted by the server; retention and decryption rights unaddressed |
The encryption is the detail that turned a privacy story into a trust story. The client encrypted each archive with AES-256-CTR and wrapped the key with RSA; in the researcher’s words, “the RSA public key used for encryption is delivered on the fly by the server, while the private key lives exclusively in the cloud”. The user could see the ciphertext on their own disk and could not open it. Neither could the client.
§ 03What left the machine
One correction the researcher made to his own headline deserves the same prominence the headline got. The 313 MB commercial repository that anchored the story never uploaded: it exceeded a size limit, failed 564 times and stayed pending, and he confirmed on his OpenWrt router that the chunks never left his network. The smaller case is the one that proves the mechanism end to end: a separate public-repo workspace of “538 files, about 15KB after compression and encryption, status accepted by the server”. Another user reproduced the directory layout and state files on Windows with several small workspaces showing no failure record.
| Snapshot | Files | Size on disk | Attempts logged | Server response |
|---|---|---|---|---|
| Commercial project | 42,411 | 313 MB encrypted | 564 failures | Never accepted; over the size limit |
| Public repository | 538 | about 15 KB encrypted | 1 | Accepted |
§ 04What the published code shows
The researcher read the repository the morning it appeared. The history is “an empty initial commit, followed by a massive feat: open source commit dumping 6,973 files and 1.03 million lines of code at once”; pull requests are locked and issues are disabled, so nothing can be filed against it and no diff shows how the pipeline was removed. The license is Apache-2.0. A search for the captured upload-credential endpoint, the OSS PostObject path, the AES-256-CTR routine and the public-key delivery “returned zero matches”. Repo Wiki is gone except for an unrelated Wikipedia reference. Code indexing and symbol search run on bundled ripgrep 14.1.1 and bfs, local processes, which the researcher reads as “proving that local codebase retrieval never needed full-repo uploads in the first place”.
The checkpoint claim fared worst. The first statement tied the uploads to session checkpoint restore and rollback. The published implementation runs git diff by commit id against the current workspace and writes JSON metadata under ~/.zcode/checkpoints/. Checkpoints are local git utilities with no cloud dependency. The repository also carries a 27 KB NOTICE.md that, in the researcher’s reading, disclaims every outbound request in the codebase and does not mention whole-repository uploads.
§ 05The audits, and what an audit cannot show
The September 21 statement names two assessors. CAICT, the China Academy of Information and Communications Technology, “confirmed that the zcode-prod Alibaba Cloud OSS bucket is in a zero-data state”, that remediation is complete in ZCode v3.14.0, that Repo Wiki has been removed and the snapshot workflow disabled. NSFOCUS confirmed that every object and the bucket itself were deleted, and that “no functional path capable of triggering the generation of local repository snapshots or transmitting local files externally was identified”. Z.ai adds that “no such data is retained and that it has never been used for model training”, announces a vulnerability reporting process in which “we will provide rewards based on the severity of the issues reported”, and says “The full security assessment report will be released soon”.
Deleting the bucket is the right containment move and the researcher says so. His objection is about time, not intent: a static verification that a bucket was empty and then gone after September 20 is a fact about September 20, and “proving that a bucket was emptied or deleted after Sep 20 cannot retroactively reconstruct what happened to data uploaded prior to Sep 18”. The list he left open stands: how anyone outside the company verifies destroyed immediately, who held the private key and when it was destroyed, and how a feature that needed cloud copies for restore squares with copies that were deleted at once.
He also pushed back on being called a community developer or a foreign hacker: “I was simply a paying Coding Plan subscriber who uncovered unannounced exfiltration of private code and published the packet capture evidence”. And he owned the one error in his own record, a publish time hallucinated by the AI helper that wrote his page metadata, with a line that fits the whole episode: “the moment you get lazy and trust an AI blindly, it will find a way to bite you in the rear”.
§ 06The headlines, graded
| Claim | Status |
|---|---|
| ZCode uploaded users’ code | Confirmed: Z.ai’s two statements accept that uploads occurred and describe the deletion of the bucket that received them |
| It was a Repo Wiki feature | Z.ai’s account. The 3.12.3 audit found the sidecar firing before every prompt as well as on Wiki updates |
| Turning the toggles off stopped it | Not in 3.12.3: both relevant toggles off, the client still packaged and attempted uploads. In 3.14.0 the pipeline is removed, so there is nothing to toggle |
| The data was destroyed immediately | Company claim, unverifiable from outside. The bucket audits describe September 20 onward |
| Nothing left anyone’s machine | Wrong: a 538-file workspace was accepted by the server; others reported accepted small workspaces |
| A 313 MB commercial repo was stolen | Wrong: 564 failed attempts, never uploaded, confirmed at the router by the researcher |
| ZCode is fully open source now | The code is public under Apache-2.0. The history is two commits, pull requests are locked, issues are disabled |
| The code was used to train GLM | Z.ai says never; no external check exists |
| The private key was on the server | Confirmed by the researcher’s reverse engineering; Z.ai’s statements do not address the key |
§ 07What this means if you run coding agents on private code
The four incidents we recorded this month, OpenAI at Hugging Face, Anthropic, Meta and Gemini, were agents reaching outward from a test box that could see more than intended. This one runs the other way. Nothing the model did is in question; the harness around it packaged everything the user could read and sent it where a settings page said it would not. The two stories share a mechanism: a piece of software with a person’s credentials went where its network and its code let it go, and the person’s intent was not part of the decision.
The controls are the same in both directions. Where does the agent run, and what can that place reach? What can it read, and is that the whole disk or the one repository? What leaves the machine, and did you see it leave? A toggle in a settings pane answers none of those; only an egress you can watch and a scope you set do. The researcher’s own defense was a directory lock, not a preference, and his advice to keep it after the fix, because the client can hot-update, is the honest version of every vendor promise: trust the boundary you control, not the one you were told about.
That is how we build AI employees. An employee runs on a computer you scope, holds only the tools and credentials you grant, and the agent classifies every command that reaches your world; the platform rejects any command that arrives unclassified, and you set the threshold above which it waits for you. Whether a vendor later deletes a bucket is not a control you own, so the design does not depend on it.
§ 08What we are watching for
- The full CAICT and NSFOCUS reports Z.ai promised, and whether they address data uploaded before September 18 and the private key.
- Whether github.com/zai-org/ZCode opens pull requests and issues, and whether later commits carry real history.
- ZCode’s privacy policy, which the researcher archived on September 18 still dated June 15, 2026 with no mention of workspace snapshots.
- The vulnerability reporting program’s terms.
- Any independent reproduction of the 3.14.0 audit, and any report of accepted snapshots beyond the small workspaces already described.
§ 09The record
As of September 21, 2026, 13:15 UTC: page opened. Repository metadata read from the GitHub API at 13:02 UTC (created 2026-09-20T12:01:16Z, initial commit 12:06:58Z, open-source commit 21:14:32Z, Apache-2.0, 5,033 stars, 1,412 forks). X posts are id-clocked: the first release announcement 00:54:32 UTC, the ZCode statement 01:23:22 UTC, both September 21; the statement text was read in full in Chrome. The researcher’s report, with its September 19 and September 21 updates, was read at 13:07 UTC; the Feishu statement was read in the V2EX reproduction. Times marked Beijing are UTC+8.
§ 10Sources
- ferstar, Inside ZCode: Silently Uploading Your Entire Git History to the Cloud, September 18, 2026, with updates September 19 and September 21; read September 21, 2026.
- ZCode (@zcode_ai), statement on X, September 21, 2026, 01:23 UTC; read September 21, 2026.
- Z.ai Feishu user-group statement, September 18, 2026, as reproduced on V2EX; read September 21, 2026.
- zai-org/ZCode on GitHub and its API metadata; read September 21, 2026.
- Z.ai, ZCode documentation; read September 21, 2026.
- Our own records: Gemini Hacked Three Companies, September 19, 2026; the OpenAI Hugging Face incident; GLM-5.3-Flash.
Q1Which ZCode versions were affected, and is the current one safe?
The researcher’s packet captures came from client 3.12.3. Z.ai says remediation is complete in v3.14.0, and the researcher’s audit of that build found the upload sidecar dismantled and the upload-credential endpoint returning 404. The researcher still recommends a filesystem lock on the snapshot directory as a tripwire, because the desktop client can receive hot updates.
Q2Did any user code actually reach Z.ai's servers?
Yes, at least one snapshot did. The 313 MB commercial project that made the headlines sat in pending with 564 failed attempts because it exceeded a size limit and never uploaded; the researcher confirmed on a router that those chunks never left the local network. A separate 538-file public-repo workspace, about 15 KB after compression and encryption, was accepted by the server. Others reported accepted small workspaces on Windows.
Q3What does Z.ai say happened to the uploaded data?
That it was destroyed immediately after the Wiki page was generated, and, in the September 21 statement, that no such data is retained and it has never been used for model training. CAICT found the zcode-prod bucket in a zero-data state and NSFOCUS confirmed the bucket itself was deleted. Both findings describe the bucket after September 20; neither can reconstruct the life of data uploaded earlier.
Q4Why does this matter for AI employees and coding agents in general?
Because a harness runs with the user’s credentials and reads what the user can read, and nothing in the model decides what the harness phones home. The four Irregular incidents were agents reaching out from a test box; this was the client reaching in. On CellCog an AI employee runs on a computer you scope with tools you grant, the agent classifies every command that reaches your world, and the platform rejects any command that arrives unclassified. Whether a vendor deletes a bucket is not a control you own.
Q5Where is the primary evidence?
The researcher’s report at blog.ferstar.org, with September 19 and September 21 updates cross-checking the statements against the code; the ZCode account’s statement on X at 01:23 UTC on September 21; the Feishu statement of September 18 as reproduced on V2EX; and the repository itself, whose metadata carries the creation and commit times. Every time in this record is UTC unless marked otherwise.



