I built a small static scanner for MCP servers after I found a real SSRF bug in one of my own webhook routes. Then I ran it on 36 public MCP servers to see how bad the ecosystem looked.

First result: 482 findings. Second result, after I read them: almost none were real.

What the noise was

  • e2e and test helpers that call exec() on purpose
  • db.exec() and RegExp.exec(), which share a name with child_process.exec but have nothing to do with it
  • strings and comments that contain "http://" or a secret-looking token
  • placeholder keys like sk_test_xxx in READMEs and examples

What I changed

  • Skip test, e2e and scripts directories (opt back in with --include-tests)
  • Flag SSRF only when the caller controls the host of the URL, not just a path or query
  • Ignore matches inside strings and comments
  • Flag exec-injection only for child_process and new Function
  • Filter placeholder secrets

Same 36 repos after the fix: 28 findings. I read all of them. They are shell strings that interpolate paths or dates. None are exploitable as far as I can tell, and I did not find anything worth disclosing.

What I take from it

A regex scanner will happily produce a scary number. If I had published "482 issues in 36 MCP servers" it would have been wrong. Counting findings is not the same as counting vulnerabilities, so any "X% of MCP servers are vulnerable" figure is only as good as the triage behind it.

The tool is free and open source: npx @sms-florin/mcp-ssrf-scan <path>

Repo: https://gitlab.com/florin-builds/mcp-ssrf-scan