Safeguard
AI Security

MCP server security for AI coding agents

A critical RCE in Anthropic's own MCP Inspector (CVSS 9.4) and two Cursor CVEs show that giving AI agents tool access creates a new, largely unvetted attack surface.

Safeguard Research Team
Research
7 min read

Anthropic introduced the Model Context Protocol in late 2024 to give a standard interface for LLM agents to call tools and read data sources, and by mid-2025 it had been wired into IDEs, CLI agents, and enterprise platforms fast enough that security tooling never caught up. The clearest proof: CVE-2025-49596, a CVSS 9.4 unauthenticated remote code execution flaw, was found in Anthropic's own MCP Inspector — the reference tool built to help developers debug MCP servers. A developer merely visiting a malicious webpage while Inspector ran locally could have arbitrary commands executed on their machine, because the tool's proxy defaulted to binding 0.0.0.0 with no auth or CSRF protection, combined with a known browser quirk that lets public sites reach services on localhost. Around the same period, two CVEs in Cursor's MCP integration — CVE-2025-54136 ("MCPoison") and CVE-2025-54135 ("CurXecute") — showed that Cursor's MCP configuration files could be manipulated, either after initial approval or via prompt injection, to make the editor execute attacker-chosen commands without further user consent. MCP servers give agents real capabilities: file access, shell execution, database queries, API calls. This piece walks through the concrete failure patterns researchers have already found, and the defensive controls that address each one.

What is tool poisoning and why don't MCP clients catch it?

Tool poisoning is a form of indirect prompt injection where malicious instructions are embedded not in user input, but in the metadata an MCP server sends to describe its own tools — the name, description, or parameter schema an agent reads before deciding how to call it. Because the agent trusts tool descriptions as part of its operating context, a poisoned description can instruct it to exfiltrate data, ignore later safety instructions, or invoke a different tool than the user intended, all without the user seeing anything unusual in the conversation. The problem is structural: the MCP specification does not require clients to validate or sandbox server-supplied metadata, and research evaluating MCP clients found that most — five out of seven in one assessment — performed no static validation of tool descriptions at all before handing them to the model. Since MCP servers are frequently installed from community registries with minimal vetting, this leaves the description field as an unmonitored injection channel sitting upstream of every tool call an agent makes.

What did CVE-2025-49596 reveal about local MCP tooling?

CVE-2025-49596, disclosed by Oligo Security in mid-2025 and covered by The Hacker News, Tenable, and Docker's engineering blog, showed that even Anthropic's own reference implementation could become a remote code execution vector. MCP Inspector runs a local proxy process to relay traffic between a developer's browser UI and the MCP server being debugged; that proxy defaulted to binding on 0.0.0.0 rather than 127.0.0.1, and shipped without session tokens or CSRF checks. Combined with what researchers call the "0.0.0.0 Day" browser behavior — where a public webpage's JavaScript can reach services bound to 0.0.0.0 on the visitor's own machine — an attacker-controlled page could send requests straight to the proxy and trigger arbitrary command execution, no authentication required. The fix, shipped in v0.14.1, added session-token authentication and switched the default bind address to localhost-only. The lesson generalizes past this one tool: any local MCP server or proxy that skips auth because "it's just localhost" is one browser quirk away from being internet-reachable.

How did the Cursor MCPoison and CurXecute CVEs enable persistent compromise?

CVE-2025-54136, nicknamed MCPoison, exploited the fact that Cursor's MCP integration re-executed a tool's underlying command using its updated configuration without re-prompting the user for approval — so a tool a developer approved once could be redefined later to run an entirely different, attacker-chosen command, and Cursor would just run it. CVE-2025-54135, CurXecute, worked differently but reached the same outcome: Cursor only required approval when an existing MCP dotfile was edited, not when a new one was created, so an indirect prompt injection (for example, a crafted message routed through a connected Slack MCP server) could get the agent to write a brand-new .cursor/mcp.json defining a malicious command, which Cursor then auto-executed with no approval step at all. Both CVEs illustrate the same underlying weakness: Cursor's one-time, install-time trust model for MCP configuration doesn't account for the file changing — whether by mutating an already-approved entry or by materializing a new one — after that initial check has passed.

What happened in the Supabase and Cursor credential-abuse incident?

In a mid-2025 incident, an AI coding agent connected to Supabase through Cursor's MCP integration was manipulated, via instructions injected through untrusted content the agent processed, into using an overly broad service-role database credential to exfiltrate integration tokens it should never have touched. The root cause wasn't a code execution bug — it was scope. The agent had been handed a credential with far more privilege than any single coding task required, so when prompt injection redirected its next action, that action had the reach of a database administrator rather than a scoped, task-specific reader. This is the recurring theme across MCP incidents: the protocol makes it easy to wire an agent up to powerful systems, but nothing in the protocol itself enforces least privilege on the credentials those connections carry.

How did the GitHub MCP server get hijacked through repository content?

Invariant Labs disclosed in May 2025 that GitHub's MCP server could be manipulated through prompt injection embedded in ordinary repository content — issue text, file contents, or pull request descriptions that an agent reads as part of its normal workflow. Because the agent treats repository content as data to summarize or act on, not as a source of instructions, injected text could redirect the agent's subsequent tool calls: opening pull requests, modifying files, or taking actions the user never asked for, using the same GitHub credentials the agent already held for the legitimate task. The flaw is the same class as classic indirect prompt injection in document-processing agents, but MCP raises the stakes because the "document" here is fetched and acted on by a tool with write access to source control, not just summarized in a chat window.

What defensive patterns actually reduce MCP attack surface?

The fixes that have emerged from this run of disclosures are consistent across vendors: scope credentials narrowly, so an agent connected to a database gets a read-only or task-specific role instead of the service-role key used in the Supabase incident; allowlist which tools an agent may call rather than trusting every tool a connected server advertises; bind local MCP servers and proxies to 127.0.0.1 with session-token authentication, the exact fix shipped for CVE-2025-49596; treat tool descriptions and repository content as untrusted input subject to validation, not as safe context; and log the full chain from prompt to tool call to downstream action so a compromised agent's behavior is reconstructable after the fact. The protocol itself has started closing gaps too — the November 2025 spec revision (protocol version 2025-11-25) formalized OAuth 2.1 for authenticating remote MCP servers, replacing ad hoc auth schemes that varied by implementation. None of these controls require abandoning MCP; they require treating every connected server as a new, unvetted piece of the attack surface, because the incidents above show that's exactly what it is.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.