# The same MCP flaw at Google, JPMorgan and DINUM: your audit

Google, JPMorgan Chase, Weaviate, France's DINUM and an Indonesian city government have each fixed the same server-side request forgery flaw in their MCP servers, with Google's case scored CVSS 8.0 as CVE-2026-14540. Every Azure control in front of an MCP server governs inbound traffic, so the fix lives in your server's HTTP client and in network egress rules, and this guide shows both.

- Published: 2026-10-07 · Category: Security & Compliance · Tags: MCP, Model Context Protocol, SSRF, Security, Azure API Management, Microsoft Foundry, Copilot Studio, Azure Container Apps, Cyber Resilience Act, AI Agents
- Author: Technspire AB, Stockholm (https://technspire.com)
- Canonical: https://technspire.com/en/blog/same-mcp-ssrf-flaw-google-jpmorgan-dinum-azure-audit

Five organisations that share no code, no industry and no country have now fixed the same bug in their Model Context Protocol servers. Google's MCP Toolbox for Databases carried it as CVE-2026-14540, a CVSS 8.0 server-side request forgery affecting versions 0.3.0 through 1.4.0, patched in 1.5.0 on 18 June 2026. JPMorgan Chase fixed it in a documentation-search server. Weaviate fixed it in its Google vectoriser modules on 25 August. France's interministerial digital directorate, DINUM, fixed it in an open-data MCP server on 4 September. The city government of Tangerang in Indonesia fixed it in a Wazuh MCP server within a day of the 2 September report. Independent researcher Syed Anas Mohiuddin found all five and published the tally on 6 October. Five US federal servers run by the General Services Administration are still in triage, and a fix for a Japanese Digital Agency server is still an unmerged pull request.

If your team runs MCP servers on Azure, behind API Management, attached to Foundry Agent Service or wired into Copilot Studio, the odds that you have written the same bug are not small. The bug is not exotic. It is an old web vulnerability class, re-created by a new kind of caller.

## What the bug actually is

Server-side request forgery, SSRF, happens when a server takes a URL, host or path from a caller and makes an outbound request to it without checking where the address resolves. The server's own network position and credentials get lent to whoever supplied the address. In the classic web case, the caller is a browser. In the MCP case, the caller is a language model, and the model got the URL from wherever it was reading: a web page, a ticket, a document in a vector store, a tool result from another server.

Mohiuddin's description of the mechanism in his 29 September write-up is the sentence to pin above the desk: "The attacker plants text somewhere a model will read it, and the model types the URL. The server sees a request from its own trusted model and does not think to ask where the idea came from."

The five fixed cases show four distinct ways to get it wrong, and each one is a pattern you can grep for.

| Pattern | Where it was found | What the fix did |
| --- | --- | --- |
| HTTP client follows redirects with no policy and no target IP check | Google MCP Toolbox, generic HTTP source (CVE-2026-14540) | An SSRF guard that validates the resolved IP at connection time and on every redirect hop, blocks non-global addresses by default, and rejects an unsafe base URL at startup |
| Allowlist checks literal IP addresses only; any hostname passes | Tangerang Wazuh MCP Server (GHSA-pw2j-pj4h-f5vg) | Resolve the hostname and check the resulting address; a name like 127.0.0.1.nip.io had walked straight through |
| A second config field bypasses the hardening applied to the first | Weaviate Google modules: apiEndpoint skipped two passes that only covered baseURL | Constrain the endpoint to legitimate Google API hosts (PR #12961) |
| URL from an upstream data producer fetched without DNS-rebinding protection | DINUM open-data MCP server (PR #126) | Pin the resolved address between check and use |
| Forked code lost the allowlist the original had | JPMorgan documentation-search server, related() tool | Restore the allowlist present in the upstream AWS project |

The Google case deserves one more line because it is the shape most Azure teams will have copied. The toolbox had baseline input sanitisation on user-controlled parameters. The gap was lower down, in an HTTP client created without a restrictive redirect policy. Sanitising the string the model sends you does nothing if the thing at the other end of the string says "go here instead" and your client obeys.

## Why the researcher calls it protocol pivoting

In May 2026, Mohiuddin argued that SSRF in MCP servers was a structural gap rather than a run of careless implementations, and predicted the same bug would surface in servers written by teams with nothing in common but the protocol. The October update is the evidence. He has since generalised the findings into an IETF Internet-Draft, draft-mohiuddin-mcp-security-considerations-00, which defines six vulnerability classes for MCP implementations, with SSRF first on the list.

Protocol pivoting is the name for the chain that makes SSRF worse in an agent system than in a web app. An adversary who gains influence over one protocol layer uses it to act across the others. Text injected into content the model reads becomes an MCP tool call. The tool call becomes an outbound request from the server. In multi-agent setups, a tool result shaped like an agent-to-agent task gets passed by an orchestrator to a subagent, which executes it because it trusts the orchestrator. Rapid7's Douglas McKee, whose team fixed an unrelated low-severity issue in the same disclosure round, summarised the difficulty: "Every piece in that chain did exactly what it was designed to do, which is what makes this so tricky to catch."

The MCP specification's own security best practices page covers SSRF, but mostly from the client side: a malicious server feeding internal URLs into OAuth metadata discovery. Server-side SSRF through tool arguments is the mirror image, and the spec's mitigations transfer directly. Enforce HTTPS, block private and link-local ranges, validate redirect targets, pin DNS between check and use, and route outbound traffic through an egress proxy. The spec also carries a warning that every one of the five fixed cases illustrates: avoid implementing IP validation by hand, because attackers exploit encoding tricks that custom parsers miss.

## What SSRF reaches from an MCP server on Azure

The reason SSRF is scored high rather than medium is what sits on the internal side of the server. On Azure, three targets matter.

**The Instance Metadata Service.** Any VM or VM-backed compute can reach 169.254.169.254, which serves instance details and, through the identity endpoint, managed identity access tokens. Microsoft designed in a partial SSRF defence: every request must carry the header Metadata: true and must not carry X-Forwarded-For, or the service rejects it. That defence holds only as long as the attacker cannot set headers. An MCP tool that takes a URL and a headers object, or a server that forwards arbitrary headers to the fetch, hands the attacker exactly what the defence assumes they lack.

**The App Service and Functions token endpoint.** On App Service the managed identity endpoint lives at a local address in the IDENTITY_ENDPOINT environment variable and requires an X-IDENTITY-HEADER value that the platform rotates. Microsoft's documentation describes the header as existing specifically to help mitigate SSRF. It is a better defence than the IMDS header because the value is a secret rather than a constant. It is still not a defence against a server that lets the model read environment variables through another tool and then make the request.

**Everything behind your private endpoints.** The point of putting Azure SQL, Key Vault, Storage and an internal Container Apps environment behind private endpoints is that nothing outside the virtual network can reach them. An MCP server inside that network with SSRF is inside the network. The researcher's Tangerang advisory lists the realistic outcomes: internal reconnaissance, cloud metadata access, requests to internal HTTP services, and exfiltration of response content back through the tool result.

## The three ways Azure teams expose MCP, and what each one does not protect

**Azure API Management.** APIM can expose a REST API as an MCP server or front an existing MCP server, and it applies policies to the tools: JWT validation against Microsoft Entra ID, rate limits, IP filtering, caching. All of that is inbound control. It decides who may call your tools. It does nothing about what your server fetches once a tool runs, because the fetch happens behind the gateway, from your backend's network identity. A perfectly governed APIM front with an unguarded fetch behind it is exactly the Google toolbox shape.

**Foundry Agent Service.** The MCP tool in Foundry connects an agent to a remote server by URL, public or private. For private servers, Microsoft's documented pattern is a Container Apps deployment with internal-only ingress on a dedicated MCP subnet. The documentation is explicit about the trust boundary: third parties create the remote servers, Microsoft does not test or verify them, and you should treat tool descriptions and results as untrusted input that can carry indirect prompt injection. The tool also lets you pass custom headers to the server. Approval gates, allowed_tools and the always-approve setting protect the agent from a bad server. None of them protect your server from a bad URL that arrived in a tool argument.

**Copilot Studio.** Agents built on the standard harness connect to MCP servers through a connector, and Microsoft's documentation places responsibility for an external server's tools on the maker. Same shape: the platform governs the connection, you govern the server.

Every Azure control in front of an MCP server governs ingress. SSRF is an egress problem. You fix it in the server's HTTP client and in the network the server runs in.

## Fix one: the HTTP client

Start by finding every tool that takes something resembling a URL, host, endpoint or path and ends up in a fetch. Include fields that come from configuration or from upstream data, not just tool arguments; the Weaviate and DINUM cases were both there. Then apply the pattern Google landed in 1.5.0. In Node, the shape looks like this.

```
import dns from "node:dns/promises";
import net from "node:net";

const ALLOWED_HOSTS = new Set(["api.example.com", "data.example.gov"]);

function isPublicAddress(ip: string): boolean {
  if (net.isIPv6(ip)) {
    // reject loopback, link-local, unique-local and v4-mapped
    return !/^(::1$|fe[89ab]|fc|fd|::ffff:)/i.test(ip);
  }
  const [a, b] = ip.split(".").map(Number);
  if (a === 10 || a === 127 || a === 0) return false;
  if (a === 169 && b === 254) return false;        // IMDS lives here
  if (a === 172 && b >= 16 && b = 64 && b <= 127) return false; // CGNAT
  return true;
}

export async function guardedFetch(rawUrl: string): Promise<Response> {
  const url = new URL(rawUrl);
  if (url.protocol !== "https:") throw new Error("https only");
  if (!ALLOWED_HOSTS.has(url.hostname)) throw new Error("host not allowed");

  const { address } = await dns.lookup(url.hostname);
  if (!isPublicAddress(address)) throw new Error("resolves to a private range");

  // Pin the resolved address so DNS cannot change between check and use.
  const pinned = new URL(url);
  pinned.hostname = address;

  return fetch(pinned, {
    redirect: "manual",                 // never follow a redirect blindly
    headers: { Host: url.hostname },    // keep SNI and Host honest
    signal: AbortSignal.timeout(10_000),
  });
}
```

Three things in that snippet are the whole lesson. The allowlist is on hostnames you chose, not a blocklist on addresses the attacker chose. The DNS lookup happens once and the address is pinned, which closes the rebinding window DINUM had. Redirects are not followed; if a tool legitimately needs to follow one, read the Location header and run it back through the same guard. The hand-rolled range check is there to make the logic readable. In production use a maintained library for the address classification, for the reason the MCP spec gives: octal, hex and IPv4-mapped IPv6 encodings defeat most home-made parsers.

The Google toolbox fix is in Go and is worth reading as a reference implementation. It added allowPrivateNetworks, allowedIpRanges and customBlockedIpRanges as explicit configuration, defaulted to blocking anything that is not global unicast, and validates the configured base URL at startup so a bad config fails fast instead of on first request.

## Fix two: the network the server runs in

Code review catches the fetch you found. Network egress control catches the one you did not. The IETF draft's mitigation list includes enforcing container-level egress restrictions independently of application code, and on Azure that maps to specific choices.

- **Azure Container Apps.** Only a workload profiles environment supports user-defined routes, NAT Gateway egress and Azure Firewall integration. The legacy consumption-only environment supports none of them. If your MCP server is on a consumption-only environment, you cannot restrict its outbound traffic at the network layer at all. Move it. Then add a UDR that sends all outbound traffic through Azure Firewall with an application rule allowlist of the FQDNs the server legitimately calls.
- **App Service and Functions.** Enable VNet integration, turn on route-all, and put an NSG and a firewall on the outbound path. Review whether the app's identity needs the roles it has; a token minted through a stolen identity endpoint call is only as dangerous as the role assignments behind it.
- **AKS.** Network policies that deny egress by default, plus an egress gateway, plus the usual IMDS restriction so pods cannot reach the node's metadata endpoint unless they need to.
- **Do not rely on the gateway.** APIM and Front Door sit on the inbound side. They see the tool call arrive. They do not see where your server goes next.

The second fix pays off when a dependency, not your code, is the problem. The researcher's September post also named Anthropic's reference fetch server and Microsoft's Playwright MCP server as carrying variants of the same gap, with fix status unconfirmed when he wrote it. If one of those runs in your environment, egress control is the mitigation you can apply today without waiting for upstream.

## Who needs to do what

| Your situation | Priority action | Effort |
| --- | --- | --- |
| You wrote MCP servers that fetch anything | Code audit of every outbound request path, guarded fetch, redirect policy, startup validation of configured endpoints | One to three days per server |
| You run third-party or open-source MCP servers on Azure | Egress allowlist at the network layer; check each project's advisories; pin versions | Half a day per environment |
| You use Google MCP Toolbox for Databases | Confirm 1.5.0 or later everywhere; review allowPrivateNetworks and the IP range settings | Hours |
| You only consume MCP through Foundry or Copilot Studio | Inventory the servers, confirm who operates each one, ask them the SSRF question in writing | Hours, plus waiting |
| You run multi-agent orchestration | Treat tool results from one server as untrusted input to every other agent; never pass them as instructions | Design change |

## The Swedish and EU angle

**DINUM is the case to show your management.** A national digital directorate shipped an MCP server for open data, received a report, and merged the fix on 4 September. Swedish agencies and municipalities building MCP front-ends to their own open-data portals and case systems are in the same position. A competent government team made the same mistake Google made, and the fix took days once reported. The question for a Swedish myndighet is whether anyone would know where to send the report.

**The Cyber Resilience Act clock started on 11 September 2026.** From that date, manufacturers of products with digital elements must report actively exploited vulnerabilities and severe incidents through the ENISA single reporting platform, with an early warning due within 24 hours. An MCP server you ship to customers, as a product or as part of one, is a product with digital elements. An SSRF that someone actually uses against a customer deployment is a reportable event. The full set of CRA obligations lands in December 2027, but the reporting duty is live now.

**Personal data behind the private endpoint turns this into GDPR.** The five open US federal findings are a logging issue: upstream error responses containing personal data written unredacted to centralised logs. The same pattern in an Azure deployment, where a tool result reflects the response from an internal service back through the agent, is a personal data breach under Article 33 the moment it is exploited, with the 72-hour notification clock to IMY attached. Review what your tools echo back, not only what they fetch.

**Procurement should ask the question now.** Add a line to the AI vendor questionnaire: for every MCP server in the offering, how does the server validate outbound request targets, does it follow redirects, and what network egress controls apply to the hosting environment. A vendor who answers "the gateway handles it" has described inbound control and not answered.

## Checklist for this week

- **1. Inventory.** List every MCP server your organisation runs or consumes, where it runs, which identity it carries, and who operates it.
- **2. Grep for fetches.** In each server you own, find every outbound HTTP call and trace the origin of its URL, host and headers. Include configuration fields and upstream data, not only tool arguments.
- **3. Guard the client.** Hostname allowlist, resolved-address check with pinning, manual redirects, HTTPS only, startup validation of configured base URLs. Use a maintained address-classification library.
- **4. Restrict egress.** Container Apps on a workload profiles environment with a UDR to Azure Firewall; VNet integration with route-all on App Service; deny-by-default network policies on AKS.
- **5. Patch the known ones.** Google MCP Toolbox to 1.5.0 or later. Check advisories for every open-source server you run, and pin versions.
- **6. Check what tools echo back.** Cap response sizes and strip anything from an internal service that should not reach the model, let alone the logs.
- **7. Publish a security contact.** A security.txt and a disclosure address on every MCP endpoint you expose. The five organisations that fixed this fast all had somewhere to send the report.

The researcher put the thesis in one sentence: the developer treats data crossing the MCP boundary as trusted because it came from inside the system. The model is inside the system. What the model read is not.

## Sources

- [Syed Anas Mohiuddin: Protocol Pivoting, four months later (6 October 2026)](https://anas-security-portfolio.vercel.app/protocol-pivoting-update.html)
- [The Next Web: Google, JPMorgan and two governments fixed the same MCP flaw (6 October 2026)](https://thenextweb.com/news/mcp-flaw-ssrf-google-jpmorgan-dinum-protocol-pivoting)
- [Syed Anas Mohiuddin: Four vendors, one bad assumption: SSRF in MCP servers (29 September 2026)](https://dev.to/syedanas01/four-vendors-one-bad-assumption-ssrf-in-mcp-servers-48ii)
- [GitHub Advisory Database: CVE-2026-14540, Google mcp-toolbox SSRF](https://github.com/advisories/GHSA-3x3x-8ffg-ghcv)
- [googleapis/genai-toolbox PR #3448: implement SSRF guard (merged 18 June 2026)](https://github.com/googleapis/genai-toolbox/pull/3448)
- [Wazuh-MCP-Server advisory GHSA-pw2j-pj4h-f5vg (3 September 2026)](https://github.com/INFOKOM-KI/Wazuh-MCP-Server/security/advisories/GHSA-pw2j-pj4h-f5vg)
- [IETF Internet-Draft: Security Considerations for MCP Implementations in AI Agent Systems](https://www.ietf.org/archive/id/draft-mohiuddin-mcp-security-considerations-00.html)
- [MCP specification 2026-07-28: Security best practices](https://modelcontextprotocol.io/specification/2026-07-28/basic/security_best_practices)
- [Microsoft Learn: Connect Foundry agents to MCP server endpoints](https://learn.microsoft.com/en-us/azure/foundry/agents/how-to/tools/model-context-protocol)
- [Microsoft Learn: Overview of MCP servers in Azure API Management](https://learn.microsoft.com/en-us/azure/api-management/mcp-server-overview)
- [Microsoft Learn: Extend your Copilot Studio agent with MCP](https://learn.microsoft.com/en-us/microsoft-copilot-studio/agent-extend-action-mcp)
- [Microsoft Learn: Azure Instance Metadata Service, security and authentication](https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service)
- [Microsoft Learn: Managed identities in App Service, REST endpoint reference](https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity)
- [Microsoft Learn: Networking in an Azure Container Apps environment](https://learn.microsoft.com/en-us/azure/container-apps/networking)

---

Technspire AB builds AI agents, Azure OpenAI solutions, and production web platforms for Swedish and EU enterprises. Book a call: https://calendly.com/technspire · hello@technspire.com · More articles: https://technspire.com/en/blog · Site overview for agents: https://technspire.com/llms.txt
