<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ahmed Hassan</title>
    <description>The latest articles on DEV Community by Ahmed Hassan (@aah20).</description>
    <link>https://dev.to/aah20</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4090002%2F338fa041-59be-43b9-9c77-6b1b7494d852.jpg</url>
      <title>DEV Community: Ahmed Hassan</title>
      <link>https://dev.to/aah20</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aah20"/>
    <language>en</language>
    <item>
      <title>I found a confirmed bug in the official MCP SDK while building a red-team tool for it</title>
      <dc:creator>Ahmed Hassan</dc:creator>
      <pubDate>Sat, 22 Aug 2026 17:30:37 +0000</pubDate>
      <link>https://dev.to/aah20/i-found-a-confirmed-bug-in-the-official-mcp-sdk-while-building-a-red-team-tool-for-it-18om</link>
      <guid>https://dev.to/aah20/i-found-a-confirmed-bug-in-the-official-mcp-sdk-while-building-a-red-team-tool-for-it-18om</guid>
      <description>&lt;p&gt;Model Context Protocol (MCP) is having a rough year. In the last fourteen months: a CVSS 9.4 RCE in Anthropic's own MCP Inspector, a prompt-injection exfiltration bug in GitHub's MCP server, a supply-chain disclosure in April 2026 that touched the official SDKs across four languages, and — just this June — RufRoot: an unauthenticated MCP bridge in an open-source agent platform with 67,000+ GitHub stars, giving full remote code execution from a single HTTP request.&lt;/p&gt;

&lt;p&gt;Existing red-teaming tools (garak, PyRIT, promptfoo) are built for prompt injection and jailbreaks against a model. None of them connect to a live MCP server and test the protocol-level failure modes above — the ones that don't care what the model says, only what the server actually lets happen.&lt;/p&gt;

&lt;p&gt;So I built &lt;a href="https://github.com/AAH20/mcp-redteam" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-redteam&lt;/code&gt;&lt;/a&gt;: a small tool that connects to a real MCP server — over stdio or Streamable HTTP — and runs six adversarial scenarios, each modeled on a real, disclosed incident or a currently-open issue on a funded organization's own project. Not hypotheticals.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug I didn't expect to find
&lt;/h2&gt;

&lt;p&gt;Building the HTTP test fixtures, I hit something strange: the second request to a stateless &lt;code&gt;StreamableHTTPServerTransport&lt;/code&gt; instance always failed with a bare &lt;code&gt;500&lt;/code&gt; and an empty body — no exception, no stack trace, nothing reaching my error handlers. The first request (an &lt;code&gt;initialize&lt;/code&gt; call) always worked. Every request after it, on the same transport instance, didn't.&lt;/p&gt;

&lt;p&gt;I reproduced it two independent ways — raw &lt;code&gt;node:http&lt;/code&gt; and Express — before finding &lt;a href="https://github.com/modelcontextprotocol/typescript-sdk/issues/1994" rel="noopener noreferrer"&gt;&lt;code&gt;modelcontextprotocol/typescript-sdk#1994&lt;/code&gt;&lt;/a&gt;: a confirmed, still-open regression. The &lt;code&gt;1.25.0&lt;/code&gt; rewrite bridges Node's HTTP objects through &lt;code&gt;@hono/node-server&lt;/code&gt;'s &lt;code&gt;getRequestListener&lt;/code&gt;, and an exception thrown inside that bridge becomes a generic Hono 500 — bypassing the SDK's own &lt;code&gt;onerror&lt;/code&gt; callback and JSON-RPC error formatting entirely. It's a real trap: the SDK's own documented "stateless mode" example doesn't reuse a transport across requests, but nothing stops you from doing it, and when you do, the failure is nearly undiagnosable from the outside.&lt;/p&gt;

&lt;p&gt;I posted an independent confirmation on the issue — reproduced on the current published SDK version, confirmed it wasn't specific to one HTTP framework — and the fix (construct a fresh transport per request) is now baked into &lt;code&gt;mcp-redteam&lt;/code&gt;'s own test fixtures with a comment explaining exactly why.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the tool actually checks
&lt;/h2&gt;

&lt;p&gt;Six scenarios, each with a real citation, not a vibe:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tool description/schema stability&lt;/strong&gt; — does a tool change what it does after being inspected once ("rug pull")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unannotated destructive tools&lt;/strong&gt; — destructive-sounding tools with no &lt;code&gt;destructiveHint&lt;/code&gt; annotation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Oversized-payload handling&lt;/strong&gt; (opt-in) — does a "read-only" tool bound a large argument or hang — echoes a still-open finding on a real &lt;code&gt;litellm&lt;/code&gt; PR&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unauthenticated tool exposure&lt;/strong&gt; — modeled directly on RufRoot (CVE-2026-59726, CVSS 10.0)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Token audience validation&lt;/strong&gt; — does the server actually enforce the MCP spec's own MUST-validate-audience requirement, or just check that some Authorization header exists&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tools/call&lt;/code&gt; authorization bypass&lt;/strong&gt; — is &lt;code&gt;tools/call&lt;/code&gt; gated as strictly as &lt;code&gt;tools/list&lt;/code&gt;, modeled on the same pattern showing up independently in &lt;code&gt;wso2/api-platform#2869&lt;/code&gt; and two separate &lt;code&gt;litellm&lt;/code&gt; issues (&lt;code&gt;#31977&lt;/code&gt;, &lt;code&gt;#36358&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Testing it against something real
&lt;/h2&gt;

&lt;p&gt;I didn't want to ship this against only my own fixtures, so I ran it against LangFlow (153K+ GitHub stars) — a platform with a real, currently-relevant CVE (CVE-2026-33017, an unauthenticated RCE via its MCP adapter, still exploitable in the version the ecosystem widely believed was patched, per JFrog's research). The result was a clean negative: LangFlow's actual MCP protocol endpoint correctly requires authentication across every scenario. Worth stating plainly — that's not a miss, it's the tool telling the truth. The real CVE lives in a different layer (LangFlow's own REST API session-bootstrap logic, not its MCP server's protocol handling), which is outside what a pure MCP-protocol tester like this one checks — and I'd rather say that clearly than force a positive result to make the story better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this, and not another jailbreak scanner
&lt;/h2&gt;

&lt;p&gt;Prompt injection tooling is already a crowded, well-funded lane (OpenAI acquired Promptfoo for this exact space in March 2026). Protocol-level MCP testing — does the server actually enforce what its own spec requires — is not. Every scenario above traces to something a real, funded organization is dealing with right now, not a hypothetical I invented to have something to build.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/AAH20/mcp-redteam" rel="noopener noreferrer"&gt;https://github.com/AAH20/mcp-redteam&lt;/a&gt; — 18/18 tests passing, CI green on Node 20/22/24, Apache-2.0.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>security</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
