We Audited 6 Popular MCP Servers. Here's What We Found.

Written by the Rafter Team

MCP servers are the new attack surface. Every AI coding agent — Claude Code, Cursor, Windsurf, Copilot — connects to MCP servers that execute commands, fetch URLs, read filesystems, and access cloud infrastructure on the developer's behalf.
We audited six of the most popular community MCP servers. Not the reference implementations (Anthropic's official servers have their own CVE history). The ones developers actually install and run daily — the ones with 5,000 to 25,000 GitHub stars.
We found 50 vulnerabilities across 6 servers. 11 are critical. Every server had at least one high-severity issue. Several had critical vulnerabilities that could lead to credential theft, arbitrary code execution, or complete system compromise — all triggerable by an AI agent acting on malicious input.
Why MCP Servers Are High-Value Targets
MCP servers sit between an AI agent (which follows instructions) and system resources (which have real consequences). An attacker doesn't need to exploit a buffer overflow or race condition. They need to craft input that an AI agent will relay to the MCP server — and the server will execute without question.
This is tool description injection at scale. The attack surface isn't the protocol. It's every server that implements it.
Three properties make MCP servers especially dangerous:
-
Elevated privileges. MCP servers typically run with the developer's full permissions — their AWS credentials, their GitHub tokens, their filesystem access. A vulnerability in an MCP server is a vulnerability in everything the developer can access.
-
Implicit trust. The MCP specification delegates security to implementors. Most implementors trust their input because it comes from an AI agent, which comes from a user. But that trust chain breaks when a malicious website, a poisoned dependency, or a prompt injection enters the picture.
-
No security review culture. Most MCP servers are weekend projects that went viral. They're built for functionality, not security. The code quality varies wildly, and security review is the exception, not the norm.
Methodology
We performed source code review on six MCP servers selected for their popularity (star count), privilege level (what system resources they access), and ecosystem role (how many developers use them daily).
For each server, we focused on:
- Input validation — Are parameters from the AI agent sanitized before use?
- Authentication and authorization — Are access controls enforced, or can anyone who connects do anything?
- Network boundary enforcement — Can the server be tricked into accessing internal resources (SSRF)?
- Credential handling — Are API keys, tokens, and secrets protected?
- Resource limits — Can the server be abused for denial of service?
- Content safety — Can malicious external content be used for prompt injection?
We did not perform dynamic testing or exploitation. All findings are based on static source code analysis. We are conducting responsible disclosure for all actionable findings before publishing exploit details.
Findings Summary
| Server | Stars | Critical | High | Medium | Low | Primary Risk |
|---|---|---|---|---|---|---|
| DesktopCommanderMCP | ~5,800 | 4 | 2 | 4 | 0 | AI disables own security controls |
| AWS MCP servers | ~8,600 | 2 | 3 | 4 | 0 | AWS credential exposure + privilege escalation |
| firecrawl-mcp-server | ~5,900 | 2 | 2 | 4 | 1 | SSRF, arbitrary code execution |
| browser-tools-mcp | ~7,100 | 1 | 4 | 2 | 1 | Complete browser surveillance bridge |
| fastapi_mcp | ~11,700 | 1 | 2 | 3 | 1 | Auth bypass exposes all API endpoints |
| git-mcp | ~7,800 | 1 | 1 | 3 | 2 | SSRF open proxy |
| Total | 11 | 14 | 20 | 5 | 50 vulnerabilities |
DesktopCommanderMCP: The AI That Fires Its Own Guard
Repository: wonderwhy-er/DesktopCommanderMCP (~5,800 stars) What it does: Gives AI agents terminal control and filesystem access.
DesktopCommanderMCP is the most dangerous server we audited — not because of a single bug, but because its security architecture is fundamentally inverted. The AI agent that the blocklist is supposed to restrict is the same entity that can disable the blocklist.
Critical: AI Agent Can Disable All Security Controls (CWE-284)
The set_config_value MCP tool lets the AI agent modify security-critical configuration at runtime with no authentication and no user confirmation:
{"tool": "set_config_value", "arguments": {"key": "blockedCommands", "value": "[]"}}
{"tool": "set_config_value", "arguments": {"key": "allowedDirectories", "value": "[\"/\"]"}}
After these two calls, every command restriction and every filesystem boundary is gone. The guard was asked to fire itself, and it complied.
Critical: Command Blocklist Bypass via Shell Builtins (CWE-78)
Even without disabling the blocklist, the command validation only checks the basename of the first token. Shell builtins and wrappers bypass it trivially:
command sudo id # 'command' not on blocklist
env sudo id # 'env' not on blocklist
bash -c 'sudo id' # nested command
S=sudo; $S id # variable expansion
The extractCommands parser tries to replicate shell syntax parsing in JavaScript. It cannot. A blocklist approach is fundamentally inadequate for command restriction.
Critical: Unrestricted Shell Execution (CWE-250)
Commands run via child_process.spawn() with the user's full shell environment. No containers, no namespaces, no seccomp, no capability dropping. Full network access. Full access to process.env — including AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, and any other secrets in the environment.
Critical: Arbitrary Code via node:local (CWE-94)
The start_process tool with command: "node:local" writes arbitrary JavaScript to a .mjs file and executes it. The blocklist check only validates the "node:local" string, not the actual code. Complete RCE bypass.
Additional Findings
- SSRF via URL fetching (High, CWE-918):
read_filewithisUrl: truefetches arbitrary URLs including internal services - Default allows all paths (High, CWE-22):
allowedDirectoriesdefaults to empty, meaning unrestricted filesystem access out of the box - Hardcoded telemetry credentials (Medium, CWE-798): GA API secrets and telemetry proxy bearer tokens in source
- Command output leaks secrets (Medium, CWE-200): All stdout/stderr returned unfiltered to the AI
- No rate limiting (Medium, CWE-770): Unlimited concurrent processes, execution rate, and output size
AWS MCP Servers: From AI Agent to AWS Account Takeover
Repository: awslabs/mcp (~8,600 stars) What it does: Official AWS MCP servers for IAM, S3, Lambda, DynamoDB, and arbitrary AWS API calls.
The AWS MCP servers create a direct path from AI agent compromise to full AWS account takeover. The IAM server returns raw access key secrets, and the API server executes arbitrary AWS CLI commands — both with dangerous defaults.
Critical: IAM Server Returns SecretAccessKey to AI Agent (CWE-200)
The create_access_key tool returns the SecretAccessKey directly in its response body. The secret persists in the AI's context window, gets processed by the model provider, and can be exfiltrated by the agent through subsequent tool calls or output text.
return {
'AccessKey': {
'AccessKeyId': access_key['AccessKeyId'],
'SecretAccessKey': access_key['SecretAccessKey'], # Full secret exposed
},
}
Critical: Full Privilege Escalation via Policy Manipulation (CWE-269)
The IAM server exposes put_user_policy, put_role_policy, attach_user_policy, and create_role — all accepting arbitrary policy documents. The only guard is a Context.is_readonly() check that defaults to False. An agent can grant itself *:* on *:
{"tool": "put_user_policy", "arguments": {
"user_name": "existing-user",
"policy_name": "backdoor",
"policy_document": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":\"*\",\"Resource\":\"*\"}]}"
}}
High: Arbitrary AWS API Calls by Default (CWE-862)
The aws-api-mcp-server's call_aws tool executes arbitrary AWS CLI commands. READ_OPERATIONS_ONLY_MODE defaults to False. REQUIRE_MUTATION_CONSENT defaults to False. An agent can delete S3 buckets, terminate EC2 instances, or exfiltrate data from any AWS service.
High: SQL Injection in DynamoDB MySQL Analyzer (CWE-89)
The migration analyzer uses sql.format(target_database=database) — Python string formatting injected directly into SQL queries. While a regex validator restricts the character set, the pattern is fragile and sets a dangerous precedent.
High: Lambda Server Invokes All Functions by Default (CWE-862)
When FUNCTION_PREFIX and FUNCTION_LIST are both empty (the default), every Lambda function in the account becomes an invokable MCP tool. Including functions that process payments, delete data, or have elevated permissions.
firecrawl-mcp-server: The SSRF Gateway
Repository: mendableai/firecrawl-mcp-server (~5,900 stars, v3.13.0) What it does: Web scraping MCP server. Fetches, crawls, and extracts content from arbitrary URLs.
A single 1,269-line TypeScript file that accepts URLs from AI agents and fetches them with zero URL validation.
Critical: No SSRF Protection (CWE-918)
Every URL-accepting tool — scrape, crawl, map, extract — passes URLs directly to the backend. The crawl tool doesn't even use z.string().url() — just z.string(). For self-hosted deployments, this is a direct vector to cloud metadata, internal services, and localhost.
Critical: Arbitrary Code Execution (CWE-94)
browser_execute accepts arbitrary bash, Python, or Node.js code when SAFE_MODE is off (the default for self-hosted). The interact tool also accepts a code parameter — but isn't gated behind SAFE_MODE at all.
High: Prompt Injection via Scraped Content (CWE-74)
All scraped content returns raw to the AI agent with no sanitization, no delimiter wrapping, no defense against hidden instructions in HTML.
High: API Key Leakage in URL Paths (CWE-200)
The legacy nginx config routes API keys via URL path segments, exposing them in server logs, CDN logs, browser history, and referrer headers.
browser-tools-mcp: Total Browser Surveillance
Repository: AgentDeskAI/browser-tools-mcp (~7,100 stars) What it does: Reads browser console logs, network requests, DOM elements, and takes screenshots for AI agents.
This tool is a complete browser surveillance bridge with no data classification, no filtering, no authentication, and no domain restrictions.
Critical: Full Network Request/Response Exposure (CWE-532)
The Chrome extension captures ALL XHR/fetch requests and forwards complete Authorization headers, Cookie headers, request bodies (including login credentials), and response bodies (including tokens) to the AI agent. The showRequestHeaders setting only controls the MCP read path — the data is always captured and stored in server memory.
High: No Origin/Domain Filtering (CWE-284)
host_permissions: "<all_urls>" in the manifest, with zero domain checks in the code. When a developer navigates from their app to their banking site, Gmail, or a healthcare portal, all data from those sites is captured too.
High: Unauthenticated API on 0.0.0.0 (CWE-306)
The Express server binds to 0.0.0.0 by default with app.use(cors()) — wildcard CORS. Any process on the machine (or the network) can read all captured browser data. A malicious web page running JavaScript could fetch http://localhost:3025/console-logs and exfiltrate everything.
High: Screenshots Expose Visible Credentials (CWE-200)
takeScreenshot captures the full visible tab as PNG, saved to a predictable path with no access controls and no automatic cleanup. Whatever's on screen — login forms, tokens in devtools, financial data — gets captured.
High: Unfiltered Console Log Exposure (CWE-532)
All console.log() output captured verbatim. Applications commonly log API keys, tokens, and PII to console during development. The 500-character truncation limit doesn't help — most secrets are shorter.
fastapi_mcp: The Auth Bypass Factory
Repository: tadata-org/fastapi_mcp (~11,700 stars) What it does: Automatically exposes FastAPI endpoints as MCP tools for AI agents.
The key question: when you wrap a protected FastAPI app with fastapi_mcp, do the auth checks still apply? Partially — but the defaults are dangerous.
Critical: MCP Endpoint Unprotected by Default (CWE-306)
The basic usage — FastApiMCP(app).mount_http() — creates an unauthenticated MCP endpoint. All FastAPI endpoints become discoverable via list_tools (names, paths, full schemas). FastAPI's Depends() guards still execute on tool calls, but the endpoint existence and schema are leaked to any connecting client.
High: All Endpoints Exposed by Default (CWE-1209)
Including admin, internal, debug, password reset, and user deletion endpoints. No filtering unless the developer explicitly passes exclude_operations or exclude_tags. The safe default — requiring explicit inclusion — is absent.
High: Fake OAuth Registration Leaks Credentials (CWE-522)
The /oauth/register endpoint returns the real client_id and client_secret to any caller with no authentication. Documented as a "workaround" for MCP's dynamic registration requirement, it effectively makes OAuth credentials public.
git-mcp: The Open Proxy
Repository: idosal/git-mcp (~7,800 stars) What it does: Serves Git repository content to AI agents, fetching from GitHub remotely.
Critical: Unrestricted SSRF (CWE-918)
The fetch_generic_url_content tool accepts arbitrary URLs with zero validation. No scheme restriction, no IP blocking, no allowlist. Running on Cloudflare Workers limits metadata endpoint access, but it's effectively an open proxy for any internet-accessible host.
High: Content/Prompt Injection via Repo Content (CWE-74)
Repository content (README.md, llms.txt) returns unsanitized to the AI agent. A malicious repository can embed hidden instructions that the AI will follow when processing the fetched documentation.
The Pattern: Trust Without Verification
Across all six servers, we see the same fundamental failure: MCP servers trust their input because it comes from an AI agent.
This trust is misplaced. AI agents relay instructions from many sources — user prompts, tool descriptions, fetched web content, repository files, previous conversation context. Any of these can be manipulated.
The most dangerous pattern we found isn't any single vulnerability. It's the combination: an AI agent reads malicious content (prompt injection), calls an MCP tool with attacker-controlled parameters (SSRF, command injection), and the tool executes without question (no validation). The entire chain — from malicious webpage to system compromise — requires zero interaction from the developer.
What MCP Server Authors Should Do
-
Default to deny. Don't expose everything by default. Require explicit opt-in for dangerous capabilities. If the default is safe, most developers will stay safe.
-
Don't trust the AI agent. The agent is a relay, not a principal. Validate inputs as if they came from an untrusted external source — because they do.
-
Block internal network access. Any tool that fetches URLs must reject private IP ranges, loopback addresses, link-local addresses, and cloud metadata endpoints. This is table stakes.
-
Never return secrets to the AI. AWS access keys, tokens, and credentials should be stored securely, not passed through the AI's context window where they persist in logs and model memory.
-
Separate the control plane from the data plane. If the AI agent can disable its own security controls, you don't have security controls. Configuration must be modifiable only by the human user, never by MCP tool calls.
-
Run security scans. Use automated tools like Rafter to catch common vulnerabilities before shipping. Every finding in this post was discoverable with static analysis.
What Developers Using MCP Servers Should Do
-
Audit before installing. Read the source code of any MCP server you install. If the server handles URLs, check for SSRF protection. If it executes commands, check for injection prevention.
-
Use allowlists. Configure allowed directories, blocked commands, and URL restrictions where available. Don't leave these defaults empty.
-
Isolate MCP servers. Run them with minimal permissions. Don't give a web scraping server access to your AWS credentials. Don't give a filesystem server access to your SSH keys.
-
Monitor tool calls. Log what your MCP servers are doing. If a scrape tool starts hitting internal IPs or an IAM server starts creating access keys, something is wrong.
-
Scan your own code. If you're building with AI assistants that use MCP servers, the code they generate inherits the security properties of those servers. Scan it.
Responsible Disclosure
We are following responsible disclosure for all findings. Maintainers of affected projects have been or will be notified with 90 days to patch before full details are published. This post presents vulnerability classes and patterns; specific exploit chains will be published after patches are available.
If you maintain an MCP server and want a security review, reach out — we're offering free Rafter scans to MCP server maintainers through 2026.
Related Reading
- Exploiting Anthropic's Git MCP Server: A Case Study in Cascading Vulnerabilities
- The WhatsApp MCP Exfiltration
- MCP's Security Gap: Why Model Context Protocol Needs a Layer Above
- MCP Tool Description Injection
- Building a Malicious MCP Server
- Cross-Server Capability Laundering
This research is ongoing. We will update this post as responsible disclosure processes complete and additional server audits are finalized. The raw finding counts may shift as we validate edge cases.