The Agent Stack Has a 1998 Problem

In the last week of June 2026, a small cluster of CVEs landed against AI agent tooling, two of them in the same desktop agent client, both authorization flaws, one sitting squarely inside an MCP OAuth callback. Read on its own, each is a medium-severity bug a maintainer patches in a weekend. Read together, the cluster is a signal, and the signal is structural: the AI agent ecosystem is accumulating attack surface faster than it is accumulating the security culture to defend it. That is not a moral failing of any one project. It is the exact condition the web was in around 1998, when a language ran mainstream with insecure defaults, credentials sat everywhere, and the install base grew faster than anyone could harden it. The tools that hold your keys and run your shell are shipping at 1998 security maturity into a 2026 threat model.

TL;DR

  • Cherry Studio, a popular desktop AI agent client, drew two CVEs on June 29, 2026: an improper-authorization flaw in its MCP OAuth callback server (CVE-2026-13524) and an authorization bypass in a preload API (CVE-2026-13534).12
  • The pattern is not local to one app. The MCP reference tooling itself shipped critical remote-code-execution flaws in 2025: mcp-remote at CVSS 9.6 (CVE-2025-6514) and Anthropic’s MCP Inspector at CVSS 9.4 (CVE-2025-49596).34
  • Agent tools are structurally more exposed than webapps ever were: they hold credentials, execute code by design, and sit inside your trust boundaries (IDE, shell, browser) rather than behind them.
  • The knowledge to prevent these bugs already exists. The MCP specification documents the confused-deputy and OAuth-flow attack classes in detail; the culture to apply it on every fast-moving integration does not yet propagate.5
  • The 1998 web matured only after worms made insecurity expensive. The agent ecosystem has no equivalent forcing function yet, and the same models now finding these bugs can write the one that becomes it.

The Cluster, Concretely

Cherry Studio is a cross-platform desktop client that markets itself as an “AI productivity studio with smart chat, autonomous agents, and 300+ assistants,” with explicit support for Model Context Protocol servers. It is exactly the kind of tool this essay is about: a consumer-facing agent that brokers your API keys, runs local integrations, and reaches out to the network on your behalf.

On June 29, 2026, VulDB published two advisories against it. CVE-2026-13524 is an improper-authorization flaw (CWE-285) in the MCP OAuth Local Callback Server, in src/main/services/mcp/oauth/callback.ts, across versions 1.9.0 through 1.9.6. The language is plain: “The manipulation of the argument code leads to improper authorization.” It scores CVSS 3.1 at 5.6, medium.1 CVE-2026-13534 is an authorization bypass (CWE-639) in the CherryIN preload API, through version 1.9.7, scoring 5.0.2 Neither is a headline. Both are the quiet authorization mistake a team makes moving fast across a surface new to everyone.

The first is the tell. An OAuth callback in an MCP client is a textbook trust boundary: the point where an external authorization server hands a code back to your machine and your machine decides whether to trust it. Mishandling it is not an exotic new bug class. It is the one the MCP specification’s own security document spends the most ink on.

I dropped two neighboring CVEs from the same window, because the cluster has to be real: CVE-2026-13533 is agentejo Cockpit CMS, a PHP content manager rather than an agent framework, and CVE-2026-13543 could not be verified at all. A few solid examples beat a padded list.

Why Agent Tools Are Structurally Worse Off

A classic webapp circa 1998 was insecure, but it lived behind a boundary. It ran on a server you did not sit inside, its blast radius was the database and the session, and a breach got the attacker the app’s data.

An agent tool inverts that geometry. It runs on your machine or inside your IDE, holds long-lived credentials to your cloud and your repos, and executes code as a core feature rather than an exploit. There is no boundary to sit behind, because the tool is the boundary, and it is porous by design.

Simon Willison named the danger precisely in June 2025 with the “lethal trifecta”: an agent becomes exploitable when it combines “access to your private data,” “exposure to untrusted content,” and “the ability to externally communicate” in a way that can steal that data.7 Every capable agent has all three by default, because reading your secrets, ingesting attacker-influenced content, and making outbound requests are its features, not its bugs. The trifecta is not an edge case. It is the baseline configuration.

That is the structural difference. The 1998 webapp had to be tricked into leaking one boundary’s worth of data. The 2026 agent arrives pre-wired with every capability an exfiltration chain needs, and the only thing between a malicious input and your credentials is whether the tool drew its internal trust boundaries correctly. The Cherry Studio callback bug is what it looks like when one of those boundaries is drawn a little wrong.

The MCP Amplification

Model Context Protocol is the connective tissue of the 2026 agent stack, and it multiplies the surface in a specific way: every MCP server is a new privileged integration, usually written quickly, that the model can invoke. Adding one is frictionless. Auditing one is not. The install base of integrations is outrunning the population of people who read their code.

