TachyonicTachyonic

We Tested Two MCP Implementations Against Three Attack Classes — Here's What Broke

Mar 3, 2026 by Emmanuel Ndangurura

Our previous research identified three vulnerability classes in the MCP SDKs: tool capability shadowing (H1), token audience confusion (H2), and stale authorization (H3). That work examined the protocol and SDK source code.

This is what happens when you test those hypotheses against production systems.

We assessed two real-world MCP implementations — one using stdio transport, one using Streamable HTTP — and traced every confirmed vulnerability back to a normative gap in the MCP specification. Eleven implementation bugs. Seven specification gaps. One hundred percent reproduction rate.


Abstract

Systematic security assessment of MCP implementations across two production AI platforms and the MCP protocol specification. Three classes of boundary vulnerabilities tested against live deployments. Eleven implementation-level vulnerabilities confirmed, traced to seven normative gaps in the MCP specification. All findings reproducible with automated test suites achieving 100% pass rates.

This is the first published independent assessment of production MCP implementations against the vulnerability classes identified in our SDK audit.


Methodology

Our assessment followed a six-phase approach designed to separate scanner noise from genuine findings and tie every confirmed vulnerability to its root cause in the protocol.

Phase 1 — Reconnaissance. We cloned open-source repositories, analyzed MCP server configurations, mapped tool registrations, reviewed authentication mechanisms, and documented permission models for both targets.

Phase 2 — Lab Reproduction. We built a mock MCP lab using Flask and JSON-RPC with three hypothesis-specific endpoints. This controlled environment let us validate our attack tooling before touching production systems.

Phase 3 — Automated Scanning. We ran our tachyonic CLI scanner against the mock lab, Platform A (stdio transport), and Platform B (Streamable HTTP transport). Scan categories included tool abuse, permission escalation, and multi-agent injection.

Phase 4 — Manual Triage. Every scanner finding was classified as true positive (TP) or false positive (FP). This phase was critical — 37 out of 41 scanner findings against production targets were false positives. Scanner precision on live targets was 9.8%, compared to approximately 100% in the controlled lab.

Phase 5 — Reproduction Hardening. We built automated reproduction suites for all confirmed findings. Platform A: 14 out of 14 tests passing. Platform B: 8 out of 8 tests passing. Every vulnerability is reproducible on demand.

Phase 6 — Specification Analysis. We traced each confirmed vulnerability to a normative gap in the MCP specification, identifying where the protocol's silence creates the conditions for implementation-level bugs.


Targets

TargetTypeMCP TransportToolsHypotheses Confirmed
Platform AOSS (stdio)stdio via npx7 toolsH2 (partial), H3 (recon)
Platform BOSS (HTTP)Streamable HTTP30 toolsH1 (partial), H2 (partial)
MCP SpecificationProtocolN/AN/AAll three

Platform A is a code search platform that exposes 7 MCP tools over stdio transport. Its MCP server runs as a local process invoked via npx. Authentication uses flat API keys with no per-tool scoping.

Platform B is a workflow builder platform that exposes 30 MCP tools over Streamable HTTP transport. Authentication uses OAuth with a single scope covering all 30 tools.

Both are open-source. Both have active production deployments. Both were assessed with the same methodology.


Hypothesis Results

H1: Tool Capability Shadowing

Lab: Confirmed. When two servers register identical tool names, the SDK silently routes to the highest-priority registration. No error, no warning to the LLM.

Production: Not directly confirmed on live targets — neither platform runs in a multi-server configuration where we could inject a shadow server. However, tool-schema poisoning (specification gap SG-4) demonstrates a related vector. Platform B's 30 tool descriptions contain imperative LLM directives embedded in their schema fields — an invisible instruction channel that influences model behavior without the user's knowledge.

H2: Token Audience / Scope Confusion

Lab: Confirmed. Tokens minted for one server are accepted by a different server without audience validation.

Production: Both platforms exhibit the underlying condition. Platform A uses flat API keys that are inherently unscopable — the same key grants access to all 7 tools with no mechanism to restrict access to a subset. Platform B's OAuth implementation declares a single scope that covers all 30 tools. There is no per-tool authorization boundary. A token that grants access to a read-only tool also grants access to every write and execute tool on the server.

