A developer freeing up disk space on a 256GB MacBook Air found the file that would force one of China’s most prominent AI labs to publish the source code of its flagship coding tool. Inside ZCode’s data directory sat a 313MB encrypted archive of his commercial project, complete with its entire Git history, waiting to be shipped to Alibaba Cloud storage. A metadata file beside it recorded 564 failed upload attempts. He could not open the archive himself, because the only decryption key lived on Z.ai’s servers.

Three days later, on September 21, Z.ai published ZCode on GitHub under the Apache-2.0 license, apologized, and said the data had never been retained or used to train its GLM models. The repository crossed 3,400 stars within a day. The company also said two Chinese security firms had verified that the storage bucket holding uploaded snapshots was empty and had since been deleted.

The findings came from a researcher who publishes as ferstar and who, by his own account, was a paying GLM Coding Max subscriber. In a September 18 write-up, he documented that his ~/.zcode folder had grown past 700MB and traced the bulk of it to a checkpoints directory. Unpacking the Electron app bundle, he reconstructed the pipeline: the client requested credentials from zcode.z.ai, received an RSA public key plus signed form credentials for Alibaba Cloud object storage, packed the workspace into a tar.gz, encrypted it with AES-256-CTR, wrapped the symmetric key with RSA-OAEP, and posted the result directly to the storage bucket, bypassing Z.ai’s own application servers.

The plaintext manifest showed what was inside. The snapshot covered 42,411 files from a 345.5MB workspace. Git LFS caches alone accounted for 196.1MB, or 56.8 percent; .git/objects added 102.2MB, or 29.6 percent. Actual source code and documentation made up just 46.2MB, or 13.4 percent. In total, the .git directory was 86.6 percent of the payload, meaning the archive held every commit, every deleted secret, and every unpushed branch since the project began.

“A key that only the server can use serves exactly one purpose: making sure the server can read your code whenever it wants,” ferstar wrote. He also found that the two settings a user might expect to stop the behavior, Optimize Experience and Repo Snapshot Indexing, only governed training consent and server-side indexing. The capture sidecar was instantiated unconditionally at startup, fired before every prompt and on task completion, and generated up to 62 capture events in a single session. Deleting the archive did not help: within half an hour a fresh 313MB copy appeared with the retry counter at 565. “If the software won’t let you turn it off, use the OS kernel to lock it in a cage,” he wrote, recommending an immutability flag on the checkpoints directory.

One clarification matters. The 313MB archive never left his machine; it failed 564 times because it exceeded the server’s size limit, and ferstar confirmed via router logs that the encrypted chunks stayed on his local network. But a separate public-repo workspace of 538 files did upload successfully and was accepted by the server.

Z.ai responded the same day in its Feishu user community, attributing the uploads to a default-on codebase indexing feature that powers session checkpoint restore, version rollback, and a cloud-generated Repo Wiki. It said uploaded data was destroyed immediately after Wiki generation, the feature had been fixed, and every user would receive an extra weekly quota reset. The September 21 statement on X went further: remediation was complete, a vulnerability reward program would follow, and the referenced code data “is not retained” and “has never been used for model training.” According to the statement, the China Academy of Information and Communications Technology confirmed the zcode-prod bucket was in a zero-data state, and NSFOCUS found “no functional path capable of triggering the generation of local repository snapshots or transmitting local files externally” in the remediated v3.14.0 client, which strips the upload pipeline entirely.

Why it matters

Z.ai built its reputation on open weights, and by TNW’s reckoning it is approaching $1 billion in annual sales while giving away its best models. That leaves the paid product as the software wrapped around the models, and that software is precisely the part nobody could inspect. ZCode’s privacy policy, unchanged since June 15, describes collecting code submitted through conversation. A background snapshot of a full Git history is a different category of data, and a training toggle that does not govern transmission is a distinction most users will not draw until it is too late.

The comparison developers reached for was Grok Build, caught uploading whole repositories earlier this year against explicit marketing claims. xAI’s recovery included a retest by outsiders confirming uploads had stopped. Z.ai’s open-source drop makes that kind of retest possible; RuntimeWire notes the repository contains the desktop host, web server, CLI agent, and backend services rather than a thin wrapper. But the repo launched with only two commits, no SECURITY.md, and a NOTICE file that explicitly scopes out anything past Z.ai’s gateway. Client source can prove the uploader is gone. It cannot prove what happened to snapshots accepted before September 18, or whether the RSA private key was shared across users. An engineer at a major Chinese robotics firm told the South China Morning Post the company had already banned Z.ai tools internally.

What to watch

The full third-party assessment report Z.ai has promised is the document that will decide whether this closes. Look for independent researchers, ferstar included, to diff the published source against the shipped 3.14.0 binaries and confirm no capture path remains reachable through hot updates. Watch whether the privacy policy is amended, whether the reward program publishes scope and amounts, and whether Z.ai answers the per-user versus shared-key question. And note the escape hatch developers already have: GLM models run inside other coding tools, so users can abandon the client without abandoning the model, an outcome Z.ai’s open-weights strategy was never meant to produce.

“A key that only the server can use serves exactly one purpose: making sure the server can read your code whenever it wants.”
— ferstar, Developer and security researcher who reverse-engineered ZCode
313MB
Encrypted archive of a 345.5MB commercial workspace
564
Failed upload attempts logged for one snapshot
42,411
Files packaged in a single snapshot
86.6%
Share of payload that was the .git directory