MCP (Model Context Protocol) is becoming the standard way AI agents connect to external tools. Claude, ChatGPT, Cursor, VS Code Copilot, and Gemini all support it. There are over 10,000 MCP servers in the ecosystem. But nobody was systematically checking if they're secure.
So I built a scanner and tested 35 real servers and client configurations from public GitHub repositories. The results weren't great.
The Numbers
| Metric | Count |
|---|---|
| Total scanned | 35 |
| With findings | 62% |
| Critical | 6 |
| High | 299 |
| Medium | 181 |
| Total findings | 486 |
Finding #1: Path Traversal is Everywhere
The single most common vulnerability, appearing 262 times. MCP servers that handle file operations routinely accept user-controlled path parameters without validation. An agent (or attacker manipulating the agent) can request ../../../../etc/passwd and the server reads it.
This is worse than typical web apps because the "user" isn't a human making deliberate requests. It's an AI agent that can be manipulated through prompt injection in any data it processes.
Finding #2: Your Cursor Config Might Be a Backdoor
6 of the configs I scanned had critical severity findings. Shell metacharacters in server arguments that could achieve RCE when the IDE loads the config.
This is the same vulnerability class behind:
- CVE-2025-6514 (437K npm downloads, CVSS 9.6)
- CVE-2026-30615 (Windsurf RCE)
- CVE-2025-54136 (Cursor)
One config I found used bash -c with a chained command string as the server entry. That's a live RCE vector in a public repo.
Finding #3: API Keys Committed in the Open
5 of the 15 client configs passed sensitive credentials as environment variables. Real OpenAI keys, AWS secrets, and Amadeus API keys in public repos.
MCP configs are especially dangerous because they often contain keys for multiple services at once.
Finding #4: Unpinned Packages
Nearly every config uses npx -y without version pinning:
{
"mcpServers": {
"server": {
"command": "npx",
"args": ["-y", "@some-package/mcp-server"]
}
}
}
No version pin means a supply chain attack propagates to everyone automatically. The -y flag suppresses confirmation prompts.
Safe version: "@some-package/mcp-server@0.6.2"
Finding #5: Shell Execution Without Sanitization
5 servers contained exec.Command("bash", "-c", ...) or subprocess.run(shell=True) with user-controllable parameters. If an attacker can influence the tool input through prompt injection, they get arbitrary command execution.
The Threat Model is Different
In MCP, you're not securing against a human attacker directly. You're securing against an AI agent that might be manipulated by an attacker through any data it processes. Every tool input should be treated as potentially adversarial.
Check Your Own Setup
I built MCPSense to catch all of this. Open source, MIT licensed, single binary.
# Install
curl -sSL https://raw.githubusercontent.com/fayzkk889/MCPSense/main/install.sh | sh
# Scan your config
mcpsense scan ~/.cursor/mcp.json
# Scan a server
mcpsense scan ./my-mcp-server
27 checks covering tool poisoning (ASCII smuggling, annotation lying, cross-tool manipulation), config injection, prompt injection, SSRF, path traversal, and spec compliance.
SARIF output for GitHub Code Scanning. GitHub Action for CI/CD. Four scan modes.
Full writeup with terminal output examples: mcpsense.site/blog
If this was useful, star the repo so others can find it.
Top comments (0)