GPT-56T 861 —
MUSE-SPK 835 -0.7%
GPT-56SC 828 -5.2%
QWEN-38X 824 —
CL-OP55X 822 —
GROK-46H 822 -5%
GPT-6A 820 —
GLM-5 784 -8.4%
CL-FAB5H 743 -5.6%
KIMI-K3X 742 -8.4%
CL-OP5H 720 -5.8%
CL-OP5X 709 -18%
CL-OP46H 698 -5.9%
CL-OP47H 690 -5.9%
GEM-38FH 677 +0.1%
GEM-37FH 657 -24%
GPT-56S 622 —
CL-OP47 582 -0.7%
GPT-55H 582 —
INKL 531 —
GEM-31P 513 —
GEM-3P 499 —
CL-OP46 496 -0.2%
CL-OP48 490 —
GPT-56T 861 —
MUSE-SPK 835 -0.7%
GPT-56SC 828 -5.2%
QWEN-38X 824 —
CL-OP55X 822 —
GROK-46H 822 -5%
GPT-6A 820 —
GLM-5 784 -8.4%
CL-FAB5H 743 -5.6%
KIMI-K3X 742 -8.4%
CL-OP5H 720 -5.8%
CL-OP5X 709 -18%
CL-OP46H 698 -5.9%
CL-OP47H 690 -5.9%
GEM-38FH 677 +0.1%
GEM-37FH 657 -24%
GPT-56S 622 —
CL-OP47 582 -0.7%
GPT-55H 582 —
INKL 531 —
GEM-31P 513 —
GEM-3P 499 —
CL-OP46 496 -0.2%
CL-OP48 490 —
← Back to feed

ZCode Silently Packages Entire Git Histories and Uploads Them to Alibaba Cloud — No UI Toggle Stops It

On September 17, 2026, developer ferstar published a reverse-engineering walkthrough of ZCode, Z.ai’s official AI coding desktop app built on GLM open-weight models. The finding: whenever the app is logged in, ZCode silently packages the user’s entire workspace — including the complete .git history, LFS asset cache, reflogs, and global app configs — encrypts it, and uploads the archive directly to Alibaba Cloud object storage (Aliyun OSS).

The archive ferstar found on their own machine: 313MB encrypted package from a 345MB commercial workspace, 42,411 files, 564 failed upload attempts still waiting to retry. The .git directory alone accounted for 86.6% of the payload.

The Key Is Only On Z.ai’s Servers

ZCode uses envelope encryption. The payload is encrypted with AES-256-CTR, and the symmetric key is wrapped using an RSA-OAEP public key delivered by Z.ai’s server at upload time. The corresponding private key never touches the user’s machine.

The 313MB ciphertext sitting on the user’s own disk cannot be decrypted by the user. The ZCode client cannot decrypt it either. Only Z.ai’s backend holds the key.

Upload flow, reconstructed from the client’s app.asar:

  1. ZCode requests credentials from zcode.z.ai, which returns OSS form signatures, a snapshot ID, a per-round RSA public key, and an Aliyun OSS endpoint.
  2. The client packs the workspace to tar.gz, encrypts with AES-256-CTR, wraps the symmetric key with the server-provided RSA public key.
  3. The archive posts directly to Aliyun OSS, which callbacks to Z.ai’s backend to register the snapshot.

A single session generated up to 62 capture events — triggered before every prompt and on task completion.

No Toggle Stops It

ZCode’s settings expose two relevant switches:

  • Optimize Experience (optimizeAgentExperienceEnabled): controls only whether data is used for model training. Snapshot capture and upload continue regardless.
  • Repo Snapshot Indexing (repoSnapshotIndexingEnabled): controls only whether the server builds a searchable index. Local packaging and upload continue regardless.

The host assembly code instantiates the capture sidecar unconditionally at startup. The only requirement is a valid JWT from the token provider. The pipeline is not an agent tool — it runs as a host-level sidecar outside the agent tool loop, which is why no permission setting in the agent interface reaches it.

ZCode’s privacy policy states it collects “text, files, and code submitted during conversations.” Across the entire policy, FAQ, and changelog, there is no mention of packaging and uploading complete workspaces and full Git histories.

What a Git Object Store Contains

A Git object store is not a snapshot of the working tree — it is the complete lineage of the repository since the first commit. Deleted API keys from old commits survive in object history. Unpushed branch names that reveal unreleased product plans are in there. Internal hostnames and repository paths from .git/config are in there. An uploaded archive is years of engineering history, not just currently open files.

Independent Windows testing confirmed identical behavior. One researcher found 32 workspaces with snapshots taken; 14 showed no failure records, indicating successful uploads. The largest package was 107MB. A secondary finding: ZCode’s global model-providers.json and provider_config.json — which store API keys in plaintext — are included in the uploaded manifest across every workspace.

The Confirmation

When ferstar’s post circulated on X, the most prominent reply came from an account affiliated with the ZCode team: “hey I am sorry to let you find it.” The official Z.ai account had not responded as of publication. The post passed 276,000 views within 13 hours.

ZCode launched in July 2026. Its pitch ran on trust — Z.ai positioned the harness against Claude Code weeks after Claude Code’s hidden-telemetry controversy, with open weights cited as the alternative to vendor control. A Z.ai executive, asked directly whether ZCode would include “any sort of spyware,” replied the company would not implement “anything beyond what’s listed” on the ZCode website.

The Fix

Blocking the checkpoint directory at the kernel level stops uploads while leaving chat, autocomplete, and tool calls functional:

macOS/Linux:

sudo chattr +i ~/.zcode/v2/checkpoints

Windows (PowerShell):

icacls "$env:USERPROFILE\.zcode\v2\checkpoints" /inheritance:r /grant "${env:USERNAME}:(OI)(CI)(RX)" /deny "${env:USERNAME}:(OI)(CI)(WD,AD,WEA,WA)"

The checkpoint rollback UI stops working. That feature required uploading your code in the first place.

The Model Layer Is Not the Trust Surface

Running open-weight GLM models locally is real: no per-token bill, no vendor lock-in. The ZCode case sharpens the boundary past the model. A locally-running open-weight model inside a cloud-phoning harness is not a local deployment. The trust surface includes the runtime, the desktop app, and the update pipeline — not just the weights.