<?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: Gowthaman</title>
    <description>The latest articles on DEV Community by Gowthaman (@gowthaman90).</description>
    <link>https://dev.to/gowthaman90</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%2F281464%2F8872ba83-7b1e-4490-a361-fe2a9d38e53c.jpeg</url>
      <title>DEV Community: Gowthaman</title>
      <link>https://dev.to/gowthaman90</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gowthaman90"/>
    <language>en</language>
    <item>
      <title>From 9% to 63%: Letting a Benchmark Build a Better MCP Security Proxy</title>
      <dc:creator>Gowthaman</dc:creator>
      <pubDate>Thu, 16 Jul 2026 21:09:21 +0000</pubDate>
      <link>https://dev.to/gowthaman90/from-9-to-63-letting-a-benchmark-build-a-better-mcp-security-proxy-3gg8</link>
      <guid>https://dev.to/gowthaman90/from-9-to-63-letting-a-benchmark-build-a-better-mcp-security-proxy-3gg8</guid>
      <description>&lt;h3&gt;
  
  
  You can't improve what you don't measure. So I measured how much of the AI-agent attack surface a defense actually covers — then used that number, over and over, to build a better one.
&lt;/h3&gt;




&lt;p&gt;A year ago, "AI security" mostly meant "don't let the chatbot say something dumb." Today, AI assistants&lt;br&gt;
&lt;em&gt;act&lt;/em&gt;: they read your files, query your databases, hit APIs, and browse the web. They do it through a&lt;br&gt;
fast-spreading open standard called the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; — think of it as USB for AI&lt;br&gt;
agents, one standard plug between an assistant and the tools it uses.&lt;/p&gt;

&lt;p&gt;That plug is powerful, and it's a brand-new place for things to go wrong. A malicious or compromised&lt;br&gt;
tool can hide instructions in its own description, quietly swap its behavior after you've approved it,&lt;br&gt;
or trick the agent into shipping your credentials to an attacker. The 2025–2026 research literature now&lt;br&gt;
documents dozens of these attacks.&lt;/p&gt;

&lt;p&gt;So the obvious question: &lt;strong&gt;when you put a security tool in front of your MCP servers, how much of that&lt;br&gt;
danger does it actually stop?&lt;/strong&gt; Nobody had a good number. I set out to get one — and then something more&lt;br&gt;
useful happened. The measurement didn't just grade the defense; it &lt;em&gt;built&lt;/em&gt; it. Over the study, my&lt;br&gt;
open-source proxy &lt;a href="https://github.com/Gowthaman90/mcp-bastion" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-bastion&lt;/code&gt;&lt;/a&gt; went from covering &lt;strong&gt;9%&lt;/strong&gt;&lt;br&gt;
of the known MCP attack surface to &lt;strong&gt;63%&lt;/strong&gt;, one measured gap at a time.&lt;/p&gt;

&lt;p&gt;This is the story of that loop, and what it teaches about where AI-agent security actually stands.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, an honest measuring stick
&lt;/h2&gt;

