DEV Community

manja316
manja316

Posted on

I Audited 7 Official MCP Servers — Here Is What I Found

Every MCP server in the official repo has the same security gap. Not a vulnerability exactly — more like a missing seatbelt that everyone forgot to install.

I ran mcp-security-audit against 7 servers from modelcontextprotocol/servers. The tool connects via stdio, enumerates every tool and parameter, and scores them across documentation, schema rigor, injection safety, scope control, and metadata hygiene.

Results

Server Tools Score Grade Notable Finding
Fetch 1 100/100 A Clean. Zero findings.
SQLite 6 95/100 A Unconstrained SQL query strings
Time 2 95/100 A Unconstrained timezone strings
GitHub 26 94/100 A create_or_update_file flagged as unexpected FILE capability
Memory 9 92/100 A Unconstrained search query
Git 12 90/100 A 18 unconstrained string parameters
Filesystem 14 85/100 B read_media_file triggers base64 injection detector

5 Grade A, 2 Grade B. No critical vulnerabilities. The official servers are generally well-built.

But there's a pattern.

The Universal Weakness: Unconstrained Strings

Every server except Fetch failed to constrain string parameters. No maxLength. No pattern. No enum. Just raw, open strings that accept anything the LLM decides to send.

The Git server has 18 of them. Paths, commit messages, branch names — all freeform. The SQLite server accepts SQL queries of unlimited length. The Time server accepts timezone strings with no validation against IANA identifiers.

Why this matters:

1. DoS vector. An unconstrained string parameter accepts a 10MB commit message or a 50,000-character file path. The server has to process it. MCP servers typically run locally, so this isn't a remote attack — but if your MCP server is exposed via a network transport (which the spec supports), this becomes a real issue.

2. No input validation at the boundary. The MCP spec puts the LLM between the user and the tools. But LLMs are susceptible to prompt injection. If an attacker injects instructions that cause the LLM to send malformed input to a tool, the tool has no schema-level defense. It's trusting the LLM to be well-behaved.

3. It's trivially fixable. Adding maxLength: 1000 to a path parameter takes one line. Adding pattern: "^[a-zA-Z/_-]+$" to a timezone parameter takes one line. These constraints are enforced by the MCP protocol layer before the tool code ever runs.

The Fix (For MCP Server Authors)

Instead of:

{
  "name": "query",
  "type": "string",
  "description": "SQL query to execute"
}
Enter fullscreen mode Exit fullscreen mode

Do:

{
  "name": "query",
  "type": "string",
  "description": "SQL query to execute",
  "maxLength": 10000
}
Enter fullscreen mode Exit fullscreen mode

For parameters with known formats:

{
  "name": "timezone",
  "type": "string",
  "description": "IANA timezone identifier",
  "pattern": "^[A-Za-z_/]+$",
  "maxLength": 50
}
Enter fullscreen mode Exit fullscreen mode

For parameters with known values:

{
  "name": "operation",
  "type": "string",
  "enum": ["staged", "unstaged", "all"]
}
Enter fullscreen mode Exit fullscreen mode

Specific Findings Worth Noting

Filesystem Server: base64 injection pattern (False Positive)

The read_media_file tool description mentions returning base64-encoded content. Our injection detector flagged this because base64 strings in tool descriptions can be used to smuggle instructions past content filters.

In this case it's legitimate — the tool genuinely returns base64 media. But it highlights an interesting problem: how do you distinguish between a tool that legitimately handles encoded content and one that's been backdoored to inject encoded instructions?

The answer: context-aware scoring. Our auditor knows the Filesystem server's purpose is FILE operations, so base64 in a media reader is expected. A Calendar server returning base64 would be suspicious.

GitHub Server: Unexpected FILE Capability

The GitHub server exposes create_or_update_file, which writes files to repos. Our auditor classified the server's purpose as NETWORK/API (it talks to the GitHub API), so a FILE-writing tool is flagged as scope creep.

This is actually correct behavior — creating files in repos IS what the GitHub API does. But the finding illustrates an important principle: every capability beyond a server's core purpose should be explicitly justified. If your MCP server's primary job is fetching weather data and it also has a write_file tool, that's a red flag.

Fetch Server: The Gold Standard

One tool. One parameter (URL). Properly constrained. Well-documented. Perfect score.

If you're building an MCP server, model it after Fetch. Start with the minimum surface area and add tools only when necessary.

How to Audit Your Own MCP Servers

pip install mcp-security-audit
mcp-audit scan --server "npx @modelcontextprotocol/server-filesystem /tmp"
Enter fullscreen mode Exit fullscreen mode

The tool outputs a scored report with specific findings and recommendations. It works with any MCP server that communicates over stdio.

Full JSON audit reports for all 7 servers: LuciferForge/audit-reports

What This Means for the MCP Ecosystem

MCP is 6 months old and growing fast. The official servers are setting the standard that every community server will follow. Right now, that standard includes good documentation and clean injection safety — but skips input validation.

This is the same pattern we saw with early REST APIs. Everyone shipped endpoints without input validation, then spent years adding it after the exploits started. MCP has the advantage of learning from that history.

The fix is small. One line per parameter. The official servers should lead by example.


Audits performed with mcp-security-audit v0.2.0. The tool is open-source and free.

Top comments (0)