01Scoping and Inventory
Everything starts with defining the object under test: transport (stdio, Streamable HTTP or the deprecated HTTP+SSE path), protocol revision and the three parties server, client/host and gateway. Only the revision determines which attack classes exist at all – session hijacking via the Mcp-Session-Id header, for example, no longer exists in revision 2026-07-28, while state handles and header-body validation are added instead. We catalogue every server, every tool including its full definition, every credential and every target system reachable through it, and we establish in writing beforehand which test identities and scopes will be used, because tools/list may vary depending on the authorisation presented. The testing tools themselves are also part of the scoping: the MCP Inspector – the project's official testing tool – was itself the subject of a critical vulnerability with CVE-2025-49596, which was only fixed in version 0.14.1; it must therefore be version-tracked and disclosed in the report.
02Identity and Permissions (MCP07, MCP02)
Here we test against normative requirements rather than against taste: a tool call without a token or with an invalid token must end with 401 and a correct WWW-Authenticate header, and the discovery chain must be present and correctly linked. A distinction is important here: Protected Resource Metadata per RFC 9728 is mandatory for MCP servers, while for the authorisation server either RFC 8414 or OpenID Connect Discovery 1.0 is sufficient – anyone who only checks for RFC 8414 will produce a false finding with OIDC servers. For OAuth URLs, the specification expects HTTPS outside of loopback addresses. The central test case is audience validation, because the specification explicitly prohibits token passthrough – a server must not accept tokens that were not issued for it. With proxy architectures, the confused deputy path is added: a dedicated consent page per client, exact string comparison of the redirect_uri without wildcards, and a cryptographically generated, single-use state parameter. In addition, we examine scope minimisation: wildcard or omnibus scopes, bundled privileges, and servers that trust the scope claim in the token without authorising themselves.
03Tool Definitions: Poisoning, Shadowing, Rug Pull (MCP03)
Tool descriptions, parameter documentation and JSON schemas are an instruction channel that the model reads authoritatively and that humans, as a rule, never see in full in the user interface. We first create a baseline: every definition from tools/list, resources/list and prompts/list is hashed field by field and serves as a reference for later comparisons. Three tests follow – the comparison of the text visible in the client with the description actually passed to the model, the controlled rug pull test in the test environment (if an already approved definition changes, the host must request consent again or report the change), and the shadowing test with two servers connected in parallel that offer identically named or functionally overlapping tools. The class is proven in practice: with CVE-2025-54136 in Cursor, changes to already approved MCP configurations took effect without renewed consent.
04Indirect Prompt Injection via Tool Outputs (MCP06)
Not only the description but also the return side is an attack surface: the specification explicitly obliges servers to sanitise tool outputs (MUST) and recommends that clients validate tool results before passing them to the model (SHOULD) – the weaker requirement on the client side must be reflected in the wording of the finding. We first inventory all channels through which third-party content enters the context – tool responses, retrieved pages and documents, repository content, tickets, mailboxes, persisted memory – and introduce a harmless, clearly traceable marker into each channel in order to observe whether the agent treats it as an instruction or as data. In doing so, we examine a core architectural question: is there a separation of provenance between instructions and data, or do both end up in the same context window? If an agent simultaneously has access to sensitive data, processes untrusted content and has the ability to communicate externally – the lethal trifecta according to Simon Willison – the finding can already be justified architecturally, even without a successful individual demonstration.
05Transport, Execution and Supply Chain (MCP05, MCP04, MCP09)
Hard requirements apply at the transport layer: servers must validate the Origin header of incoming connections, and locally running instances should bind to 127.0.0.1 instead of 0.0.0.0 – otherwise a single visited website is enough to talk to a local server via DNS rebinding. We test server-side validation against the declared schema, the handling of URLs in the OAuth discovery path (private and link-local ranges, redirect chains, DNS rebinding as a TOCTOU scenario) as well as sandboxing and egress control of tool execution; proof that an input reaches an interpreter unvalidated is already the finding. On the supply chain side, we reconcile registry entry, repository and maintainer and check version pinning, signatures and approval gates for updates – labels such as "official" or "verified" are no proof of trustworthiness, as CVE-2025-6514 in the widely used package mcp-remote has shown (versions 0.0.5 to 0.1.15 are affected, fixed in 0.1.16). Added to this is the search for shadow servers via repository and endpoint scans, repeated network scans with a differential report, and evaluation at the gateway, because that is where it is measured which servers an agent actually contacts – and not merely which ones appear in the configuration.
06Telemetry, Evidence and Reporting (MCP08)
The hardest question comes at the end: can it be reconstructed after the fact which agent called which tool at which point in time, with which parameters and on behalf of which identity? To this end, we carry out a defined, harmless sequence of actions – connection, tool listing, several calls, one rejected call – and then attempt to reconstruct exactly this sequence from the logs alone; a clean negative finding is a fully valid result here, because it renders all other findings unprovable in operation. In the report we separate two categories of evidence: configuration and architecture findings can be demonstrated deterministically, behaviour-based findings cannot – for these we state the number of repetitions, the hit rate as well as the model, client and version. Each finding is additionally assigned to the layer on which it sits (protocol and transport, authorisation, tool definition, client/host, agent layer), because countermeasures and the responsible party differ per layer.