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()andRegExp.exec(), which share a name withchild_process.execbut have nothing to do with it - strings and comments that contain "http://" or a secret-looking token
- placeholder keys like
sk_test_xxxin 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_processandnew 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>