Protocol maintainer response: The MCP team confirmed that TokenVerifier is an interface — audience validation is the implementer's responsibility. Their security tutorial includes working examples of audience validation in TypeScript, Python, and C#, each requiring custom code to check the aud claim against the server's URL. The SDK provides the mechanism but not the policy: the TokenVerifier.verify_token() interface has no expected_audience parameter, so every implementer must independently discover and build audience checking. Neither platform in our assessment did.

H3: Stale Authorization

Lab: Confirmed. Cached permissions persist after revocation for the duration of the cache TTL.

Production: Platform A's permission synchronization operates on a 24-hour polling cycle. API keys have no expiration. When source access is revoked, the MCP server continues serving results from the previously-authorized source for up to 24 hours. This is not a cache TTL issue — it is an architectural decision that creates a fixed 24-hour stale authorization window.


Confirmed Vulnerabilities

Platform A — 7 True Positives

IDVulnerabilitySeverityCWECVSS 4.0Spec Gap
TP-1Command flag injection via unsanitized parameter — exposes all branches, developer identifiers, internal ticket referencesHIGHCWE-887.5SG-1
TP-2Path traversal causes unhandled 500 crashMEDIUMCWE-225.3SG-1
TP-3Additional command injection causes 500 errors across multiple toolsMEDIUMCWE-885.3SG-1
TP-4Cross-resource unauthenticated searchMEDIUMCWE-8625.3SG-5
TP-5Sensitive pattern exposure via regex searchLOW3.7
TP-6Unauthenticated AI agent accessLOW3.7SG-5
TP-7Query injection via filter parameterINFOCWE-9432.0

TP-1 is the most severe. A single unsanitized parameter allows command flag injection that causes the underlying CLI tool to expose metadata it should never return through the MCP interface. This includes internal branch names, developer identifiers, and project management references — information that an external user should not be able to access through a code search tool.

TP-2 and TP-3 share the same root cause (SG-1): the MCP specification provides no concrete guidance on input sanitization for tool parameters. The server passes user-controlled input directly to system commands without validation, resulting in unhandled crashes. These are not data exfiltration vulnerabilities, but they demonstrate that the server's error handling assumes trusted input.

TP-4 and TP-6 trace to SG-5: the MCP specification defines no per-tool authorization scoping. The API key grants access to all tools equally. There is no mechanism to say "this key can search public repositories but not private ones" or "this key can read but not trigger agent actions."

Platform B — 4 True Positives

IDVulnerabilitySeverityCWECVSS 4.0Spec Gap
TP-1System prompt leak via initialize — 1,678 characters exposed, no authentication requiredHIGHCWE-2005.3SG-2
TP-2Unauthenticated tool enumeration — 30 tools with full schemas exposedMEDIUMCWE-2005.3SG-3
TP-3Internal infrastructure leak via OAuth discovery — cloud provider hostnames, VPC IP addressesMEDIUMCWE-2005.3SG-6
TP-4Tool descriptions contain behavioral LLM directives (tool-schema poisoning)LOWSG-4

Platform B's vulnerabilities are all information disclosure, but the information disclosed is operationally significant.

TP-1 exposes the full system prompt — 1,678 characters of behavioral instructions — to any unauthenticated client that sends an initialize request. The MCP specification's instructions field is returned before authentication completes. This system prompt contains the platform's proprietary logic for how the AI agent should behave, what it should prioritize, and how it should handle edge cases. Competitors can read it. Attackers can study it to craft targeted prompt injections.

TP-2 returns the full tool registry — all 30 tools with complete JSON schemas — without requiring authentication. This is the platform's entire attack surface, enumerated for free. The MCP specification's tools/list endpoint has no authentication requirement.

TP-3 leaks internal infrastructure details through the OAuth discovery endpoint. The well-known configuration response includes internal hostnames that reveal the cloud provider, region, and VPC topology. This is reconnaissance gold for an attacker planning lateral movement.

TP-4 is subtle but important. Platform B's tool descriptions contain imperative directives aimed at the LLM — instructions like "always use this tool first" or "prefer this tool over alternatives." These are not user-visible. They influence model behavior through a channel that the user cannot inspect or override.


Specification Gaps

