Opening the Folder Is the Exploit, Again: ZCode Connects Workspace MCP Servers Without Asking
NVD published CVE-2026-88755 at 15:17:33Z on 16 October 2026 against Z.ai ZCode, the desktop coding agent built around the GLM model family. The record is sourced to cve@mitre.org, carries vulnStatus: Received, and as of writing has no CVSS score and no affected-version configuration data — the number exists, the analysis does not. The researcher writeup behind it names the product precisely: ZCode desktop client 3.11.2.6792 on Windows x64, verified on 8 September 2026. The type is a trust boundary violation with two impacts: arbitrary code execution and information disclosure.
The mechanism will sound familiar if you read yesterday’s briefing: when ZCode opens a workspace, it merges the repository-local .zcode/config.json into its mcp.servers table and immediately connects to every declared server without any user approval. For stdio servers the client spawns the configured command directly. Opening a repository is therefore equivalent to executing any command the repository declares. No security-relevant click, no consent dialog — the reproduction logged an MCP handshake within a second of opening the folder and calc.exe spawning automatically, with eight EXECUTED markers in the log.
This is the second time in twenty-four hours this site has written up this exact flaw class in a shipping coding agent. The pattern is no longer an anecdote; it is the default way project-scoped MCP loses.
The file the repository brings with it
The attack surface is a documented configuration path, not an undocumented one. ZCode reads MCP configuration from a fixed directory convention with two scopes: user scope at ~/.zcode/cli/config.json (available in every workspace) and workspace scope at <project root>/.zcode/config.json (current project only), both under the mcp.servers key, plus .agents/mcp.json compatibility paths. We confirmed this structure first-hand in ZCode’s own MCP documentation: the User-versus-Workspace scope distinction, the exact file paths, and the fact that imported servers are stored in the .zcode configuration file of the chosen scope and enabled by default.
The researcher reports that vendor documentation describes workspace-level MCP servers as having moved from “require manual authorization” to trusted-and-connected by default. We did not find that exact sentence in the current docs page we read — which describes the OAuth approval flow for remote HTTP and SSE services at length, while local stdio servers, the dangerous kind, get their credentials through environment variables and no equivalent approval language. That asymmetry in the documentation mirrors the asymmetry in the product, and it is worth stating the sourcing boundary plainly: the trust-downgrade claim is the researcher’s; the file paths, the scopes, and the enabled-by-default import behaviour are verified from the vendor’s own page.
The attack scenario needs no privileges and no interaction beyond the normal developer workflow: the attacker places a .zcode/config.json in a public repository or a pull request against the victim’s project, the victim clones and opens it in ZCode, and the client spawns the declared command. The writeup notes the client bundle (resources/glm/zcode.cjs) reports a trustedMcpServerCount metric computed over the merged table — user-approved and repo-declared servers counted together, with no distinction between configuration origins at the implementation level.
Two payloads, one missing trust decision
What elevates this above a single-path RCE is the second finding, and it is the one agent operators should sit with. MCP tool descriptions from the auto-connected server are injected verbatim into the agent’s context. A poisoned description — in the reproduction, disguised as a billing and usage-attribution requirement — instructed the agent to pass the contents of its local credential file as a tool parameter. The log shows a doc_summarize call whose context parameter carried the full 1,821-byte ~/.zcode/v2/credentials.json: plaintext API keys, a JWT token, and SSH workspace password entries, flagged by markers including oauth, zcodejwttoken and remote-workspace, with no visible warning to the user.
So the single missing approval gates two distinct compromises: deterministic local code execution through the stdio spawn, and probabilistic-but-reliable credential exfiltration through description poisoning. The first needs no model cooperation at all; the second turns the model’s helpfulness into the exfiltration mechanism. Defenders who scope this as “just another prompt injection” will mitigate the wrong half — no system-prompt hardening, alignment work, or tool-approval policy stands between a repository folder and a spawned process.
The product already knows how to do trust
The detail that convicts the design rather than the implementation is that ZCode implements a full trust state machine for workspace-level hooks — the writeup enumerates its states as pending_trust, trusted_persistent, blocked_untrusted, blocked_policy, revoked and stale_digest, plus a trust_selected approval schema — while workspace-level MCP servers have no equivalent mechanism. The capability exists in the same codebase; it was simply not applied to the channel that spawns processes. The researcher’s remediation list reads like a straightforward port: default workspace-declared servers to pending_trust, track configuration origin through the merge, reuse the existing approval schema and digest anchoring, and add provenance marking to tool descriptions before they enter model context.
We have not verified the hook state machine from the client bundle ourselves — the binary is not open source and we did not reverse it — so take the enumeration as reported. But the structural point does not depend on it: every agent vendor now faces the same question of which repository-borne files execute and which merely inform, and answering “all of them execute until someone complains” is how this class keeps shipping.
A pattern this site keeps writing up
Yesterday’s Junie CLI briefing (CVE-2026-111091) covered the identical shape: project-scope MCP configuration that names a command the runtime starts, where cloning a repository and starting the agent is the entire exploit chain. The writeup cites the older comparable case of CVE-2025-61260 in the Codex CLI’s workspace MCP auto-trust; we have not independently reviewed that record and repeat the citation as the researcher’s, not our own. The through-line across all three is the editorial distinction we drew yesterday and will keep drawing: prompt injection through a repository file is a probabilistic attack on a model’s judgement, while a project-scope MCP entry is a deterministic attack on a launcher. Nothing in the model’s Weights decides whether the process spawns.
Related reading on this site: GitSpawn turns untrusted repositories into RCE across seven coding agents, and the MCP configuration secrets sprawl measured across public files — the credential store ZCode’s second path loots is exactly the sprawl those counts describe.
What to do
Do not open untrusted repositories in ZCode until the vendor ships an approval gate, or open them only in a disposable VM or container. The trigger is the open-folder action itself, so post-open vigilance arrives too late for the RCE path.
Treat .zcode/config.json and .agents/mcp.json as executable content. Before the first agent run on any unfamiliar checkout, read the workspace agent-config paths the way you would read a Makefile or a git hook: the question is what command this starts, not whether it looks like configuration. Extend the same treatment to every agent you run — the file names differ per vendor, the hazard does not.
Put agent-config paths under code review and CI. A pull request that adds or edits a workspace MCP file changes what executes on every reviewer’s machine. A path-based required-reviewer rule catches the untrusted-fork case before anyone clones.
Prefer user scope for servers that hold authority, and audit what is already in workspace scope in repositories you have open. Servers you rely on belong in ~/.zcode/cli/config.json, where a cloned project cannot define them. Enterprises should ask Z.ai for a policy switch disabling workspace-scope MCP entirely — the researcher recommends exactly this, and the ninety seconds it takes to ask is cheaper than the incident.
Rotate credentials if you opened anything unfamiliar. The exfiltration path is silent by design; the absence of a visible warning is not evidence of absence. Any API keys, tokens, or SSH workspace passwords present in the local ZCode store during such a session should be considered exposed.
Verification note. The CVE identifier, NVD publication timestamp (2026-10-16T15:17:33.537Z), vulnStatus: Received, the cve@mitre.org source identifier, the description text, and the three NVD reference URLs were read first-hand from the NVD 2.0 API. The record carries no CVSS metrics and no configuration data at time of writing; we state no score and no affected range beyond the researched version, and we ignore third-party aggregator scores. The technical detail — handshake observations, marker counts, credential-file size, trust-state names, and the documentation claim — comes from the researcher’s NVD-referenced gist and the accompanying public proof-of-concept repository, both read first-hand; short quoted phrases are the researcher’s words, not ours. The MCP scope structure, file paths, and import behaviour were read first-hand from ZCode’s vendor documentation. Brave Search was used for discovery and returned only CVE-mirror aggregators and automated scoring pages — no independent technical analysis and no vendor advisory exist at time of writing. Nothing was installed, no ZCode instance was run, no repository was crafted or cloned to test this, no credential file was touched, and no third-party request was sent beyond reading the cited public records. We have no evidence of exploitation and imply none. Remediation guidance is our editorial analysis.
Sources:
- NVD — CVE-2026-88755, Z.ai ZCode workspace MCP auto-connect with code execution and credential disclosure (
vulnStatus: Received, no CVSS at time of writing) - Researcher writeup — CVE-2026-88755 gist: handshake and RCE verification, 1,821-byte credential exfiltration, hooks trust-state asymmetry
- Proof-of-concept repository — crafted workspace configs, reproduction notes, and verification logs (video artifact noted but not relied upon)
- ZCode Docs — MCP: User versus Workspace scope,
.zcode/config.jsonload paths, and import behaviour (read first-hand) - al-ice.ai — Junie CLI CVE-2026-111091: the same flaw class, one day earlier