The reference tooling shows this is not a hobby-project problem. In July 2025, JFrog disclosed CVE-2025-6514, an OS command injection in mcp-remote, a connector used by Claude Desktop, Cursor, and Windsurf, that a malicious server triggers with a crafted authorization_endpoint URL during the OAuth flow: critical, CVSS 9.6.3 The same month, Tenable disclosed CVE-2025-49596, a 9.4 remote-code-execution flaw in Anthropic’s own MCP Inspector, where a missing authentication check let a malicious website reach a local port and, via DNS rebinding, run arbitrary commands.4

Two of the four CVEs in this essay are OAuth-flow flaws in MCP tooling: one in the callback server, one in endpoint discovery. That is not a coincidence. OAuth in an agent client is a repeatedly fumbled boundary, and the specification says so out loud. The MCP security-best-practices document, dated June 18, 2025, devotes its longest section to the “confused deputy problem,” and mandates that proxy servers implement per-client consent, validate the OAuth state parameter, and match redirect URIs exactly.5 That was published a year before Cherry Studio shipped its callback bug. The gap is not knowledge. It is the distance between a specification’s security appendix and the median integration written last Tuesday.

Prompt injection makes the amplification qualitatively worse than anything the old web faced. Willison coined the term in September 2022, writing “I propose that the obvious name for this should be prompt injection,” by analogy to SQL injection: trusted instructions and untrusted input concatenated into one string an engine then interprets.6 For an agent, data is a vector, not just code. A poisoned web page, a booby-trapped file, a hostile tool description: any byte the model reads can carry an instruction. The MCP spec is blunt about it, warning that a malicious server can turn the client into a proxy for data exfiltration.5 You cannot patch that with input escaping, because the input is natural language and the interpreter is a model.

The 1998 Analogy, Made Precise

The analogy has to survive fact-check or it is just a vibe, so here is the era, accurately.

PHP 3 shipped in June 1998 and put a dynamic web language into millions of hands with a default that now reads as reckless: external input, from the query string, cookies, or the server, was registered directly into the global scope. register_globals was on, and a variable an attacker controlled could quietly become one your code trusted. The fix took four years. PHP 4.2.0, released in April 2002, changed the default, and the release announcement states it flatly: “External variables (from the environment, the HTTP request, cookies or the web server) are no longer registered in the global scope by default.”8 The other era-defining crutch, magic quotes, ran addslashes to fake SQL-injection safety without the substance, and outlived register_globals by years before the project finally killed it. Insecure defaults, an illusion of safety, a multi-year lag before the culture caught up. That was the app layer of the young web.

The culture did not arrive on its own. It was forced. On July 19, 2001, the Code Red worm exploited a buffer overflow in Microsoft’s IIS web server, and by CAIDA’s count “more than 359,000 computers were infected with the Code-Red (CRv2) worm in less than 14 hours.”9 On January 25, 2003, the Sapphire/Slammer worm hit a buffer overflow in Microsoft SQL Server, packed itself into 376-byte packets, and “infected most of the vulnerable hosts that could be found within ten minutes,” the fastest-spreading worm in history to that point.10 Those were infrastructure worms, not PHP bugs, and I will not conflate them. The point is the shape of the decade: insecure defaults across every layer, and a security culture that matured only after insecurity became viscerally, publicly expensive. Secure-by-default was a lesson the industry paid for in worms.

Map that onto 2026 and the correspondence is uncomfortable. Insecure defaults: agent clients that trust callback codes and skip consent checks. The illusion of safety: a permission prompt over a token scoped admin:*. The exploding install base: an MCP server for everything, added in one click, audited by nobody. What the ecosystem does not have yet is the worm. It has the 1998 defaults and the 2001 target profile, and it is waiting on its forcing function.

The Operator’s Posture

You do not get to wait for the culture. You run these tools now, so you draw the boundaries the ecosystem has not yet drawn for you. The frame I use is the trifecta as an operational checklist: for any agent, ask what it may read, what it may execute, and what it may exfiltrate, and put a deterministic guard on each.

Capability What the agent does Where it goes wrong The guard
Read Ingests files, web pages, tool output, MCP responses Untrusted content carries injected instructions Treat every fetched byte as hostile input, never as instruction; label and isolate external data sources
Execute Runs shell, edits files, calls tools by design Crafted data becomes a command (injection, confused deputy) Permission rules that evaluate before the call; allowlist tools and MCP servers; require consent on new local servers
Exfiltrate Makes outbound requests, writes to repos, posts to APIs Read plus execute completes the lethal trifecta Egress controls; block private and link-local IP ranges; scope tokens least-privilege; never pass tokens through