Every confirmed vulnerability traces to a normative gap in the MCP specification. These are not implementation mistakes — they are predictable consequences of the protocol's silence on security-critical topics.

IDGapSeverityImplementations Affected
SG-1No concrete input sanitization guidanceHIGHPlatform A (TP-1, TP-2, TP-3)
SG-2instructions field unconstrained — returned before authenticationHIGHPlatform B (TP-1)
SG-3tools/list has no authentication requirementMEDIUMPlatform B (TP-2)
SG-4Tool description field has no content constraintsMEDIUMPlatform B (TP-4)
SG-5No per-tool authorization scopingMEDIUMBoth platforms
SG-6OAuth discovery has no internal-information-leak prohibitionMEDIUMPlatform B (TP-3)
SG-7No token revocation notification mechanismLOWPlatform A (recon)

SG-1 is the most impactful gap. The MCP specification tells implementers to expose tools but provides no guidance on how to sanitize the arguments those tools receive. Platform A passes tool parameters directly to shell commands. This is the obvious default when the protocol says nothing about input handling.

SG-2 and SG-3 together create an excessive pre-authentication information surface. Before a client proves its identity, it can learn the server's full system prompt and enumerate every available tool with complete schemas. The specification does not require authentication for either operation.

SG-5 affects both platforms. The MCP protocol defines authentication at the server level but not at the tool level. A valid token grants equal access to every tool on the server. There is no mechanism for a server to say "this token can call search but not delete."

SG-7 is lower severity but architecturally significant. When a token is revoked, there is no protocol-level mechanism to notify the MCP server. The server continues honoring the cached token until its local cache expires. In Platform A's case, the polling-based permission sync extends this window to 24 hours.


Cross-Cutting Themes

Four patterns emerged across both assessments.

1. Specification Silence Creates Implementation Bugs

Neither platform made unusual engineering decisions. Both followed the MCP specification's guidance — or more precisely, followed the path of least resistance where the specification provides no guidance. The specification says "expose tools." It does not say "sanitize tool arguments." The specification says "use OAuth." It does not say "scope tokens per tool."

The MCP security tutorial acknowledges many of these risks — "do not implement token validation or authorization logic by yourself," "don't configure or accept generic audiences," "split access per tool or capability." But the guidance lives in a tutorial page, not in the SDK's default behavior. The TokenVerifier interface accepts a token string and returns an access token object. There is no parameter for expected audience, no default scope enforcement, no built-in input sanitization. Implementers who do not find and follow the tutorial — or who rely on the SDK's defaults — inherit every gap.

When a protocol is silent on a security-critical topic, every implementer must independently discover and solve the problem. Most will not. The result is systemic vulnerability across the ecosystem.

2. The Pre-Authentication Information Surface Is Excessive

Platform B exposes its system prompt and full tool registry before authentication. This is not a bug in Platform B — it is the MCP protocol's design. The initialize response includes the instructions field. The tools/list response includes every tool. Neither requires a valid token.

An unauthenticated attacker can map the entire attack surface of any MCP server that follows the specification.

3. Tool Descriptions Are an Invisible Instruction Channel

Platform B's tool descriptions contain imperative directives that influence LLM behavior. The user never sees these instructions — they are embedded in the tool schema and passed directly to the model. The MCP specification places no constraints on what a tool description can contain.

This is tool-schema poisoning. It is the MCP equivalent of invisible prompt injection, delivered through the protocol's own metadata channel.

4. Authorization Is All-or-Nothing

Both platforms implement authentication at the server level. Once a client has a valid token, it can call any tool. There is no per-tool authorization, no role-based access control within a server, no way to grant read access without also granting write access.

The MCP specification defines scopes but provides no guidance on mapping scopes to individual tools. Platform B declares a single scope for all 30 tools. Platform A uses API keys with no scoping mechanism at all.


Scanner vs. Manual Signal

The gap between automated scanning and manual assessment is the most operationally significant finding for teams building AI security tooling.

TargetTransportTests DispatchedScanner FindingsTrue PositivesFalse PositivesManual AdditionsFinal TP Count
Mock LabHTTP22622622600226
Platform Astdio38220416+37
Platform BHTTP38221021+44

