DEV Community

NET_DARK_BOI
NET_DARK_BOI

Posted on

One year of MCP security: nine in ten public servers have no auth, and the worst bug is from 1988

The Model Context Protocol went from a November 2024 announcement to the default way AI agents reach tools, files and APIs. Within eighteen months it also became the most thoroughly attacked piece of AI infrastructure in existence — not because the protocol invented new bugs, but because it wired a component that cannot tell instructions from data to credentials that can do real damage.

This is a summary of what the incidents, the CVEs and the security research actually say, with the numbers traced to their sources.

The numbers, before the stories

A July 2026 study dynamically audited 414 internet-facing MCP servers out of 640 confirmed production instances. 91.8% had no OAuth authentication. The scan found 687 tool instances that expose shell execution without access controls, and 68 reportable vulnerabilities including SQL injection, SSRF against cloud metadata endpoints and path traversal (Padilla, Exposed by Design, arXiv, 2026).

The Cloud Security Alliance's May 2026 research note on what it calls the "MCP security crisis" puts the supply-chain side at roughly 200,000 vulnerable MCP instances behind more than 150 million package downloads, with at least seven confirmed high or critical CVEs by that point, and cites a July 2025 internet scan that found 1,862 publicly reachable servers with no authentication at all (CSA, May 2026).

The earliest structured look, from March 2025, tested popular open-source servers and found 43% with command injection, 30% with unrestricted URL fetching (SSRF) and 22% with path traversal. The authors' diagnosis was blunt: the protocol "was designed primarily for functionality rather than security" (Equixly, March 2025).

Command injection. SSRF. Path traversal. Missing authentication. None of these are AI vulnerabilities. They are the OWASP list from fifteen years ago, rediscovered inside servers that were written in a weekend to wrap an existing API.

What MCP is, in two paragraphs

An MCP client (an IDE, a chat app, an agent runtime) connects to one or more MCP servers. On connect it asks each server for its tools via tools/list. The server answers with names, descriptions and input schemas, and the client puts those descriptions into the model's context so the model can decide what to call. Servers can run locally as child processes or remotely over HTTP, where OAuth is supposed to handle identity.

Two consequences follow. First, everything a server sends — tool descriptions included — is input to the model. Second, whatever credentials the server holds are exercised on behalf of whoever, or whatever, managed to steer the model. Every incident below is one of those two facts meeting a real credential.

Five incidents, in the order they taught something

April 2025 — attacks before the first tool call. Trail of Bits showed that a malicious server can put a prompt-injection payload in a tool description or in its server instructions. Because descriptions enter the context at connection time, the model's behaviour is manipulated before any tool is invoked — which bypasses the human-in-the-loop approval that MCP clients put in front of tool calls. They named it line jumping; others call it tool poisoning (Trail of Bits).

May 2025 — the public issue that read the private repo. Invariant Labs demonstrated a "toxic agent flow" against GitHub's official MCP server: a developer asks an agent to look at open issues in a public repository; one issue, written by a stranger, instructs the agent to read the developer's private repositories and post what it finds in a pull request on the public one. The agent complies. Nothing in the server was broken; the agent simply held a token that could reach private repos and followed text from someone who could not (Invariant Labs).

May–June 2025 — the cross-tenant leak with no attacker. Asana launched its MCP server on 1 May 2025. A logic bug allowed data from one organisation's Asana instance to surface to MCP users in other organisations, within each user's own access scope, until Asana found it on 4 June. Roughly 1,000 customers were affected; the server was taken offline and restored on 17 June. There is no indication anyone exploited it — it was ordinary multi-tenant isolation failing in a brand-new code path (BleepingComputer).

July 2025 — the support ticket that ran SQL. General Analysis showed the cleanest version of the pattern. An attacker files a support ticket containing instructions addressed to the assistant. A developer later opens tickets from Cursor through the Supabase MCP server, which runs with the service_role key — the one that bypasses row-level security. The assistant reads the ticket, treats the embedded text as a task, queries the integration_tokens table and writes the OAuth secrets back into the ticket, where the attacker reads them (General Analysis). Simon Willison used it as the textbook case of his lethal trifecta: private data, untrusted content and a channel out, in one agent (Willison). Supabase's response was mostly configuration: scope the server to a project, run it read-only, restrict the tool set (Supabase).

July 2025 — remote code execution on the developer's laptop. JFrog disclosed CVE-2025-6514 (CVSS 9.6) in mcp-remote, the npm bridge that clients use to reach remote servers. During OAuth discovery a malicious server returns a crafted authorization_endpoint; the client hands that string to the open package, and on Windows PowerShell's $() subexpression turns it into arbitrary command execution. Versions 0.0.5 to 0.1.15 were affected, across more than 437,000 downloads (JFrog). It was the first documented case of connecting to an untrusted MCP server leading to code execution on the client machine.

By 2026 the disclosures had moved up the stack — from individual servers to the SDKs and the package supply chain — which is why the CSA note reads less like a bug list and more like an incident-response plan (CSA).

