Google, JPMorgan and the French Government Shipped the Same MCP Bug. Nobody Asked Who Controls the Argument

On Monday, October 5, Ars Technica published a story under a headline I could not scroll past: "MCP for agent-to-agent comms may be the riskiest protocol you've never heard of." I build on the Model Context Protocol on both sides: I expose MCP servers, and I run an MCP client that consumes other people's. So I went past the article to the researcher's write-up, the CVE records and the pull requests that fixed the bugs. The story is more useful there than in the headline.
The same bug, five times
The researcher is Syed Anas Mohiuddin, who describes himself as independent: no employer, no lab, no team. His October update lists five organizations whose own security teams each confirmed and fixed the same mistake: Google, JPMorgan Chase, Weaviate, France's interministerial digital directorate (DINUM), and the city government of Tangerang in Indonesia.
The mistake is server-side request forgery. A tool takes an argument, the argument becomes a URL or a path, and the server fetches it from its own network position without checking where it really lands.
Google's case is CVE-2026-14540, published on July 31 with Google as the numbering authority. Its MCP Toolbox, versions 0.3.0 through 1.4.0, built its HTTP client with no CheckRedirect policy and no target IP validation, so a crafted path parameter could make it follow a redirect to an internal endpoint. The CVSS 4.0 score is 8.0, High. The fix, merged on June 18, checks the resolved address at connection time to defeat DNS rebinding, adds IP allow and block lists, and rejects an unsafe base URL at startup instead of on first request.
JPMorgan's case taught me the most. Its payments documentation MCP server had two tools that fetch content. One, read_documentation, enforced a domain allowlist. Its sibling, related(), fetched any caller-supplied URL. The pull request that fixed it on September 18 routes both tools through a single fetch path "so the two tools can't drift out of sync again."
The French case shows where a bad value comes from: the official MCP server for data.gouv.fr fetched a documentation URL from the open-data catalog, a field any registered data producer can set. The fix, merged on September 4, validates the destination IP at connect time and re-checks every redirect hop.
Rapid7 adds a different bug: CVE-2026-97228, published September 25, a GraphQL injection through an unvalidated export identifier in its Bulk Export MCP server, rated 2.7, Low, fixed in 0.6.2. Rapid7's own advisory names the realistic exposure: "a compromised or careless upstream MCP client, or indirect prompt injection forwarding an unvalidated identifier."
He also filed five reports on US federal MCP servers on September 2. They are still in triage, so I leave them out.
Why teams that share nothing made the same mistake
His thesis fits in one sentence: "The developer treats data crossing the MCP boundary, in either direction, as trusted because it came from inside the system."
In an agent, it fails. A tool argument is written by a model that has just read a web page, a document or an email anyone could have written. Douglas McKee, director of vulnerability intelligence at Rapid7, told Ars that anything passed from an LLM to your tool "should be treated like input from a stranger on the Internet."
On the Tools page of the current MCP spec, version 2026-07-28, the server-side security requirements are four short bullets, starting with "Validate all tool inputs." The detailed SSRF guidance (block private ranges, validate every redirect target, beware of DNS rebinding, consider an egress proxy) sits in the Security Best Practices page, and it is written for the OAuth-related URLs an MCP client fetches during authorization discovery. If your tool turns an argument into a URL, the best checklist in the spec is one you have to carry over yourself.
Protocol Pivoting, without the recipe
About that headline: strictly, MCP connects an agent to tools and data, and A2A, a protocol Google started and donated to the Linux Foundation, connects agents to other agents. Real deployments chain the two: an orchestrator delegates to specialist agents over A2A, and each specialist has its own MCP servers.
Mohiuddin's May paper calls the resulting attack class Protocol Pivoting. Text an attacker controls arrives in a tool result. The orchestrator turns it into a delegated task. The specialist trusts its orchestrator and acts with its own credentials and network position. The MCP host validated the tool call, and A2A authenticated the orchestrator. In the paper's words, "neither protocol-level defense validates the content of the cross-protocol delegation." It is the old confused deputy problem, with an agent as the deputy.
Not everyone likes the new name. Markus Vervier of X41 D-Sec told Ars it is indirect prompt injection, and that the second protocol is "not strictly required." On the mechanics, I agree with him. The name still helps, because it points at where the fix goes: not inside one protocol, but at the hand-off between two.
What I ask of any MCP stack, mine included
The LegalTech I build handles confidential documents, so I will not describe how it is wired. Here are the questions instead.
Who controls each argument? List every tool, every argument and the source of its value: the user, the model, or upstream data. Anything the model or upstream data controls is a stranger's input. If it becomes a URL, a host or a path, send it through one guarded HTTP client: resolve and check the IP at connect time, no automatic redirects, an allowlist of the hosts the feature needs, and a hard failure at startup on a bad base URL. One client, so a sibling tool written next quarter cannot skip the check.
Is an identifier a name or a key? The spec says it plainly in its guidance on stateful tools: "a handle is a name, not a capability." Check the caller's authorization against it on every call, and pass it as a bound variable, never by string interpolation, which is exactly how Rapid7 fixed its bug.
What is a tool result allowed to trigger? A tool result is data, not a delegation. Content that came from outside can be shown or summarized, but it should not start a write, an outbound request or a task for another agent in the same run without a human or an explicit policy saying yes. The spec already says clients should show tool inputs to the user before calling a server and keep a human able to deny invocations. The paper proposes tagging every piece of context with its origin and mapping origins to permitted actions. A classifier that flags instruction-like text helps, but I use a small judge model for yes-or-no calls elsewhere, and a probability is a tripwire, not a wall.
Does delegation narrow the scope? The spec says MCP servers "MUST NOT accept any tokens that were not explicitly issued for the MCP server." The same logic should hold between agents: a subagent working on a delegated task gets what the task needs, not everything its own service account can do.
What lands in your logs? The write-up's second failure mode needs no attacker: in one federal case still in triage, a server logs full upstream error bodies, which can carry personal data. With confidential documents, that is the bug I would look for first.
Monday
Open your MCP servers and search for every outbound request. For each one, write down who controls the destination. If the answer is "the model" or "whatever the upstream returned," you are looking at the bug five unrelated teams shipped this year.
McKee's line to Ars sums it up: "Every piece in that chain did exactly what it was designed to do." MCP makes it very easy to expose a function to an agent. Asking who controls each argument is still our job.
Sources
- Ars Technica, "MCP for agent-to-agent comms may be the riskiest protocol you've never heard of" (October 5, 2026)
- Syed Anas Mohiuddin, "Protocol Pivoting, four months later: the same MCP bug across a hyperscaler, a bank, a database company, and two governments" (October 2026)
- Syed Anas Mohiuddin, "Protocol Pivoting: Cross-Protocol Attack Escalation in Agentic AI Systems" (May 24, 2026)
- CVE Program, "CVE-2026-14540: Server-Side Request Forgery via Unrestricted HTTP Redirection in MCP Toolbox" (July 31, 2026)
- googleapis/mcp-toolbox, "fix(source/http): implement SSRF guard" (June 18, 2026)
- jpmorgan-payments/ai, "Fix SSRF: enforce domain allowlist in related() (RDI-159)" (September 18, 2026)
- datagouv/datagouv-mcp, "feat: harden SSRF on external APIs" (September 4, 2026)
- Rapid7, "CVE-2026-97228: Improper Neutralization of Special Elements in Data Query Logic" (September 25, 2026)
- Model Context Protocol, "Tools" (version 2026-07-28)
- Model Context Protocol, "Security Best Practices" (version 2026-07-28)
- A2A Protocol, "A2A Protocol" (read October 7, 2026)