The guard column is not aspirational. It is deterministic, and determinism is the point. Hooks fire on lifecycle events with exit codes the model cannot argue with, and permission rules evaluate before a tool runs, not after. That is the layer where “the agent should not do X” becomes “the agent cannot do X,” and it is the only layer a prompt-injection payload cannot talk its way past. When you cannot trust the input, and you cannot trust the model to police itself on the input, you enforce at the boundary the model does not control.

A second control reads as a productivity feature but is really a security one. When an agent compiles its work into a reviewable plan before executing, reviewing that plan is a security review. A forty-line workflow script that names every tool it will call and every file it will touch is a threat model you read in a minute. You cannot audit ten thousand live decisions; you can audit the plan that would generate them, before it spends anything.

And keep the asymmetry in view: the same capability that produces these CVEs also finds them. An Anthropic researcher used a coding agent and a ten-line script to surface a 23-year-old Linux kernel vulnerability and 22 Firefox CVEs. The tool on your desk is a vulnerability scanner pointed at your own stack, if you point it. Defenders can automate discovery today and are building the triage layer now. That is the one advantage the 1998 web did not have.

The Position

Here is what I think happens, specific enough to be wrong. The agent ecosystem gets its Code Red moment before it gets its security culture, because that is the order the web did it in. The forcing function is most likely a self-propagating prompt-injection payload moving between agents through shared MCP servers, or a mass credential-exfiltration event tracing back to one popular, under-audited integration. It will be cheap to build, because the same models finding kernel bugs can write it, and the warning of “a big wave coming” was never about defense only.

After it lands, secure-by-default stops being optional. MCP clients ship with consent dialogs on by default, token audiences validated, callbacks that reject unmatched redirect URIs, the way PHP eventually shipped with register_globals off. Permission layers move from opt-in to default-deny. The integrations that survive are the ones that treated the specification’s security appendix as the spec.

The uncomfortable part is the timeline. The web took roughly 1998 to 2005 to internalize secure-by-default, with years between worms to think. The agent stack compounds faster, with a higher-value target on every developer’s machine and an attacker toolchain that improves every model generation. The 1998 problem is real. The only open question is whether we act on the analogy before the worm writes the ending, or after.

Key Takeaways

  • Run the trifecta audit on every agent. Write down what each tool can read, execute, and exfiltrate, then confirm a deterministic guard on each row. A capability with no guard is your exposure, and where the next payload lands.
  • Allowlist MCP servers; treat every command parameter as untrusted execution. Adding an integration is one click and auditing it is not, so gate registration to a reviewed list. Two of the four CVEs here were OAuth-flow bugs in MCP clients: the handshake is a boundary, not a formality.
  • Make plan-time the review gate. Have agents compile intent into a reviewable plan and read it like a threat model before execution. A script that names its tools and files is auditable in a minute; ten thousand live tool calls are not.
  • Point the scanner at yourself first. The capability that produces these CVEs also finds them. Run agent-assisted security sweeps on your own code and dependencies before someone else runs theirs on you.

FAQ

Are MCP servers safe?

Not by default, and not uniformly. MCP is a protocol; its security depends on how each server and client implements it. The 2025 disclosures against mcp-remote (CVSS 9.6) and Anthropic’s MCP Inspector (CVSS 9.4) show even reference tooling shipped critical RCE flaws.34 The specification documents the major attack classes, confused-deputy, token passthrough, SSRF, local-server compromise, and prescribes concrete mitigations.5 Treat each server as a privileged integration: run only ones you trust or have audited, allowlist them explicitly, and assume any server you connect to can influence your agent.

What is prompt injection?

Prompt injection is when an attacker smuggles instructions into the untrusted input an AI system reads, and the model follows them as if they came from you. Simon Willison coined the term in September 2022 by analogy to SQL injection: trusted instructions and untrusted input concatenated into one prompt the model then interprets, with no reliable way to tell which part was the attacker’s.6 For agents it is especially dangerous because data becomes a vector, and escaping cannot fix it because the interpreter is a language model.

What is the lethal trifecta?

Simon Willison’s name, from June 2025, for the three capabilities that together make an agent exploitable: access to your private data, exposure to untrusted content, and the ability to communicate externally.7 An agent with all three can be manipulated by injected content into reading your secrets and shipping them to an attacker. Most capable agents have all three by default, which is why the move is to guard each capability rather than hope the model resists.

How do I secure an agent that runs on my machine?

Start with the boundary the model does not control. Use permission rules and hooks that evaluate before a tool runs, so a compromised prompt cannot talk its way into an action you forbade. Allowlist tools and MCP servers, require consent before a new local server executes, and scope every credential least-privilege so a stolen token has a small blast radius. Block outbound requests to private and link-local IP ranges to close the exfiltration path. Then review the agent’s plan before large operations, where injection that survived the read boundary gets caught.

