Your MCP config is the actual security boundary. Nobody audits it.
I read a lot about MCP security tooling and noticed something odd: every
scanner I found lints the design of servers, or reports that a config
"looks risky." None of them answer the two questions I actually have when I
look at my own ~/.claude.json:
- Am I running a server version with a known CVE?
- Can you just fix it?
So I built mcp-audit — a local runtime security scanner for MCP servers
with a bundled CVE table and one-click fixes. stdlib only, no dependencies.
pip install mcp-runtime-audit
mcp-audit scan
The case for scanning your own configs
The threat model here is weird compared to normal software. An MCP server
runs with your user's privileges and is driven by an AI agent on your
behalf. The configuration that launches it is hand-edited JSON nobody
reviews.
And the track record is not great:
-
The official tooling shipped RCE. CVE-2025-49596 hit Anthropic's own
MCP Inspector (CVSS 9.4): its local proxy accepted an unauthenticated
/sserequest withtransportType=stdio&command=<cmd>and spawned it as a subprocess. Visiting a malicious page was enough to run code on the developer's machine. Fixed in Inspector 0.14.1. - Enterprise MCP apps too. CVE-2026-76404 (Splunk MCP Server < 1.2.1, CVSS 9.1): unsafe deserialization in credential management, admin role to arbitrary OS commands.
-
Langflow's stdio transport wrapped your command in
bash -c. CVE-2026-105697 (CVSS 9.9): whatever command a user typed into an MCP server config got executed with no allowlist. - Anthropic's stated position is that stdio risk is "expected" — the security burden sits with whoever deploys the server. Which means the deployer is you, and your config file is the boundary.
What it checks
mcp-audit scan reads your MCP client configs (Claude Code's
~/.claude.json, Codex config, and the other usual locations — or a path
you pass with --config) and runs four checks:
1. Dangerous stdio commands. If your stdio entry wraps execution in
bash -c / sh -c / cmd /c, that's command injection by design. This is
exactly the Langflow pattern above, and it shows up in real configs more
often than you'd think.
2. Unauthenticated endpoints. SSE/HTTP servers with no
Authorization/X-API-Key header. With --probe it sends one
unauthenticated GET to confirm the endpoint actually answers — the
CVE-2025-49596 shape.
3. Bind addresses. 0.0.0.0 in a URL, a --host flag, or an env var
means the server is reachable beyond localhost.
4. Known-CVE version checks. This is the part I couldn't find anywhere
else: it extracts package@version from your npx/uvx invocations and
matches them against a bundled CVE table. Running
@modelcontextprotocol/inspector@0.13.0 gets you a critical finding naming
CVE-2025-49596 and the version that fixes it.
Every finding carries a rule id, CVE id, severity, the evidence, and the
fix — in text and JSON output, with CI-ready exit codes (0 clean, 1
findings, 2 errors).
The one-click fix
Scanning is only half the job. mcp-audit fix prints a dry-run plan; add
--apply and it:
- rewrites
0.0.0.0→127.0.0.1in URLs, flags, and env values, - adds an
Authorization: Bearer ${MCP_TOKEN}placeholder to unauthenticated endpoints (you fill in a real token), - backs up the config to
<file>.bak-<timestamp>before writing anything.
If it detects agent-guard installed, mcp-audit scan --link-agent-guard
writes critical servers into agent-guard's blocklist so your agent runtime
refuses to launch them.
How it differs from the other scanners
- mcpscan and graygnatconsole's mcp-audit-tool scan configs but neither does known-CVE version matching and neither writes fixes back.
- mcp-lint is a design-quality linter for MCP servers — a different layer. This tool audits the runtime security of the servers you run.
What's deliberately missing
- Version detection only works for
package@version-style invocations (npx/uvx/node). Servers installed some other way won't match the CVE table. - The CVE table is a bundled snapshot, not a live feed — new CVEs need a new release.
-
--probetouches the network (one GET, no payloads, no mutations), so don't point it at hosts you don't own. - It can't see what a server does after it starts. This is a config and runtime-surface scanner, not a behavior monitor.
Repo: https://github.com/hahahahahahahahah6/mcp-audit
PyPI: https://pypi.org/project/mcp-runtime-audit/ (pip install mcp-runtime-audit)
If you run MCP servers locally, run the scan — I'd genuinely like to know
what it finds in the wild.
Top comments (0)