ZCode Said It Was Only Indexing Code. It Also Opened the Project History.
ZCode was accused of uploading workspace snapshots, Git history, and LFS data during codebase indexing. The official response says the issue is fixed, but public reverse-engineering evidence leaves important questions unanswered.
When you wake up an AI coding tool, you usually want it to change a few lines and run the tests. You do not expect it to open the project’s old records while it is at it.
That is where the ZCode controversy begins. Developers in the community reported that, while indexing a codebase, ZCode may package the workspace into an encrypted archive and upload it to the cloud. The material under discussion was not limited to the files currently open. It reportedly included Git history, LFS caches, and parts of the local configuration.
The sharpest question is not whether code can ever be sent to the cloud. It is who decided how much to send, whether the user could see that decision, and whether all of it was actually needed for the task.
On September 18, several media outlets reported on the controversy. ZCode later said that the issue came from its “codebase indexing” feature and that it had been fixed. The company apologized for the codebase data upload, said it would open-source the ZCode codebase, bring in third-party reviewers, and publish further review updates.
It is still too early to say that every user had an entire repository uploaded. The problem is serious enough without making that claim: can a tool use “better results” as a reason to expand the user’s data permissions on its own?
The harder part is that the official explanation does not fully line up with the public evidence. The company knows its product best, but it is also the party being questioned. A short announcement cannot be the only stamp of approval. Community reverse engineering cannot reveal the entire server-side story, but it can show what the client actually did.
The announcement sounds small. The evidence does not.
The official response puts the incident under “codebase indexing” and says the issue has been fixed. That sounds like a bad switch or a few lines of broken code. It does not answer the questions that matter most: why would indexing need complete Git objects, LFS caches, and history metadata? Why create an encrypted archive first? Why send it to a third-party object store? When did the user agree to any of this?
Public reverse-engineering material is more specific than the announcement. Researchers showed locally generated encrypted archives, reported Git history and LFS-related data inside them, and traced a client upload path to Alibaba Cloud OSS. Media reports describing an independent check also mentioned two striking numbers: one failed upload was retried 564 times, and a local Git inventory contained 2,196 entries.
Those numbers do not prove that every user encountered the same behavior. They do show that “reading a few current files” is not a sufficient explanation. If an indexer is only looking up code, why is it turning over such a thick history book? If the company believes those files never left the machine, it should publish a file inventory and a reproducible test instead of putting the whole incident inside the words “indexing feature.”
Encryption does not settle the matter either. An encrypted archive shows that data was gathered into one package. An OSS upload path shows that the package left the client. Neither fact tells us that the server deleted it immediately, and neither proves that the user agreed.
The promises to open-source the code and bring in third-party reviewers are better than silence. They are still remediation, not a rubber stamp for the old announcement. Until the code, version differences, build artifacts, and review report are public, “the issue has been fixed” remains a statement from the party involved. Users should be able to see what changed in the requests, whether Git is still included in the archive, whether the upload domain changed, and which piece of logic was removed.
At this point, it would be inaccurate to say that the company has explained everything. A closer description is that the announcement acknowledged a problem while making it sound smaller than the public evidence suggests. It did not directly explain the Git history, LFS data, encrypted archive, or OSS upload, and it did not spell out the affected versions or the fate of the data. Avoiding the observed client behavior and wrapping the entire incident in “indexing” is, at minimum, misleading disclosure.
The problem is not uploading. It is uploading beyond the user’s expectation.
Cloud-based AI coding tools often need to send code somewhere to complete a complex task. That is not unusual by itself.
Users can generally accept clear cases: selecting a block of code and asking for an explanation, submitting a file for editing, enabling cloud indexing in settings while seeing which directories it processes, or choosing a remote agent and knowingly letting it run a project in the cloud.
The trouble starts when codebase indexing becomes a background action that users do not clearly notice.
If the client packages and uploads the workspace as soon as someone signs in, opens a project, or enables an intelligent feature, the user is not making a clear “send this code” choice. They are opening a tool and discovering later that the tool copied much more than expected.
That is why the community reaction was so strong. The issue is not whether an AI tool may process code. It is whether the tool can quietly widen the scope of data processing without informed consent.
Git history is more sensitive than the current code
Some people ask: “If the code was uploaded, what makes Git history different?”
Git history can be much more sensitive than the current working tree.
The current code may have been cleaned up. Older commits may still contain:
- API keys that were once committed;
- service endpoints that were deleted but still work;
- abandoned database connection strings;
- internal project names and customer requirements;
- unreleased feature branches;
- files that were deleted later but can still be recovered from history.
Even after a developer runs git rm, sensitive content may remain in commits, reflogs, the object database, or an LFS cache.
Uploading the current files exposes what the project is today. Uploading the full Git history may expose the project from its first commit to the present. Those are different levels of risk.
That is why “we are only indexing the codebase” cannot, by itself, explain uploading the full Git history. Indexing the current source usually does not require every historical commit, LFS object, and local repository record. If a product truly needs them, it should explain the purpose and ask the user to opt in. Otherwise, “indexing” becomes a product label that hides the collection scope.
Encrypted upload does not replace permission
One possible defense is: “The uploaded data was encrypted.”
That answers one question about transmission: how easy would it be for someone in the middle to intercept the data? It does not answer who can decrypt it, how long it will be stored, or why it was uploaded without a clear choice.
Encryption is not authorization.
A product can encrypt data that a user did not know was being uploaded and still store it. That does not make the behavior transparent or proportionate. Encryption protects confidentiality in transit and at rest; it cannot replace notice, data minimization, and meaningful consent.
Users need to know:
- which directories were read;
- whether
.git, LFS, and untracked files were included; - whether environment variables and local configuration were included;
- which service provider received the data;
- how long it will be retained;
- whether it will be used for model training or product improvement;
- how it can be deleted;
- whether uploads continue after the feature is disabled.
Without clear answers, users can only hand over their development environment on trust. For a product that handles source code, “trust us” is not a security control.
This is a product-boundary failure, not just an ordinary bug
ZCode attributed the issue to codebase indexing and said it had been fixed.
From an implementation perspective, the problem may have involved an indexer reading too broad a workspace, a client packaging the project to avoid repeated analysis, or a team treating code context as automatically authorized.
That still makes this more than an ordinary bug.
It concerns the product’s defaults: how much it reads, which files it uploads, whether it includes history, whether it may use a third-party cloud store, how long data is kept, and whether it can be used to improve a model.
Those are product decisions. They should not be decided for the user by an implementation detail.
AI products have a recurring temptation: take more data to make the model smarter, grant more permissions to make the agent more automatic, and hide more decisions to make the workflow feel effortless.
That may make the product smoother in the short term, while concentrating an irreversible leak risk on the user. The product gets more context; the user carries a larger exposure. A default setting should not make that trade on the user’s behalf.
What evidence is still needed
ZCode’s public follow-up actions include fixing the feature, apologizing, planning to open-source the codebase, bringing in third-party reviewers, and publishing review updates. Open source and independent review are the most valuable parts of that plan.
Users still need concrete technical information:
- which version introduced the behavior;
- which versions were affected;
- exactly what data was uploaded;
- where it was uploaded;
- whether
.gitand LFS were included; - how long the server retained it;
- whether anyone could download or decrypt it;
- how deletion of historical data can be verified;
- whether the fixed client still performs similar work.
If all users can see is “the issue has been fixed,” they still cannot judge whether the risk has ended.
Open-sourcing a repository does not automatically complete an audit. Reviewers also need to look at the scope of the release, the published version, the build process, and whether the public source matches the client users actually run.
Open source is the beginning of rebuilding trust. It is not proof that the incident is over.
What developers can do now
Until tools like this finish their review, developers can take a few inexpensive precautions.
First, do not point an AI coding tool at a real repository containing production secrets. Start with a sanitized copy. Remove .env files, cloud credentials, SSH keys, database connection strings, customer data, and historical branches that the task does not need.
Second, check for .git, .gitignore, LFS caches, and build artifacts. “I did not select that file” does not mean the tool cannot read it. Indexing features often scan a directory rather than the editor’s current selection.
Third, watch network requests and local temporary files. If the client creates a large archive during sign-in, indexing, or startup, check when it was created, how large it is, whether it contains Git objects, which domain receives it, and whether uploads continue after the feature is disabled.
Fourth, treat an AI coding tool as a third-party code-processing service, not as an ordinary editor. An editor usually changes local files. An AI agent may read, execute, compress, upload, and call external services. Those are different permission models.
The default should be least privilege
The sentence the industry should remember from this incident is simple:
Letting an AI change your code does not mean letting it copy the project’s entire history.
AI coding tools need context, but context needs boundaries.
A more responsible design would:
- process only the files required for the current task by default;
- exclude
.git, secret files, and hidden directories by default; - require separate permission for full-repository indexing;
- show the file list and data size before uploading;
- let the user cancel every upload;
- offer a local indexing mode;
- show the cloud retention period clearly;
- provide a way to delete historical data;
- separate “use for this task” from “use for model improvement.”
This costs some automation and adds a few confirmation steps. That is the real cost of privacy.
If a tool asks for the entire repository, it should at least make clear what the user is handing over. Otherwise, it is offering an unexplained expansion of permissions rather than intelligence.
On the surface, the ZCode incident is a dispute about code uploads. At a deeper level, it is a trust problem for the whole AI coding industry. As agents become more able to act for users, their defaults cannot remain hidden in the background.
Developers need visible permissions, auditable code, reversible data handling, and evidence specific enough to check. The real professionalism of an AI coding tool is not how much code it can read. It is whether it knows which code it should leave alone.
Sources
- ZCode user feedback and support
- ZCode user suggestions and feedback repository
- Public reports and reverse-engineering material: ZCode silently uploaded Git history
- Official response and media coverage: ZCode codebase data controversy
This article was compiled from community technical disclosures, independent review articles, public media reports, and ZCode’s official response. The criticism concerns the gaps between the announcement and the client behavior already described publicly. The scope of server-side retention, decryption, and deletion should still be judged against reproducible third-party audits, public source code, and logs.
More Articles