The Model Context Protocol (MCP) is moving fast. Dozens of MCP servers are being published to npm and PyPI every week — integrations for file systems, databases, browsers, shells, and developer tools. AI agents are being granted access to these servers, often without any security review.
We asked a simple question: what happens when you actually probe these servers with real attack payloads?
The answer: a lot. We found 15 confirmed vulnerabilities across 100 servers in our initial scan campaign, including critical SSRF, command injection, and path traversal flaws. We also built the tool that found them — MCPFuzz, now open source.
The Problem: MCP Has No Security Baseline
MCP was designed for capability, not security. The protocol lets AI agents call tools, read resources, and execute actions on connected systems. There is no mandatory input validation, no authentication requirement, no sandboxing — these are left to each server author.
The result is a long tail of npm and PyPI packages, written quickly, often by a single developer, with no security review, being trusted by AI systems with access to files, shells, APIs, and databases.
Before MCPFuzz, the only way to assess an MCP server’s security was to read the source code — if it was public. There was no dynamic scanner, no fuzzer, no automated way to probe a live MCP server with exploit payloads.
What We Built: MCPFuzz
MCPFuzz is a dynamic security scanner for MCP servers. It connects to a live server using the MCP protocol, discovers its tools, and probes each tool with targeted payloads across 12 vulnerability classes.
pip install mcpfuzz
# Scan a stdio server
mcpfuzz scan --transport stdio --server-command "npx -y @some/mcp-server"
# Scan an HTTP server
mcpfuzz scan --transport sse --server-url http://localhost:8000
The scanner supports all four MCP transports: stdio, sse, http, and streamable-http. It auto-discovers tools using the MCP tools/list call and fuses findings into a colour-coded HTML report with CVSS scores.
What It Checks
| Module | What It Probes |
|---|---|
ssrf | SSRF via URL injection into tool parameters — cloud metadata, internal services, OOB callback |
path_traversal | Directory traversal via ../ sequences in file-path parameters |
command_injection | Shell injection in parameters passed to OS commands |
sql_injection | SQLi payloads in query parameters |
auth_bypass | Admin/privileged tool access without credentials |
tool_poisoning | LLM-judge detection of misleading tool descriptions (requires --llm-key) |
rug_pull | Tool schema changes between baseline and re-scan |
idor_bola | Object-level access control testing |
dns_rebinding | DNS rebinding via time-of-check time-of-use delays |
hardcoded_secrets | API keys, tokens, passwords exposed in tool responses |
protocol_fuzzing | Malformed MCP messages, oversized payloads, type confusion |
cve_checks | 13 CVE-specific checks targeting known MCP vulnerabilities |
It also runs a pre-scan SAST pass on npm packages: downloads the tarball, scans for 17 dangerous patterns (child_process.exec, eval, unsafe deserialization, etc.) before sending a single request.
The 100-Server Campaign: What We Found
We selected 100 publicly available MCP servers from the official modelcontextprotocol/servers list, awesome-mcp-servers, npm, and PyPI. Selection criteria: the server must implement @modelcontextprotocol/sdk (npm) or mcp>= (Python), and must be installable and launchable without a paid account.
15 confirmed vulnerabilities across categories:
SSRF (7 findings)
Server-Side Request Forgery was the most common class. MCP servers that accept URLs as tool parameters and fetch them server-side are vulnerable by design when there is no allowlist validation.
| Server | Severity | CVSS | Status |
|---|---|---|---|
html-to-markdown-mcp | CRITICAL | 9.1 | Fixed — PR #3 merged |
git-mcp | CRITICAL | 9.1 | Reported — onmyway133/git-mcp#1 |
fetch-mcp | CRITICAL | 9.1 | Reported — GitHub issue #3 |
@mcp-get-community/server-curl | CRITICAL | 9.1 | Disclosed to maintainer |
@247arjun/mcp-curl | CRITICAL | 9.1 | Reported — GitHub issue #2 |
@arabold/docs-mcp-server | HIGH | 7.5 | Reported — GitHub issue #374 |
lighthouse-mcp | HIGH | 7.5 | Fixed — PR #23 merged |
SSRF severity depends on transport. For network-exposed servers (sse, http), confirmed SSRF is CRITICAL: cloud metadata endpoints (169.254.169.254, fd00:ec2::254) are reachable, internal services are exposed. For stdio servers (local process only), we rate HIGH — exploitation requires a compromised AI agent on the same host.
We received positive responses from both lighthouse-mcp and html-to-markdown-mcp maintainers, who shipped fixes within 48 hours.
Path Traversal (3 findings)
File-handling MCP servers that construct paths from tool arguments without sanitisation are vulnerable to ../../../etc/passwd style traversal.
| Server | Severity | CVSS | Status |
|---|---|---|---|
@wonderwhy-er/desktop-commander | HIGH | 7.8 | Reported — GitHub issue #403 |
mcp-filesystem-server | HIGH | 7.8 | Disclosed to maintainer |
csv-mcp | HIGH | 7.8 | No public repo — package orphaned |
desktop-commander is one of the more widely-used servers in this category, granting AI agents access to terminal commands and the local file system.
Command Injection (1 finding)
| Server | Severity | CVSS | Status |
|---|---|---|---|
wiki-mcp | CRITICAL | 9.8 | Reported — msilverblatt/wiki-mcp#1 |
wiki-mcp passed tool arguments directly to a shell command without escaping. Payload ; id executed and returned the server’s user ID in the response. This is the highest-severity finding in the campaign — a fully exploitable RCE via an AI agent call.
Missing Authentication (2 findings)
| Server | Severity | CVSS | Status |
|---|---|---|---|
@mako10k/mcp-shell-server | HIGH | 8.1 | Reported — GitHub issue #22 |
mcp-server-ssh | MEDIUM | 6.5 | Reported — bacarrdy/mcp-ssh-server#1 |
mcp-shell-server exposes shell execution tools with no authentication gate. Any MCP client — or any AI agent with access to the server — can execute arbitrary shell commands.
Information Disclosure (2 findings)
| Server | Severity | CVSS | Status |
|---|---|---|---|
mcp-redis-diagnostics | MEDIUM | 5.3 | Reported — Dmitriusan/mcp-redis-diagnostics#10 |
mcp-system-info | LOW | 3.7 | Reported — cooderamily/system-tool-mcp#1 |
DoS (1 finding)
| Server | Severity | CVSS | Status |
|---|---|---|---|
@browsermcp/mcp | HIGH | 7.5 | Reported — GitHub issue #163 |
Recursive callback loop triggered by a crafted tool call. Server enters infinite recursion and becomes unresponsive.
What Responsible Disclosure Looks Like for MCP
Most MCP server maintainers are individual developers — not security teams with a coordinated disclosure process. We adapted:
- Check for a public repo first. If no public issue tracker exists, email the maintainer directly using the npm/PyPI package contact.
- Include a minimal PoC. Maintainers without a security background need to see the payload and the response, not a CVSSv3 vector.
- Give 90 days. Most maintainers respond within 1–2 weeks. Two of our reports resulted in patches within 48 hours.
- Don’t withhold severity. Being vague about impact doesn’t help maintainers prioritise.
Two findings resulted in merged fixes before this post was published. We consider those wins.
False Positives: What We Had to Fix
Dynamic scanning against a protocol that has no standard error format is hard. Some things that looked like vulnerabilities were not:
@playwright/mcp — Our SSRF module flagged browser_navigate for fetching arbitrary URLs. The maintainers were right: this is the product. A browser MCP server that navigates to URLs is working as designed. We updated the scanner to detect tool names containing navigate, browse, visit, and open_url — and treat those as by-design fetchers, not SSRF.
mongodb-mcp-server (official MongoDB) — Our info-disclosure module flagged list-knowledge-sources as leaking version metadata. It turned out the field values are documentation version labels, publicly intended. Scanner fix: a non-error response with no $ prefix is not an info leak.
Fixing false positives is part of the work. A scanner that cries wolf on every browser tool trains engineers to ignore alerts.
The Scanner Is Open Source
MCPFuzz is available now:
- GitHub: github.com/Cyberneticsplus-Services/mcpfuzz
- PyPI:
pip install mcpfuzz - LLM-judge (tool poisoning detection):
pip install 'mcpfuzz[llm]'
If you maintain an MCP server and want a free security scan, open an issue on GitHub or contact us. If you find a false positive or a missed vulnerability class, we want to know.
What Comes Next
We are expanding the target list beyond 100 servers. The MCP ecosystem is growing fast — new servers are published daily. We are also adding:
- GitHub Actions integration — scan your MCP server on every push
- CVE database — tracking MCPFuzz-discovered vulnerabilities with assigned CVEs where applicable
- Streamable-HTTP transport support — the newest MCP transport, not yet covered by any other scanner
The security posture of the MCP ecosystem is improvable. Most of the vulnerabilities we found are simple — missing input validation, no allowlisting, unsanitised shell arguments. They are fixable in an afternoon. The harder problem is that most MCP server authors don’t know to look.
That’s the gap MCPFuzz is built to close.