Build1 publisher3 min readPublished
ZCode encrypted a developer's Git history with a key only its server could unwrap
A reverse-engineering walkthrough published September 18th traced a 313MB archive in ZCode's local data directory to a 42,411-file commercial workspace whose Git objects and LFS blobs were 86.6% of the payload.
The Engineer · Build desk
What happened
- A developer using the name ferstar found a 313MB encrypted archive inside ZCode's local data directory while clearing disk space, and reverse-engineered the desktop client to work out what it held.
- The archive corresponded to a 345.5MB commercial workspace containing 42,411 files, and its accompanying metadata logged 564 failed upload attempts.
- Ferstar said no private key on the test machine could unwrap the archive's encryption key, because the matching private key was held on Z.ai's servers.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- exposure Rotating a leaked credential does not remove it from the object store, so a snapshot of full history ships secrets a team already believed retired, along with unpushed branches and internal hostnames.
- constraint Downloadable model weights do not answer this question. The packaging and upload decisions live in the Electron bundle and its outbound calls, and that is where a review has to spend its time.
- decision Anyone approving a coding agent on a repository with LFS objects now has to test the network path directly, since the privacy control ferstar examined mapped to training use of content.
- contradiction Local checkpointing and server-held keys pull in opposite directions: the first argues for capture the user can read back, the second means only the vendor ever could.
ZCode asked zcode.z.ai for upload credentials and got back an object key, size limits, Alibaba Cloud Object Storage Service form credentials and an RSA public key [6]. The client then compressed the workspace, encrypted it with AES-256-CTR and wrapped the symmetric key with RSA-OAEP-SHA256. It tried to push the ciphertext straight to Alibaba Cloud's storage, and Alibaba Cloud called back to Z.ai's backend to register the snapshot after receipt [7]. Ferstar said none of the private keys on the test machine could unwrap the archive's key, because the private half was held server-side [8]. As cryptographic construction that is competent work, and it runs in one direction only. A 313MB file of the developer's own repository sat on the developer's own disk, openable only by the vendor [2][8].
The .git directory was 86.6% of the payload, with 196.1MB of Git LFS data and 102.2MB in .git/objects against roughly 46.2MB of source and documentation [5]. Source and docs are about 13% of the 345.5MB workspace [18]. Compression bought about 9%, 313MB out from 345.5MB in [17]. That is what you get when most of the input is already-compressed objects and LFS blobs. Had every one of the 564 recorded attempts [4] carried the whole file, that would be roughly 176GB of egress from one machine [19]. The manifest logged the attempts as failed, not their byte counts [4].
Checkpoint and rollback give a plausible product reason to capture workspace state. ZCode's agent documentation says the product combines workspace state, file references, execution modes and Git branch context during long-running development tasks [11]. The client could not decrypt these bytes [8], and a local rollback needs bytes the client can decrypt. Runtimewire's account, drawn from Tokenstead's reporting of the findings [21], holds that the server-held key plus full repository history gives Z.ai a wider data set than a rollback mechanism would require [12].
Ferstar also compared the visible settings against the packaged code. The control labelled "Optimize Experience" governed whether user content could be used for model training, according to that analysis [13]. Runtimewire presents the comparison under the finding that ZCode's switches did not stop the upload pipeline [13].
Ferstar's test covers one installation, and cannot show how broadly Z.ai deployed the mechanism across ZCode versions, accounts or regions [10]. The method carries over: the packaged app.asar, the plaintext local manifest and the outbound calls were all readable by the user who went looking [1][5]. Z.ai publishes GLM weights and is building ZCode as a first-party environment to compete with Cursor and Claude Code [16]. Whatever you can download of the weights, repository handling is decided by the desktop application and its cloud connections [14]. The company was formed in 2019 out of technology from Tsinghua University's Knowledge Engineering Group, is led by CEO Zhang Peng, was co-founded by Tang Jie, and is listed in Hong Kong [15].
What to watch
- Whether Z.ai publishes a version range, account scope or changelog entry for the snapshot pipeline, or moves the unwrap key to the client.
- Whether other installations reproduce the manifest and the 564-attempt counter. That is what would move this beyond one machine.
- Whether ZCode ships a setting whose effect on the packaging step can be verified from network capture rather than from the label.