The ZCode repository-upload incident is bigger than one coding tool. It exposes a security question developers increasingly need to answer before giving an AI agent access to a project: does โrepository accessโ mean the current file, the working tree, or years of Git history?
That distinction matters because .git can contain information no longer visible in the current codebase, including deleted secrets, old source versions, reflogs, LFS assets, and local branch history. ZCode says the affected upload behavior has been fixed, but the incident leaves a lasting lesson: AI coding agents need explicit data boundaries, not just permission to โaccess the repo.โ
What Actually Happened With ZCode?
On September 18, 2026, developer ferstar published a reverse-engineering investigation of ZCode 3.12.3 after noticing unexpectedly large files under the application's local data directory.
According to the original investigation, the client created encrypted workspace snapshots that could include source files as well as .git, Git LFS objects, reflogs, and repository metadata. The client also contained a pipeline for obtaining upload credentials and sending encrypted archives to Alibaba Cloud OSS.
ZCode subsequently acknowledged repository-data uploads associated with codebase indexing and Repo Wiki, apologized, said the behavior had been fixed, and announced plans for open-source and third-party review. Contemporary coverage reproduced the main points of ZCode's response.
| Claim | Evidence |
|---|---|
| Older ZCode created broad repository snapshots | Supported by reverse-engineering and local snapshot evidence |
| An upload pipeline existed | Supported by reverse-engineered client behavior |
| A small repository successfully reached the service | Verified by the researcher's follow-up test |
| The 313MB commercial repository successfully uploaded | No โ that upload failed |
| Current ZCode still uses the same pipeline | No evidence; researcher reports the old path was removed |
This is the first important information gap to close: the incident was real, but some viral summaries overstated what was successfully transferred.
Did the 313MB Private Repository Actually Upload?
No.
The commercial-project snapshot contained roughly 42,000 files and produced an encrypted archive of about 313MB. According to the researcher's September 19 update, it remained in a local pending state after 564 failed attempts because it exceeded the upload limit. ([blog.ferstar.org](https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/))
A separate smaller public repository did successfully reach the service. It contained 538 files and produced a much smaller encrypted payload.
| Repository | Observed Result |
|---|---|
| 313MB commercial repository | Packaged locally, repeatedly attempted, upload failed |
| Small public repository | Successfully accepted by the remote service |
The correct conclusion is therefore not โevery ZCode repository was uploaded.โ It is that the old client contained a functional repository-upload mechanism whose actual success depended on the snapshot.
Why the `.git` Directory Is the Most Important Part of This Incident
In the researcher's large snapshot, most of the payload was not current source code.
| Snapshot Content | Approximate Share |
|---|---|
.git/lfs/ |
56.8% |
.git/objects/ |
29.6% |
.git/logs/ |
0.2% |
| Current source code and documentation | 13.4% |
That means approximately 86.6% of the snapshot came from .git. ([blog.ferstar.org](https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/))
This changes the security interpretation completely.
An AI agent reading the current source tree may see what the developer intentionally keeps today. Accessing Git history can reveal what the developer thought they had already removed.
Possible historical exposure includes:
- deleted source files
- old API keys or tokens
- previous internal endpoints
- abandoned features
- historical configuration
- local branch activity
- reflog-only states
- large historical LFS assets
The Git reflog documentation explains that reflogs record previous values of local references. Those records can exist locally even when the corresponding history was never pushed to a remote repository.
This gives us a useful security rule:
โRead my projectโ and โread my Git historyโ should be separate permissions.
Why Deleted Secrets Can Still Exist After You Remove Them From Code
Deleting a credential from the latest file does not necessarily delete it from Git.
A developer may accidentally commit an API key, remove it in the next commit, and see a completely clean current file. The earlier blob can still remain reachable through repository history.
GitHub's guidance on sensitive-data removal explicitly recommends revoking or rotating exposed credentials before rewriting history.
That order matters:
- Invalidate the credential.
- Remove sensitive history where appropriate.
- Prevent the secret from being committed again.
For AI coding agents, this means a history-aware feature can access data that a normal editor view no longer exposes.
It also explains why a read-only agent is not automatically low risk. Read-only access can still leak valuable information if its filesystem scope is too broad or if retrieved content is sent to a remote model.
Model Context, Telemetry, Training, and Repository Uploads Are Not the Same Thing
Another major lesson is that a single โprivacyโ toggle cannot represent every type of data flow an AI coding tool may have.
| Data Flow | Typical Purpose |
|---|---|
| Inference context | Send code needed to answer the current task |
| Telemetry | Measure crashes, reliability, and usage |
| Model-training data | Improve future models or product behavior |
| Repository index | Search and understand a project more efficiently |
| Cloud snapshot | Preserve broader workspace state |
| Sync / backup | Restore data across sessions or devices |
The affected ZCode version is important because the researcher reported that disabling its optimization/training option did not disable the separate snapshot pipeline. The report also claimed the Repo Snapshot Indexing toggle did not prevent packaging and upload attempts in that version. ([blog.ferstar.org](https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/))
This leads to a rule that applies well beyond ZCode:
โDo not train on my dataโ does not mean โdo not transmit my data.โ
A cloud model still needs inference context. Telemetry may travel through another endpoint. Sync may retain another copy. Repository indexing may have its own data path.
The same distinction appears when a local AI agent uses cloud tools: privacy depends on the exact data crossing the boundary, not simply on where the main agent process runs.
Encryption Does Not Answer the Most Important Privacy Question
The affected ZCode snapshot was encrypted before upload.
The reverse-engineering report describes AES-256-CTR encryption for the archive and RSA-OAEP-SHA256 wrapping for the symmetric key. The RSA public key was provided by the service, while the corresponding private key was not stored locally. ([blog.ferstar.org](https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/))
That protects data differently from user-controlled end-to-end encryption.
| Protection | What It Means |
|---|---|
| TLS / transport encryption | Protects data while crossing the network |
| Cloud encryption at rest | Protects stored bytes from some infrastructure threats |
| Provider-controlled key | The service may retain technical ability to decrypt |
| User-controlled end-to-end key | The service does not possess the required decryption key |
So โthe repository was encryptedโ is incomplete.
The stronger question is:
who can decrypt it?
This same principle applies to private RAG, cloud backup, AI memory, and any system that claims data is protected because it is encrypted.
How Much Repository Access Does a Coding Agent Actually Need?
Coding agents legitimately need more context than traditional autocomplete. A repository-wide refactor may require many files. A debugging agent may need tests, dependency metadata, Git state, and build output.
But โthe agent may need broad contextโ does not imply โevery feature should receive every byte in the repository.โ
| Data Scope | Sensible Default |
|---|---|
| Current file | Allow for relevant tasks |
| Referenced source files | Allow |
| Whole source tree | Task-dependent |
.gitignore-excluded files |
Exclude |
.env / credentials |
Block |
.git objects |
Exclude unless explicitly required |
| Reflogs | Exclude by default |
| Git LFS cache | Exclude unless required |
| SSH / cloud credentials | Block |
| Full remote snapshot | Explicit consent |
This is a data-access version of the same principle used in a tool-execution trust boundary: the model's ability to request something should not automatically grant authority to access or export everything nearby.
For coding agents, we need two independent boundaries:
- Action boundary: what can the agent change or execute?
- Data boundary: what can the agent read or send?
An agent with no write permission can still create serious privacy exposure if its read and network permissions are unrestricted.
What Did ZCode Change After the Incident?
The incident should not be described as if the same behavior is known to exist in current ZCode versions.
In a follow-up inspection of ZCode 3.14.0, the researcher reported that the previous upload sidecar had been removed and the old credential endpoint returned 404. The inspected path retained local checkpoint functionality without the earlier remote-upload mechanism. ([blog.ferstar.org](https://blog.ferstar.org/en/posts/zcode-silent-workspace-snapshot-upload/))
Current Repo Wiki documentation also describes a much narrower data boundary.
It says Wiki context excludes:
.git- dependency directories
- build output
- caches
- local runtime state
- supported
.gitignoreexclusions - suspected sensitive configuration files
- symlink targets
Repo Wiki output is documented as local application data rather than content written back into the repository.
This is materially different from the snapshot behavior reported in version 3.12.3.
Is Open Source Enough to Make a Coding Agent Private?
No.
Open source can make a client easier to audit, but an open-source application can still send source code to cloud models, upload telemetry, sync state, or rely on provider-controlled storage.
The more useful checklist is:
| Question | Security Property |
|---|---|
| What can the agent read? | Local data scope |
| What can leave the machine? | Egress boundary |
| Why is it transmitted? | Purpose limitation |
| How long is it retained? | Persistence |
| Who controls encryption keys? | Decryption authority |
| Can the behavior be disabled? | User control |
| Can outsiders verify it? | Auditability |
That is why a private AI architecture is defined more by its data flow than by whether its software license happens to be open source.
How Should Developers Audit a New AI Coding Agent?
Developers do not need to reverse-engineer every app, but a new agent should not receive a sensitive commercial repository as its first test environment.
- Read the data-handling documentation. Separate inference, telemetry, training, indexing, sync, and backup.
-
Check exclusion rules. Look specifically for
.git,.env, ignored files, dependencies, credentials, and symlinks. - Start with a disposable repository. Use non-sensitive code first.
- Inspect local app storage. Unexpected large caches or snapshots may reveal hidden data scope.
- Observe outbound traffic. Firewall, DNS, proxy, or router logs can identify remote services.
- Use harmless canary files. Test whether unrelated files enter model or upload context.
- Grant the narrowest permissions first. Expand them only when a specific task requires it.
This is also where least-privilege agent design helps, as long as โread-onlyโ is combined with narrow paths and controlled outbound data rather than unlimited repository visibility.
What a Local-First Coding Agent Should Do Differently
Local-first does not mean every task must run offline.
It means local data stays inside the local trust boundary by default, and external transmission is deliberate rather than incidental.
| Local-First Principle | Preferred Behavior |
|---|---|
| Repository indexing | Keep symbols, embeddings, and metadata local where practical |
| Remote model context | Send only task-relevant code |
| Git history | Exclude unless the task explicitly needs history |
| Secrets | Filter before context construction |
| Remote upload | Show scope and request explicit consent |
| Training consent | Separate from inference permission |
| Sensitive repositories | Offer fully local model and indexing paths |
| Network dependency | Document what stops working offline |
This principle is broader than coding. A truly local AI workflow has to keep its critical data path local end to end; a locally installed model is not enough if embeddings, indexing, authentication, or file processing silently depends on a remote service.
For hybrid systems, the stronger pattern is to keep private files behind a local service and expose only the minimum required context to approved remote tools. That is the same approach used when designing an agent that uses cloud services without exposing its entire local filesystem.
The Bigger Lesson: Repository Access Is a Security Permission
The lasting lesson from ZCode is not โnever use cloud coding agents.โ It is that repository access has become a security permission in its own right.
A modern coding agent may combine:
- full-project reading
- Git awareness
- terminal execution
- browser access
- remote models
- background tasks
- long-term memory
- autonomous file editing
That means developers need to review more than what commands an agent can execute.
They also need to ask:
- What files can it observe?
- How far back into history can it see?
- Which of that data leaves the machine?
- Which service receives it?
- How long is it retained?
- Who can decrypt it?
For AI coding agents, privacy is no longer simply about whether the model trains on your code. It is about whether the agent's data boundary matches the task you actually asked it to perform.
Frequently Asked Questions About the ZCode Repository Upload Incident
Did ZCode upload the researcher's entire 313MB private repository?
No. The researcher reported that the large commercial-project snapshot was packaged and repeatedly queued for upload but failed because of its size. A separate smaller public repository was successfully accepted by the service.
Can `.git` contain secrets that are no longer in the current code?
Yes. Git objects and historical commits can preserve earlier versions of files after sensitive content has been removed from the working tree. Reflogs can also contain local reference history that may never have been pushed remotely.
Does disabling AI training stop a coding agent from uploading code?
Not necessarily. Training, inference, repository indexing, telemetry, cloud sync, and backup are separate data flows. Disabling model-training consent does not automatically disable data transfers required by another cloud feature.
Has ZCode fixed the repository snapshot issue?
ZCode says the issue has been fixed. The original researcher reported that the old remote-upload path was absent in version 3.14.0, while current Repo Wiki documentation explicitly excludes .git, dependencies, build outputs, caches, and several sensitive file categories from Wiki model context.
Is an open-source AI coding agent automatically private?
No. Open source improves auditability, but privacy still depends on what files the tool reads, what data leaves the device, which cloud services receive it, how long it is retained, and who controls the encryption keys.
Tech & AI HUB
More to Read

What It Has Never Seen? Talkie-1930 and the Einstein Test
Talkie-1930 tests whether AI can generalize beyond its training era, separating reasoning from memorization with a 1930 knowledge cutoff.

Gemini 3.8 Live Explained: When AI Can Watch, Talk, and Think at the Same Time
Gemini 3.8 Live combines real-time voice, vision, and background reasoning, making local filtering and privacy more important for always-on AI.

Grok 4.8 Is a 2.5T Model โ But the New C++ Stack Is the Bigger Story
Grok 4.8 pairs a reported 2.5T model with a new C++ training stack, showing why frontier AI is becoming an infrastructure race.

