The Model Context Protocol has become the standard plumbing between AI agents and the tools, files, and internal systems they touch. That is convenient for developers and attractive to attackers: an MCP server sits on the boundary between model-generated text and real credentials, shell commands, and internal network endpoints. A single misconfigured mcp.json can hand an agent-driven request a path to cloud credentials or an internal metadata service.
This checklist is a practical attack-surface self-assessment you can run against your own MCP deployment in an afternoon. It is organized around the areas that show up repeatedly in disclosed MCP ecosystem vulnerabilities, and each item includes what to check and what good looks like.
Why the MCP layer is the attack surface
Before the protocol, an agent calling a tool meant bespoke integration code between one framework and one API. MCP standardized that connection, and the standardization is exactly what widened the surface: a single configuration file now grants an agent access to shell-capable utilities, database clients, browser automation, and internal HTTP services. Security controls that used to live inside application code — authentication, input validation, egress policy — moved partly into configuration and partly into third-party server packages that teams install without reading.
The threat model follows from that shift. An attacker does not need a zero-day in the model. They need one of three things: a prompt the model follows (prompt injection), a tool that over-trusts model-supplied arguments (injection and SSRF), or a configuration that hands the process ambient credentials (credential leakage). The checklist below is organized so that each section closes one of those three paths.
How to use this checklist
Walk the eight sections below in order. For each item, verify the configuration file, the server implementation, or both. Critical items are the ones that have appeared as direct exploit paths in real MCP ecosystem CVEs — our detection rules are grounded in those disclosures. At the end, we show how to automate the configuration portion with a free scanner.
1. Transport and authentication
- TLS on every transport. No MCP server should listen over plain HTTP outside an isolated local loopback. Check launch arguments, reverse proxy configs, and any
--httpflags. - Server authentication is enforced. Clients must verify server identity rather than trusting any endpoint that speaks the protocol. A missing check enables machine-in-the-middle interception of tool traffic.
- Shared secrets are not embedded in config. Scan
mcp.json,claude_desktop_config.json,.cursor/mcp.json, and CI variables for tokens sitting inline in JSON. - Local-only servers bind to loopback. A stdio or local HTTP server accidentally bound to
0.0.0.0exposes tool execution to the local network.
2. Credential and secret handling
- No cloud keys in configuration files. AWS access key IDs, GCP service account JSON, and Azure secrets should never appear in MCP config — they are trivially exfiltrated by any tool that can read files. Use environment injection or a secrets manager.
- Least-privilege credentials. The identity an MCP server runs under should be scoped to what its tools actually need. A broad admin key turns a single compromised tool call into an account-wide incident.
- No tokens in error messages or logs. Check that exceptions serialize arguments without leaking environment variables.
3. Tool surface minimization
- Explicit tool allowlist. Agents should only see the tools they need. Disabled or experimental tools left registered still accept calls.
- Argument validation on every tool. Each tool handler validates its own inputs — type, range, and format — before acting. Model output is untrusted input.
- Tool descriptions do not teach dangerous behavior. Descriptions that tell a model to “run shell commands as needed” are prompt injection waiting to happen; describe capabilities narrowly.
4. SSRF and egress control
- URL allowlists for fetch tools. Any tool that retrieves a URL supplied by the model must validate hostnames against an allowlist and block link-local ranges.
- Cloud metadata endpoints blocked. Egress to
169.254.169.254and its GCP/Azure equivalents must fail closed. This is the path that turns SSRF into stolen instance credentials. - No redirect following without re-validation. A validated external URL can 302 to an internal address; re-check the destination on every hop.
5. Command execution
- No shell strings built from model input.
exec("convert " + user_arg)is a command injection sink. Use argument arrays (spawn/execFile) withshell: false. - Command allowlist. If a tool wraps a CLI, the executable name comes from a fixed list, never from the model.
- Sandboxing around execution. Filesystem writes and subprocesses run inside a confined working directory with no inherited credentials.
6. Prompt injection boundaries
- Fetched content is treated as data, not instructions. Web pages, emails, and documents returned by tools are untrusted; content inside them must never change the tool-call plan without a human or policy gate.
- Tool results are screened before being acted on. Injection text arrives through tool outputs as often as through user prompts.
7. Logging, budgets, and kill switch
- Audit logging for tool calls. Record which tool was called, with what arguments, and what identity authorized it.
- Timeouts and token budgets. A runaway agent loop should hit a timeout and a spending ceiling rather than running indefinitely.
- A working kill switch. One configuration change or flag must disable tool execution globally — and it should be tested, not assumed.
8. Dependencies and supply chain
- Pinned versions with lockfiles. Unpinned MCP servers and tool dependencies can silently move to a compromised release.
- Scans run in CI on every change. Configuration and code drift are how a hardened setup quietly rots after the initial review.
Automating the self-check
The configuration portion of this checklist can be scanned automatically. The open-source correctover-scan CLI inspects MCP configuration files — including .cursor/mcp.json, claude_desktop_config.json, and .claude/mcp.json — for credential exposure, missing transport encryption, SSRF exposure, missing timeouts, and related misconfigurations, with results mapped to OWASP AISVS control IDs:
# Auto-detect and scan all MCP configs in the current directory
npx correctover-scan
# Scan a specific file
npx correctover-scan mcp.json
# SARIF output for the GitHub Security tab
npx correctover-scan -f sarif > report.sarif
In CI, the correctover-scan GitHub Action runs the same checks on every push and pull request, optionally failing the build on critical findings and uploading SARIF. Source and issues live in the correctover-scan repository; the package is on npm.
A configuration scan catches the deployment mistakes above. It does not reason about your agent’s code — for example, whether a tool handler concatenates model output into a shell string, or whether a free-text output field leaks credentials. That requires semantic analysis of code and traces, which is what a deeper audit covers.
Reading the scan results
A scanner report is only useful if the severities mean something. Treat findings in three tiers:
- Critical — fix before anyone else uses the agent: credentials inline in config, plaintext transport for a remote server, SSRF-capable fetch tools with no host validation, and shell execution fed by model arguments. Each of these has a direct, demonstrated path to code execution or credential theft.
- High — fix in the current sprint: missing input validation on tool handlers, no tool allowlist, absence of a kill switch, egress that reaches metadata ranges under certain configurations.
- Medium — track and schedule: missing audit logging, absent timeouts, unpinned dependencies, verbose error messages. These do not break in isolation, but they remove the detection and containment signals you need after the fact.
If the same finding appears in multiple MCP configs — for example every developer machine carries a token inline — fix it once at the source: move the secret to an environment-injected value or secrets manager and document the pattern, rather than editing twelve config files by hand.
A 30-minute first pass
If you have never audited your MCP setup, the fastest path to signal is short: run npx correctover-scan at the repository root, read the critical findings, and grep the same files for the high-signal strings scanners can miss — shell: true, child_process.exec with template literals, eval(, and hardcoded URLs containing 169.254.169.254 or localhost management ports. Configuration scanning catches what can be detected declaratively; that targeted grep catches the code patterns a config scanner structurally cannot see.
Turning results into a baseline
Treat the first scan as a baseline: fix critical findings, gate new ones in CI, and re-run after any change to tools or credentials. A hardened MCP deployment is not a one-time state — it is a baseline you keep verifying as the agent grows.
Free 1-page audit summary — reply with your repo link
Want a quick read on your own agent or MCP setup before a full review? Send us a repository link and we’ll return a free 1-page scan summary covering the findings our semantic engine flags, with concrete fix pointers.
Details: correctover.com/agent-audit.html