Two September 2026 incidents break two different assumptions that developers make about AI coding agents: Plugin4Shell showed that a plugin pinned to a reviewed version can still run different code, and ZCode showed that a privacy toggle and a privacy policy may not describe what the app actually sends. They are not the same kind of problem, and treating them as one "AI agent security story" hides the parts that matter for a decision: who the adversary is, which versions are affected, and what can still be checked from the outside. This article separates the two using the researchers' own write-ups, the vendors' statements as reported by those researchers, and the primary documents that could be opened.
This analysis is based on primary security research, vendor documentation, and a published privacy policy, verified as of 6 October 2026.
The two incidents, normalized
| Plugin4Shell | ZCode workspace upload | |
|---|---|---|
| What it is | Supply-chain vulnerability in how agents install pinned plugins | Vendor client behavior: workspace snapshots sent to the vendor's cloud |
| Broken assumption | "A pinned commit is the code that runs" | "Settings and the privacy policy describe what leaves my machine" |
| Who acts | A third party who controls a plugin's repository | The vendor's own client, while the user is logged in |
| User action needed | None, because plugin auto-update runs in the background | None beyond being logged in |
| Products named | Claude Code, Codex, GitHub Copilot, Gemini CLI | ZCode 3.12.3 (the version the researcher analyzed) |
| Public disclosure | 17 September 2026 (Air Security) | 18 September 2026 (independent researcher "ferstar") |
| Evidence of real-world harm | Working proof of concept in the sources reviewed | Vendor acknowledged uploads occurred and some users were affected |
| How the fix is delivered | Agent-side version check; patched or unpatched per product | Client update that removes the upload pipeline |
Plugin4Shell: how a pin gets bypassed
Marketplaces protect users by pinning each plugin to one reviewed Git commit. According to Air Security's disclosure, the affected agents check out that pinned value but never confirm the working tree actually landed on it. In Claude Code, Codex, and GitHub Copilot, an attacker who controls the plugin's repository can create a branch named after the 40-character pinned hash and make it the default branch. Git prefers a branch over a commit when both share a name, so the checkout silently resolves to attacker code while the install reports success at the pinned commit.
Gemini CLI fails differently. It fetches the pinned commit correctly, then checks out a reference called FETCH_HEAD, which a repository can shadow with a default branch of the same name. The commit it fetched is discarded. Air's proposed fix is one assertion run inside the agent after checkout: confirm the resolved HEAD equals the pinned hash, or abort.
The "zero-click" part comes from background updates. Air reports that Claude Code and Codex enable plugin auto-update by default, so when a marketplace re-pins a plugin to a new, still-benign commit, every installed copy updates itself, and the attacker's branch trick fires at that moment. Anthropic's own marketplace documentation confirms the surface involved: plugin sources can be pinned to a ref or hash, and a plugin can be fetched from a Git repository on any host. That second detail matters for the next section.
The precondition most summaries skip
Air states that the branch-name variant works only where a host allows branches named like a hash. GitHub rejects such names outright, while Bitbucket and self-hosted Git servers accept them. A marketplace hosted on GitHub therefore blunts that variant, but Air notes this does nothing for the Gemini CLI variant, and the agent-side fix remains the only complete one. This is why the same flaw is more serious in an enterprise that runs a self-hosted marketplace than for a user installing from a GitHub-hosted community directory, even though both are affected in principle.
Patch status, one product at a time
| Agent | Status reported by Air Security | Auto-update default |
|---|---|---|
| Claude Code | Fixed in 2.1.179; Anthropic confirmed the fix on 17 June 2026, three months before public disclosure | On |
| Codex | Fixed in 0.146.0; verified on 12 August 2026 | On |
| GitHub Copilot | Disclosed to Microsoft; no fix shipped as of Air's 17 September post | Not stated |
| Gemini CLI | Google confirmed on 4 August 2026 that it will not patch a deprecated product; Air advises moving to Antigravity | Not stated |
Two cautions apply to this table. First, Air Security sells agent-supply-chain products and says its own customers were not affected, so the patch statuses are its account rather than vendor advisories; no vendor advisory or CVE identifier appeared in the sources reviewed. Second, the Copilot row is dated to Air's publication; Microsoft may have shipped a fix since, which is worth checking before relying on it. Our pricing comparison of Cursor, GitHub Copilot, and Claude Code covers what each of those products costs, but not their patch cadence.
ZCode: what was sent, and what wasn't
The ZCode finding comes from a paying subscriber who goes by ferstar and published a reverse-engineering report on 18 September 2026. In version 3.12.3, the client packaged the open workspace, including the full Git directory, the large-file cache, and reflogs, while the user was logged in. It encrypted the archive with a key whose public half the server supplied and whose private half only the vendor holds, then uploaded it to Alibaba Cloud storage. Captures ran before every prompt and after certain task types, up to 62 times in one session.
The most quoted number is 42,411 files in a 313 MB encrypted archive, of which 86.6% was the Git directory. A detail that many summaries drop: the researcher later clarified that this particular archive failed to upload 564 times and never left his network, which he confirmed through his router's connection records. A separate, tiny public-repository workspace of 538 files did upload and was accepted by the server. So the accurate statement is that uploads demonstrably occurred, and that exposure depended on workspace size and whether the upload succeeded.
Why Git history is the sensitive part
A Git directory holds every past version of every file. The researcher lists deleted API keys, unpushed branch names that reveal unreleased plans, and internal hostnames from the repository configuration as examples of what a history carries that a current working tree does not.
The vendor's account against the researcher's findings
| Question | Z.ai's statement (18 September) | Researcher's findings |
|---|---|---|
| What triggered uploads | A "codebase indexing" feature; Repo Wiki generation may trigger an upload | A resident sidecar triggered before every prompt, not only on Wiki generation |
| Could users stop it | Not addressed; feature was on by default early on | Two settings toggles did not stop local packaging or upload; they governed training consent and server-side indexing |
| Why upload at all | Supports checkpoint restore and Wiki | After the code was open-sourced, checkpoints turned out to use local Git only |
| What happens to the data | Destroyed right after the Wiki is generated | Cannot be verified externally; a server-only key sits oddly with a restore feature |
| Fix | "Fixed"; later cites third-party audits and deletion of the storage bucket on 20 September | Version 3.14.0 removes the pipeline; 3.14.3 checked on 23 September and found clean |
ZCode's privacy policy is dated 15 June 2026. It says the service collects text, files, and code submitted in conversations, and that the optimization program is off by default. It contains no mention of workspace snapshots or Git history, which matches the researcher's reading. The audit results Z.ai cites are known here only through the researcher's summary of the company's statement; the full reports and the official repository could not be opened for this analysis, so they are treated as claimed, not confirmed.
One limit is built into the researcher's own reasoning: emptying a storage bucket on 20 September cannot show what happened to data uploaded before 18 September. That question has no outside answer yet. And an editor's design says little about the agents it hosts; the editor architecture comparison of Zed, Devin Desktop, and Cursor shows how differently those tools are built, but what any hosted agent sends over the network is a property of the agent.
What these incidents do not show
- They do not show that other agents upload workspaces. The sources document one product's behavior; nothing here tests Claude Code, Codex, or Copilot for it.
- They do not show exploitation of Plugin4Shell in the wild. The disclosure describes a working proof of concept; Air's earlier marketplace research reports takeovers at scale, but that is a related class, not this bug.
- They do not rank products. Claude Code is Anthropic's product, and its status here comes from a third party's disclosure and Anthropic's public documentation, not from any comparison of vendors.
What to check, by situation
- You run Claude Code or Codex: confirm the version is at least 2.1.179 or 0.146.0 respectively. Auto-update likely moved you already, but the version number is the thing to verify.
- You use GitHub Copilot's plugin features: look for a current Microsoft advisory, since the last status verified here predates 17 September, and restrict plugin sources to hosts you control or that reject hash-like branch names.
- You still use Gemini CLI: Google's stated position, via Air, is that no patch is coming, so every install stays vulnerable; migrating is the remedy Air recommends.
- You used ZCode 3.12.3 or earlier while logged in: update to 3.14.0 or later, and consider rotating any credential that ever appeared in a repository you opened, because Git history keeps deleted secrets. The researcher also published a filesystem-lock workaround, which he still recommends as a backstop since the client can receive hot updates.
- You are choosing an agent: check whether each privacy setting maps to actual network behavior, and who holds the keys to anything uploaded. Those two questions would have flagged ZCode in advance.
Frequently asked questions
Is Plugin4Shell exploitable if my plugin marketplace is on GitHub?
According to Air Security, the branch-name variant needs a host that accepts hash-like branch names, and GitHub rejects them. The Gemini CLI variant is not blocked by that restriction, and only an agent-side fix fully closes the problem.
Did ZCode upload my entire repository?
Not necessarily. The researcher's large 313 MB archive failed to upload and stayed on his machine, while a small workspace uploaded successfully. Z.ai acknowledged that some users were affected, so exposure depended on workspace size and whether the upload succeeded.
Has Z.ai's claim that uploaded data was deleted been verified?
No independent verification was available. Z.ai cites third-party audits and says full reports will follow, and the researcher notes that bucket deletion after 20 September cannot show what happened to earlier uploads.
Does Plugin4Shell have a CVE number?
No CVE identifier appeared in the sources reviewed, and the patch statuses come from the researchers' disclosure rather than vendor advisories.
Last verified: 6 October 2026. Patch status and vendor statements are changing and are reported here as of that date.