In the controlled lab, scanner precision was 100%. Every finding was genuine because the mock server was designed to be vulnerable.

Against production targets, scanner precision dropped to 9.8%. Thirty-seven out of 41 scanner findings were false positives — cases where the model refused the attack but quoted evidence strings in its refusal, triggering the scanner's detection heuristics.

Manual testing found 7 vulnerabilities the scanner missed entirely. Platform B's 4 true positives were all discovered through manual testing — the scanner produced zero true positives against that target.

The takeaway: automated scanning is necessary for coverage but insufficient for accuracy. Every scanner finding requires manual triage. And the most impactful vulnerabilities — system prompt leaks, infrastructure exposure, authentication bypasses — are often invisible to pattern-matching scanners because they involve protocol-level behavior, not payload-level responses.


What Should Change

For the MCP Specification

  1. Publish input sanitization guidance. The specification should include normative requirements for how tool parameters must be validated before use, particularly when tools invoke system commands or file operations.

  2. Require authentication for tools/list and initialize. The protocol should not expose the server's capability surface and system prompt to unauthenticated clients.

  3. Constrain the instructions field. Define what the instructions field may and may not contain, and require that it be withheld until authentication succeeds.

  4. Define per-tool authorization scoping. The protocol needs a mechanism for mapping OAuth scopes to individual tools, so that a token can grant access to a subset of a server's capabilities.

  5. Add a token revocation notification mechanism. Servers need a way to learn about revocations without waiting for cache expiry.

  6. Constrain tool description content. Define boundaries for what tool descriptions may contain, preventing their use as an invisible LLM instruction channel.

  7. Add OAuth discovery content guidance. The specification should warn implementers not to expose internal infrastructure details through well-known configuration endpoints.

For Teams Deploying MCP Today

  1. Sanitize all tool parameters. Do not pass user-controlled input directly to shell commands, SQL queries, or file system operations. Treat every tool argument as untrusted.

  2. Add authentication to tools/list. Even if the specification does not require it, your server should.

  3. Review your system prompt exposure. If your initialize response includes an instructions field, assume it is public. Do not put proprietary logic or sensitive information in it.

  4. Audit your OAuth discovery endpoint. Remove internal hostnames, VPC addresses, and any infrastructure details from your .well-known configuration.

  5. Review tool descriptions for embedded directives. If your tool descriptions contain instructions aimed at the LLM rather than the user, consider whether those directives should be there.

  6. Implement per-tool authorization at the application level, even though the protocol does not require it. Map your OAuth scopes to specific tool subsets.

  7. Minimize your permission sync window. If your MCP server caches authorization decisions, keep the TTL as short as operationally feasible. For destructive operations, bypass the cache entirely.


Disclosure

The findings in this report describe vulnerability classes and their manifestation in anonymized production implementations. Vendor-specific findings have been reported to the affected parties through responsible disclosure. The MCP specification gaps were reported to the protocol maintainers, who classified them as informative — the SDK provides interfaces, and security enforcement is the implementer's responsibility.

This publication describes vulnerability patterns and specification gaps. It does not include exploit code, specific endpoint paths, or information sufficient to reproduce the findings against the assessed platforms.


Methodology Notes

Scanner: Our 122-attack taxonomy (open source), executed via our CLI scanner against MCP servers.

False positive handling: Raw scanner output had a 9.8% true positive rate against production targets (4 TP out of 41 findings). All results in this report were manually triaged to confirmed findings only. Genuine = the tool executed with attacker-controlled arguments, or an information disclosure endpoint returned sensitive data without authentication.

Reproduction suites: Platform A: 14/14 automated tests passing. Platform B: 8/8 automated tests passing. Every finding in this report is reproducible on demand.

Evidence integrity: All evidence packs are SHA256-checksummed at time of collection.

Total assessment cost (scanner runs): $2.83.


Tachyonic provides 48-hour AI red team assessments. If your product uses MCP, tool-calling agents, or any LLM with external integrations, we test the boundaries that matter. Book a 15-minute scoping call. Our 122-attack taxonomy is open source.

Secure Your AI Agents

We find vulnerabilities in AI applications in 48 hours. Resistance score, reproduction steps, remediation playbook included.

Book a Free Scoping Call