The bug that predates all of this

In 1988 Norm Hardy described a compiler service that could write to the billing file because it charged for compilations, and that also let users name an output file for debug logs. Someone named the billing file. The compiler had the authority; the user did not; the compiler could not tell that the instruction came from someone who should not be giving it. Hardy called it the confused deputy (Hardy, 1988).

Every agent incident above is that compiler. The GitHub agent had the private-repo token and followed an issue. The Cursor assistant had service_role and followed a ticket. The deputy has the credential; the requester does not; the deputy cannot attribute the instruction.

The protocol's authors know this. The MCP project's own Security Best Practices document contains a section literally titled "Confused Deputy Problem" — about proxy servers with a static client ID whose consent cookie lets an attacker skip the consent screen — and its rule is unambiguous: "MCP proxy servers MUST implement per-client consent". The same document forbids token passthrough ("MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server"), warns that OAuth discovery can be pointed at 169.254.169.254, and, on state handles passed back as tool arguments, says "MCP servers MUST NOT treat possession of a state handle as authentication" (MCP Security Best Practices). That last sentence describes insecure direct object reference — the first bug in every web-security course — written down again for agent builders.

OWASP has now formalised the list twice. The OWASP MCP Top 10 (beta, led by Vandana Verma Sehgal) runs from MCP01 Token Mismanagement & Secret Exposure through MCP03 Tool Poisoning, MCP05 Command Injection & Execution, MCP07 Insufficient Authentication & Authorization and MCP09 Shadow MCP Servers, to MCP10 Context Injection & Over-Sharing (OWASP MCP Top 10). The broader OWASP Top 10 for Agentic Applications 2026, released on 9 December 2025 by more than a hundred contributors, adds the agent-level view: goal hijack, tool misuse, identity and privilege abuse, memory poisoning, rogue agents (OWASP GenAI Security Project).

Two documents, twenty categories, and most of them map onto vulnerabilities with CWE numbers from the 2000s.

What the evidence says holds

Reading the incident write-ups and the vendor responses side by side, the effective controls are unglamorous and consistent.

Authorization at the tool boundary, keyed to the verified principal. The check is "may this user perform this action on this object", with the user derived from the token the server validated — never from an argument the model filled in. This is the fix for Asana's cross-tenant bug, for state-handle hijacking, and for the confused deputy in general.

Break the trifecta per session. Invariant's mitigation for the GitHub flow was one repository per session; Supabase's was read_only=true and project scoping. If a session ingests untrusted content, it should not simultaneously hold broad private access and an outbound channel. Least privilege here is not a policy document; it is a token that cannot reach the billing file.

Descriptions and fetched content are data, not instructions. Trail of Bits shipped mcp-context-protector as a wrapper that pins tool descriptions and flags changes; the OWASP list has tool poisoning at number three for a reason. Any text a server sends must be treated as evidence for the model, never as policy over it (Trail of Bits).

Do what the spec says about OAuth. Per-client consent, audience validation, no token passthrough, HTTPS and private-range blocking for discovery URLs. The mcp-remote CVE lived entirely in the discovery step the spec now warns about.

Human confirmation for side effects. Reading a ticket and sending its contents to an outside address are different permissions. An assistant that can draft the message should not be the component that decides to send it.

Inventory. MCP09 exists because most organisations do not know which servers their developers have connected. The CSA's first recommendation is not a patch; it is a list.

The unexciting conclusion

MCP did not create a new class of vulnerability. It created a new distribution channel for four old ones — command injection, SSRF, missing authorization and the confused deputy — and attached each of them to a component that will follow any well-phrased paragraph. The fixes are the same ones the web learned in the 2000s, applied at the tool boundary instead of the HTTP handler.

For readers who would rather see the deputy than read about it, Breachloom has three browser exercises and a chain built on exactly these patterns, all against fictional applications with nothing to install:

Hardy's paper is four pages long. Most MCP configurations would benefit from someone reading it and then counting how many billing files the agent can write to.


Sources: Padilla — Exposed by Design: A Dynamic Security Assessment of Internet-Facing MCP Servers at Scale (arXiv, 2026) · Cloud Security Alliance — MCP Security Crisis research note (May 2026) · Equixly — MCP Servers: The New Security Nightmare (March 2025) · Trail of Bits — Jumping the line (April 2025) · Trail of Bits — mcp-context-protector (July 2025) · Invariant Labs — GitHub MCP Exploited (May 2025) · BleepingComputer — Asana warns MCP AI feature exposed customer data (June 2025) · General Analysis — Supabase MCP: how prompt injection leaked private tables (July 2025) · Simon Willison — Supabase MCP can leak your entire SQL database (July 2025) · Supabase — Defense in depth for MCP servers · JFrog — CVE-2025-6514 (July 2025) · Model Context Protocol — Security Best Practices · OWASP MCP Top 10 · OWASP Top 10 for Agentic Applications 2026 · Norm Hardy — The Confused Deputy (1988)

Top comments (0)