Sources


  1. CVE-2026-13524, CircL Vulnerability-Lookup, vulnerability.circl.lu/vuln/cve-2026-13524 (published June 29, 2026). Improper authorization (CWE-285) in the MCP OAuth Local Callback Server of CherryHQ cherry-studio 1.9.0 through 1.9.6, file src/main/services/mcp/oauth/callback.ts. “The manipulation of the argument code leads to improper authorization.” CVSS 3.1 base score 5.6 (medium); GHSA-9c5h-h4mj-p5ch; fix proposed in pull request #15388

  2. CVE-2026-13534, CircL Vulnerability-Lookup, vulnerability.circl.lu/vuln/cve-2026-13534 (published June 29, 2026). Authorization bypass (CWE-639) in the CherryIN preload API of CherryHQ cherry-studio through 1.9.7, function sha256 in src/main/services/memory/MemoryService.ts. CVSS 3.1 base score 5.0 (medium); GHSA-qwwm-4xhq-q4m4; the vendor notes memory is planned for removal in v2. 

  3. CVE-2025-6514, GitHub Advisory Database, github.com/advisories/GHSA-6xpm-ggf7-wc3p (published July 9, 2025). “OS command injection when connecting to untrusted MCP servers due to crafted input from the authorization_endpoint response URL,” in mcp-remote versions >= 0.0.5, < 0.1.16; CVSS v3 base score 9.6 (critical); patched in 0.1.16. Discovered and detailed by JFrog Security Research; client exposure (Claude Desktop, Cursor, Windsurf) per JFrog’s advisory post

  4. CVE-2025-49596, Tenable Research, “How Tenable Research Discovered a Critical Remote Code Execution Vulnerability on Anthropic MCP Inspector,” tenable.com (July 9, 2025). RCE in Anthropic’s MCP Inspector below version 0.14.1, root cause a missing authentication check between the Inspector client and proxy, exploitable from a malicious website via CORS and DNS rebinding; CVSS 9.4 (critical); fixed in 0.14.1 by adding proxy session tokens. 

  5. “Security Best Practices,” Model Context Protocol specification, revision 2025-06-18, modelcontextprotocol.io/specification/2025-06-18/basic/security_best_practices. Documents the confused-deputy problem and mandates that MCP proxy servers “MUST implement per-client consent” with OAuth state validation and exact redirect-URI matching; also covers token passthrough (“MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server”), SSRF, session hijacking, and local-server compromise. 

  6. Simon Willison, “Prompt injection attacks against GPT-3,” simonwillison.net/2022/Sep/12/prompt-injection/ (September 12, 2022). Coins the term: “I propose that the obvious name for this should be prompt injection,” drawing the analogy to SQL injection and the concatenation of trusted instructions with untrusted input. 

  7. Simon Willison, “The lethal trifecta for AI agents: private data, untrusted content, and external communication,” simonwillison.net/2025/Jun/16/the-lethal-trifecta/ (June 16, 2025). Names the three capabilities whose combination makes an agent exploitable: “access to your private data,” “exposure to untrusted content,” and “the ability to externally communicate.” 

  8. “PHP 4.2.0 Release Announcement,” php.net/releases/4_2_0.php (April 2002). Documents the security-default change: “External variables (from the environment, the HTTP request, cookies or the web server) are no longer registered in the global scope by default.” This is the register_globals off-by-default change, roughly four years after PHP 3 shipped the on-by-default behavior in 1998. 

  9. “CAIDA Analysis of Code-Red,” CAIDA, caida.org/archive/code-red. “More than 359,000 computers were infected with the Code-Red (CRv2) worm in less than 14 hours,” beginning July 19, 2001, exploiting a buffer overflow in Microsoft IIS; at peak “more than 2,000 new hosts were infected each minute.” 

  10. “The Spread of the Sapphire/Slammer Worm,” CAIDA, caida.org/archive/sapphire. Released Saturday, January 25, 2003, at approximately 5:30 AM UTC, exploiting a buffer overflow in Microsoft SQL Server; the worm crafted 376-byte packets and “infected most of the vulnerable hosts that could be found within ten minutes,” the fastest-spreading worm in history at the time. 

関連記事

Silent Egress: The Attack Surface You Didn't Build

A malicious web page injected instructions into URL metadata. The agent fetched it, read the poison, and exfiltrated the…

20 分で読める

Your Agent Has Two Untrusted Inputs

AI agents have two untrusted inputs: code the model writes and tool output it reads. One now has a real WASM sandbox; th…

12 分で読める

Your Agent Writes Faster Than You Can Read

Five research groups published about the same problem this week: AI agents produce code faster than developers can under…

17 分で読める