Your Enterprise Deployed MCP Servers — Has Anyone Audited Them?
The Model Context Protocol (MCP) is becoming the standard way AI agents interact with external tools and data sources. More enterprises are deploying MCP servers in production every week.
But here is what most teams have not done: security audit their MCP server implementations before going live.
After systematically scanning 24+ MCP server implementations and analyzing hundreds of vulnerability patterns, here is what I have learned about the real attack surface and how to check yours.
Why MCP Servers Are a Unique Attack Surface
Traditional web APIs have well-understood security patterns. MCP servers are different:
1. They execute arbitrary operations, not just return data
An MCP server does not just answer questions — it runs code, queries databases, sends emails, manages infrastructure. A compromised MCP server is not a data leak; it is an action execution engine.
2. The protocol assumes trust between client and server
MCP architecture assumes the agent (client) and the tool (server) operate in a trusted relationship. There is no built-in mechanism for the server to validate whether a tool call is legitimate, or for a third party to verify that calls are compliant.
3. Most implementations skip input validation
In our analysis, the most common vulnerability pattern was: user-controlled parameters passed directly to shell execution functions (exec(), os.system(), subprocess.run(shell=True)) without sanitization.
This is not theoretical. It is the number 1 pattern we find in production MCP servers.
The 6 Things You Need to Check
Based on our audit methodology (formalized as CCS — Correctover Conformance Standard), here is what a real MCP security audit covers:
1. Command Injection Surface
What to look for: Any path where user-controlled input reaches a shell execution function.
# VULNERABLE — direct shell execution
os.system(f"curl {user_url}")
# SAFE — parameterized or validated
subprocess.run(["curl", validated_url], shell=False)
Why it matters: Command injection in an MCP server gives an attacker the ability to execute arbitrary system commands with the server privileges.
2. SSRF (Server-Side Request Forgery)
What to look for: MCP tools that accept URLs or hostnames as parameters without validation.
# VULNERABLE — no URL validation
def fetch_data(url: str):
return requests.get(url).text
# SAFE — allowlist validation
ALLOWED_DOMAINS = {"api.example.com", "data.internal.com"}
def fetch_data(url: str):
parsed = urlparse(url)
if parsed.hostname not in ALLOWED_DOMAINS:
raise ValueError(f"Domain not allowed: {parsed.hostname}")
return requests.get(url).text
Why it matters: An attacker can make your MCP server fetch internal metadata endpoints (169.254.169.254), scan internal networks, or access services behind your firewall.
3. Authentication and Authorization
What to look for: MCP servers that expose tools without requiring authentication, or that do not differentiate between tool access levels.
Why it matters: An unauthenticated MCP server is an open door to your infrastructure. Even with authentication, flat permissions (all users can access all tools) violate least privilege.
4. Credential Handling
What to look for: API keys, tokens, or secrets stored in environment variables that are accessible to MCP tool execution contexts.
Why it matters: If an MCP server has command injection (see number 1), the attacker inherits access to all environment variables — including credentials for databases, cloud providers, and third-party APIs.
5. Runtime Compliance Verification
What to look for: Do you have a mechanism to verify that every tool call your MCP server executes conforms to your security policy — before it runs?
Why it matters: Post-hoc logging tells you what happened. Runtime verification prevents bad things from happening. The difference is: logs equal forensic analysis; verification equals prevention.
6. Fail-Closed Guarantees
What to look for: What happens when your security layer crashes? Does the system default to allowing or blocking the tool call?
# FAIL-OPEN (vulnerable) — governance crash = tool executes
try:
if not verify(call):
return deny()
except Exception:
pass # Bug: exception swallowed, tool proceeds
return execute(call)
# FAIL-CLOSED (safe) — governance crash = tool blocked
try:
if not verify(call):
return deny()
except Exception:
return deny() # Safe: any failure blocks execution
return execute(call)
Why it matters: Every observer-pattern governance hook (the most common integration pattern) is structurally fail-open. When the governance layer throws an exception, the framework defaults to allowing execution. This is CWE-636, and it is the most dangerous architectural pattern in AI agent governance.
How to Audit Your Deployment
If you want to check your own MCP servers, here is a practical approach:
Step 1: Inventory
List every MCP server in your environment. Include the tool names each server exposes and the parameters they accept.
Step 2: Static Analysis
For each server, grep for dangerous patterns:
grep -rn "exec\|eval\|os.system\|subprocess.*shell=True\|__import__" your_mcp_server/
Step 3: Input Validation Review
For every tool that accepts user-controlled parameters, verify that inputs are validated against an allowlist before reaching any execution function.
Step 4: Runtime Testing
Send malformed inputs to each tool endpoint. Check whether the server rejects them or passes them through.
Step 5: Fail-Mode Verification
Simulate governance layer failures (timeouts, exceptions, crashes). Verify that tool calls are blocked, not allowed, during failures.
Automating the Process
Manual audits work for small deployments. For larger environments, you need automated runtime verification that:
- Intercepts every tool call before execution
- Validates against structural, schema, latency, cost, identity, and integrity dimensions
- Blocks non-conforming calls with fail-closed guarantees
- Produces tamper-evident audit receipts
That is what CCS (Correctover Conformance Standard) was built for. It is a protocol-level verification framework with sub-10us overhead — fast enough for production use without degrading agent performance.
What to Do Now
If you are running MCP servers in production:
- This week: Run the static analysis (Step 2) on your MCP server codebase. You will likely find at least one dangerous pattern.
- This month: Complete the full 5-step audit. Document findings.
- This quarter: Implement runtime verification. Move from post-hoc logging to pre-execution blocking.
Or, if you would like a professional security assessment of your MCP server deployment, we offer enterprise auditing services at correctover.com.
This article is based on systematic security analysis of 24+ open-source MCP server implementations. No specific vendors are named; the patterns described are common across the ecosystem.
Top comments (0)