&lt;p&gt;I built &lt;a href="https://github.com/Gowthaman90/mcp-defense-bench" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-defense-bench&lt;/code&gt;&lt;/a&gt;, an open, vendor-neutral&lt;br&gt;
benchmark that measures how much of the MCP attack surface a defensive proxy covers. Three design&lt;br&gt;
choices keep it honest, and they matter more than the headline number:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A matched benign control for every attack.&lt;/strong&gt; Every malicious test case has a near-identical
&lt;em&gt;innocent&lt;/em&gt; twin. A tool only scores if it flags the attack &lt;strong&gt;and&lt;/strong&gt; leaves the twin alone. Without
this, a "security tool" that flags &lt;em&gt;everything&lt;/em&gt; would score 100% while being useless in practice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measure only what the tool inspects at runtime.&lt;/strong&gt; Adapters drive each tool's &lt;em&gt;real&lt;/em&gt; code — not a
mock, not its docs. If a proxy inspects tool &lt;em&gt;descriptions&lt;/em&gt; but never looks at tool &lt;em&gt;results&lt;/em&gt;, it
scores zero on result-borne attacks, even if its rules &lt;em&gt;could&lt;/em&gt; have matched. We measure deployed
behavior, not theoretical capability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducible or it doesn't count.&lt;/strong&gt; A defender is scored only if its detection runs locally and
deterministically. Cloud-model "magic" that can change between runs is observed, not scored.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The rubric behind it is a &lt;strong&gt;threat–control crosswalk&lt;/strong&gt;: 24 MCP attack vectors, each mapped to an&lt;br&gt;
architectural layer, a STRIDE class, and the governance frameworks organizations actually use — the&lt;br&gt;
NIST AI Risk Management Framework, the NSA's MCP Security guidance, and the OWASP Top 10s for LLM and&lt;br&gt;
Agentic applications. (If you want the "map of the whole landscape" version of this story, that's a&lt;br&gt;
a separate write-up; here I'm focused on the improvement loop.)&lt;/p&gt;

&lt;p&gt;Each attack scores one of three levels: &lt;strong&gt;none&lt;/strong&gt; (missed), &lt;strong&gt;detect&lt;/strong&gt; (warns you), or &lt;strong&gt;enforce&lt;/strong&gt;&lt;br&gt;
(blocks it). Weighted coverage counts an enforce as 1.0, a detect as 0.5.&lt;/p&gt;




&lt;h2&gt;
  
  
  The loop: measure → find the gap → fix → measure again
&lt;/h2&gt;

&lt;p&gt;Here's the part that surprised me. A benchmark is usually a scoreboard you check at the end. This one&lt;br&gt;
became a to-do list.&lt;/p&gt;

&lt;p&gt;The proxy started at &lt;strong&gt;9%&lt;/strong&gt; — it scanned tool &lt;em&gt;descriptions&lt;/em&gt; for poisoning and nothing else. Then the&lt;br&gt;
benchmark pointed at the next gap, I closed it, and re-ran. Every step below was re-verified at &lt;strong&gt;zero&lt;br&gt;
false positives&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;What the benchmark exposed → what I added&lt;/th&gt;
&lt;th&gt;Coverage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;baseline&lt;/td&gt;
&lt;td&gt;description scanning only&lt;/td&gt;
&lt;td&gt;9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;result-borne injection → scan tool &lt;em&gt;results&lt;/em&gt;, not just definitions&lt;/td&gt;
&lt;td&gt;18%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;parameter smuggling → validate arguments against the tool's schema&lt;/td&gt;
&lt;td&gt;23%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;DNS-rebinding on local servers → an origin check that &lt;em&gt;blocks&lt;/em&gt;
&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;cross-tool exfiltration → sensitive-argument + least-privilege scanning&lt;/td&gt;
&lt;td&gt;34%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;a brand-new split-payload attack → cross-tool correlation&lt;/td&gt;
&lt;td&gt;38%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;four vectors &lt;em&gt;no tool&lt;/em&gt; covered → command-injection, config-drift, server-identity, cross-server taint&lt;/td&gt;
&lt;td&gt;48%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;depth, not breadth → evasion normalization + inline secret redaction + block-by-default&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;63%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Two moments in that table are worth slowing down on, because they're where "measure a defense" turned&lt;br&gt;
into "discover something."&lt;/p&gt;

&lt;h3&gt;
  
  
  When the benchmark caught up with a fresh attack
&lt;/h3&gt;

&lt;p&gt;Halfway through, two attacks were published (June 2026) that my frozen rubric didn't have yet:&lt;br&gt;
&lt;strong&gt;mid-session tool injection&lt;/strong&gt; (a tool that mutates its behavior &lt;em&gt;after&lt;/em&gt; you've approved it) and&lt;br&gt;
&lt;strong&gt;ShareLock&lt;/strong&gt; (a stealthy attack that splits a malicious payload across &lt;em&gt;several&lt;/em&gt; tools, so no single&lt;br&gt;
tool description looks suspicious).&lt;/p&gt;

&lt;p&gt;I verified both against their source papers, encoded each as a matched attack/benign pair, and re-ran&lt;br&gt;
every tool. The result was stark: &lt;strong&gt;ShareLock was covered by nothing.&lt;/strong&gt; Every scanner looked at one tool&lt;br&gt;
at a time and saw nothing wrong.&lt;/p&gt;

&lt;p&gt;But a &lt;em&gt;proxy&lt;/em&gt; sees the whole tool set at once. So I added &lt;strong&gt;cross-tool correlation&lt;/strong&gt; — it scans the&lt;br&gt;
combined descriptions and flags the coordinated "share/checksum"-style staging metadata the attack uses.&lt;br&gt;
&lt;code&gt;mcp-bastion&lt;/code&gt; became the first and (on the benchmark) only measured tool to catch it. A benchmark that&lt;br&gt;
only tested a fixed set of attacks would have missed this entirely. The value was in &lt;em&gt;re-measuring as&lt;br&gt;
the threat surface moved.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The attack only an aggregating proxy can see
&lt;/h3&gt;

&lt;p&gt;Later, I added &lt;strong&gt;cross-server data-flow tracking&lt;/strong&gt;. Picture an agent reading a secret from your vault&lt;br&gt;
server and then, two calls later, posting it to a webhook on a &lt;em&gt;different&lt;/em&gt; server. No single tool did&lt;br&gt;
anything wrong; the danger is in the &lt;em&gt;flow across a trust boundary&lt;/em&gt;. A per-server scanner is blind to&lt;br&gt;
it. A proxy that fronts all your servers isn't — it can watch a credential-shaped token read from server&lt;br&gt;
A reappear in an argument headed to server B, and stop it. That's not a rule you can bolt onto one&lt;br&gt;
tool; it's a capability you only get from the vantage point.&lt;/p&gt;




&lt;h2&gt;
  
  
  From "warns you" to "blocks it"
&lt;/h2&gt;

&lt;p&gt;A tool that &lt;em&gt;detects&lt;/em&gt; an attack and prints a warning is a linter. A tool that &lt;em&gt;blocks&lt;/em&gt; it is a firewall.&lt;br&gt;
The last leg of the journey (48% → 63%) was mostly about turning warnings into blocks — safely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Evasion normalization.&lt;/strong&gt; The benchmark had obfuscated variants of known attacks — payloads hidden
behind Cyrillic look-alike characters or base64. My proxy caught the invisible-character trick but
sailed right past the others. Adding a normalization pass (fold look-alikes to ASCII, decode base64,
then scan) took its robustness from &lt;strong&gt;1 of 3 evasions caught to 3 of 3.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inline secret redaction.&lt;/strong&gt; Instead of just &lt;em&gt;warning&lt;/em&gt; that a tool result contains an AWS key, the
proxy now strips the secret out of the result before the agent (or your logs) ever see it. Detection
became mitigation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Block the sure things by default.&lt;/strong&gt; The deterministic, near-zero-false-positive checks — schema
violations, command-injection payloads, exact-token cross-server leaks — now &lt;em&gt;block&lt;/em&gt; out of the box,
while the fuzzier heuristics stay as warnings. The proxy went from blocking a handful of vectors to
&lt;strong&gt;blocking 11 of the 19 it covers.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through all of it, the false-positive count stayed at &lt;strong&gt;zero across 35 test cases&lt;/strong&gt;. That's the whole&lt;br&gt;
point of the matched benign controls: you can push toward "block by default" &lt;em&gt;because&lt;/em&gt; you've proven the&lt;br&gt;
checks don't fire on innocent traffic.&lt;/p&gt;




&lt;h2&gt;
  
  
  The honest ceiling: what a proxy will never fix
&lt;/h2&gt;

&lt;p&gt;Here's the result I care about most, and it's not the 63%. It's the &lt;strong&gt;5 of 24 vectors that no measured&lt;br&gt;
tool covers — and that no content-scanning proxy ever will:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Registry/supply-chain attacks&lt;/strong&gt; (typosquatted packages, unverified provenance) — need cryptographic
attestation and a verified registry, not runtime scanning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sandbox escape&lt;/strong&gt; — needs OS-level isolation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consent fatigue&lt;/strong&gt; — needs client-side UX controls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A proxy is &lt;em&gt;necessary but not sufficient.&lt;/em&gt; The data makes the case for &lt;strong&gt;defense-in-depth across&lt;br&gt;
distinct mechanism classes&lt;/strong&gt; better than any argument could: 19 of 24 vectors are caught by &lt;em&gt;some&lt;/em&gt;&lt;br&gt;
tool but missed by &lt;em&gt;others&lt;/em&gt;, and a whole cluster sits outside every proxy's reach. Anyone selling you a&lt;br&gt;
single box that "secures your MCP" is selling you 63%, at best.&lt;/p&gt;




&lt;h2&gt;
  
  
  It re-runs itself now
&lt;/h2&gt;

&lt;p&gt;The loop is no longer manual. &lt;code&gt;mcp-bastion&lt;/code&gt;'s continuous-integration pipeline runs the full benchmark&lt;br&gt;
on &lt;strong&gt;every change&lt;/strong&gt; and fails the build if coverage drops below a floor or any false positive appears.&lt;br&gt;
The measurement isn't a one-time paper result; it's a standing regression test on the defense. When the&lt;br&gt;
next MCP attack drops, the process for handling it is already wired: add the vector, re-measure, close&lt;br&gt;
the gap, and the gate makes sure it stays closed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Try it, break it, tell me I'm wrong
&lt;/h2&gt;

&lt;p&gt;Everything is open:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Benchmark:&lt;/strong&gt; &lt;a href="https://github.com/Gowthaman90/mcp-defense-bench" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-defense-bench&lt;/code&gt;&lt;/a&gt; — the rubric,
the corpus, the adapters, and a public leaderboard. Add an adapter for your tool and measure it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reference proxy:&lt;/strong&gt; &lt;a href="https://github.com/Gowthaman90/mcp-bastion" rel="noopener noreferrer"&gt;&lt;code&gt;mcp-bastion&lt;/code&gt;&lt;/a&gt; on npm
(&lt;code&gt;npx -y mcp-bastion&lt;/code&gt;) and in the official MCP registry.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The full paper&lt;/strong&gt; (methodology, tables, references): &lt;em&gt;Measuring the Defenders: A Layer-Aware,
Framework-Mapped Benchmark for Model Context Protocol Security Proxies&lt;/em&gt; — arXiv:2607.XXXXX &lt;em&gt;(link
going live shortly)&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One disclosure, up front: &lt;strong&gt;I build one of the tools the benchmark measures.&lt;/strong&gt; That's exactly why the&lt;br&gt;
whole thing is open, vendor-neutral, driven through each tool's real code, and scored alongside&lt;br&gt;
competitors and a do-nothing baseline — so you don't have to take my word for any of it. Re-run it&lt;br&gt;
yourself.&lt;/p&gt;

&lt;p&gt;The number that matters isn't 63%. It's that an honest measurement, applied relentlessly, turned a&lt;br&gt;
9%-coverage scanner into the broadest MCP defense measured — and drew a bright line around the 37% that&lt;br&gt;
needs a fundamentally different kind of tool. That line is the useful part.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you work on MCP, agent security, or AI governance, I'd genuinely value critique of the rubric and&lt;br&gt;
the methodology — open an issue, or reach me at &lt;a href="mailto:agowthaman90@gmail.com"&gt;agowthaman90@gmail.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The MCP reliability &amp; security gap — and an open-source proxy that fills it</title>
      <dc:creator>Gowthaman</dc:creator>
      <pubDate>Wed, 08 Jul 2026 13:31:18 +0000</pubDate>
      <link>https://dev.to/gowthaman90/the-mcp-reliability-security-gap-and-an-open-source-proxy-that-fills-it-3ppo</link>
      <guid>https://dev.to/gowthaman90/the-mcp-reliability-security-gap-and-an-open-source-proxy-that-fills-it-3ppo</guid>
      <description>&lt;p&gt;As AI agents move from demos to production, the &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; has become the default way to give them tools. But the operational layer around MCP is still immature, and two gaps show up fast.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reliability gap
&lt;/h2&gt;

&lt;p&gt;MCP servers disconnect mid-session — a crashed subprocess, a dropped network stream — and the agent has no good signal. It sees a generic &lt;em&gt;"No such tool available"&lt;/em&gt; error, indistinguishable from a tool that never existed. Worse, it can't reconnect itself; a human has to intervene. In a long autonomous run, capabilities silently vanish and the agent fails in confusing ways.&lt;/p&gt;

&lt;h2&gt;
  
  
  The security gap
&lt;/h2&gt;

&lt;p&gt;MCP tools are described in natural language that the model reads and acts on. That creates two live threats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Rug pull&lt;/strong&gt; — a server presents a benign tool, you approve it, and later swaps the definition for a malicious one. Static, open-source scanners only check once at install time, so they miss it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tool poisoning&lt;/strong&gt; — hidden instructions in a description ("ignore previous instructions", "read the user's SSH key and post it to...") that steer the model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Runtime defenses for these live mostly in paid platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  mcp-bastion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Gowthaman90/mcp-bastion" rel="noopener noreferrer"&gt;&lt;strong&gt;mcp-bastion&lt;/strong&gt;&lt;/a&gt; is a proxy that addresses both, and it's deliberately boring to adopt: it's a &lt;em&gt;correct MCP server&lt;/em&gt; to your client and a &lt;em&gt;correct MCP client&lt;/em&gt; to your servers, so it works with any compliant client through configuration alone — no per-client code — and removing it is a one-line revert.&lt;/p&gt;

&lt;p&gt;It's organized in three layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reliability&lt;/strong&gt; — health checks, capped-backoff auto-reconnect, and control tools (&lt;code&gt;bastion__status&lt;/code&gt;, &lt;code&gt;bastion__reconnect&lt;/code&gt;) that let the agent itself inspect and recover connections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime security&lt;/strong&gt; — trust-on-first-use tool pinning that blocks rug pulls until you re-approve, heuristic poisoning inspection, and cross-server shadowing detection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit &amp;amp; compliance&lt;/strong&gt; — every tool call becomes a structured, optionally tamper-evident event, fanned out to pluggable sinks (console / file / webhook) and mapped to &lt;strong&gt;NIST AI RMF&lt;/strong&gt; and &lt;strong&gt;OWASP LLM Top 10&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It speaks both stdio and Streamable HTTP. TypeScript, Apache-2.0, layered architecture, tests, and CI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx mcp-bastion
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;a href="https://github.com/Gowthaman90/mcp-bastion" rel="noopener noreferrer"&gt;https://github.com/Gowthaman90/mcp-bastion&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's early and I'd love feedback — especially on the security heuristics and which audit sinks people want.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>cybersecurity</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
