MCP Security in Production: What the Spec Does Not Solve

The MCP spec secures who can connect, not what your agent does next. Here is what it requires, what it leaves to you, real CVEs, and a production checklist.

Nov 5, 20265 min read
MCP Security in Production: What the Spec Does Not Solve
MCPModel Context ProtocolAI SecurityAI AgentsPrompt InjectionOAuthTool PoisoningApplication Security

Model Context Protocol has become the default way to connect AI agents to real tools, which means an agent can now read a customer record, open a pull request, or run a query. That power is exactly what makes MCP security worth getting right, and the part most teams misunderstand is this: following the spec secures who can connect, not what your agent will do once connected.

The current MCP specification, version 2026-07-28, is strong on authorization. It says far less about prompt injection, which is where agents are most exposed. Here is what the protocol gives you and what you still have to build.

What the spec requires

The first detail surprises people: authorization is optional in MCP. Local stdio servers are expected to take credentials from the environment instead. For HTTP servers that do implement it, the rules are specific:

  • OAuth 2.1 for authorization servers, with Protected Resource Metadata on the MCP server.
  • PKCE is mandatory for clients, and they must refuse to proceed if the server does not advertise support for it.
  • Resource indicators (RFC 8707) must be sent by clients, so tokens are bound to one specific server.
  • Audience validation: servers must only accept tokens issued specifically for them.
  • No tokens in query strings, and invalid or expired tokens get a 401.
  • Dynamic Client Registration is deprecated, kept only for backwards compatibility. Client ID Metadata Documents are the newer path.

Authorization mistakes the spec warns about

The spec's security best practices describe the attacks behind those rules. These are the ones most relevant if you build MCP servers:

Token passthrough

Your server receives a client's token and forwards it to a downstream API. The spec calls this an anti-pattern and forbids it outright: an MCP server must not pass through the token it received. Upstream calls need a separate token, otherwise you lose audit trails and audience checks in one move.

Confused deputy

This targets MCP proxies that connect to third-party APIs using a static client ID. An attacker can abuse existing consent cookies to obtain authorization codes without the user approving anything. Proxies must get user consent for each dynamically registered client before forwarding to the third-party authorization server.

Server-side request forgery

MCP clients follow URLs during OAuth discovery, and a malicious server can point them at internal addresses. Validate and restrict those URLs. Real servers have this issue too, as the Grafana case below shows.

What the protocol does not solve

The spec is direct about its limits. It says MCP cannot enforce its security principles at the protocol level, and that tool annotations should be considered untrusted unless they come from a trusted server. The pages I read offer no protocol-level defense against these three attacks, so they are yours to handle. The definitions below come from Pillar Security's analysis, which is a vendor source:

  • Tool poisoning: instructions hidden in a tool description tell the model to do something the user never asked for.
  • Rug pulls: a server behaves well during review, then changes its descriptions or behavior after an update.
  • Indirect prompt injection: content returned by a tool, such as an email, web page or database row, carries instructions the model follows.

Indirect injection is the hard one, because the attacker never touches your system. They only need to place text somewhere your agent will read it. OWASP ranks prompt injection as LLM01, and also lists Supply Chain (LLM03) and Excessive Agency (LLM06), which together describe most of the MCP risk surface. Agent-specific risks are covered in its separate Top 10 for Agentic Applications.

Real vulnerabilities

These are not theoretical. Each of these is a published CVE that I checked against its official record:

CVEProductCVSSIssue
CVE-2025-6514mcp-remote 0.0.5 to 0.1.159.6OS command injection
CVE-2026-19516mcp-grafana up to 1.0.09.1Caller-controlled request target
CVE-2026-10591Amazon Kiro IDE before 0.118.8Agent file writes to sensitive paths

The three show different failure modes. In mcp-remote, simply connecting to an untrusted server was enough, through a crafted authorization endpoint. In mcp-grafana, a caller-supplied header chose where the server sent its requests. In Kiro, crafted instructions could cause writes to paths such as .vscode/tasks.json, turning a file edit into code execution. That last one is the pattern to remember: an agent's harmless tool can become dangerous depending on what it touches.

A production checklist

Before you connect a server

  • Keep an inventory and an allowlist of approved servers and tools.
  • Pin versions, and review changes to tool descriptions on update, not just code.
  • Treat community MCP servers as third-party code, because that is what they are.

Limit the blast radius

  • Give each server its own least-privilege credentials, and keep secrets out of config files.
  • Use read-only access unless writing is genuinely required.
  • Run local servers in a sandbox without access to your home directory or broad network.
  • Block agent writes to config, CI, and task files that can trigger execution.

Assume injection will succeed

  • Treat every tool result as untrusted data, not instructions.
  • Avoid letting one agent combine private data, untrusted content, and a way to send data out. If it needs all three, require a human in the loop.
  • Require human approval for irreversible actions, and turn off auto-approval in production.
  • Filter outbound requests with a domain allowlist so stolen data has nowhere to go.

Watch and test it

  • Log every tool call with its arguments, user and result.
  • Alert on unusual tool sequences and sudden changes in behavior.
  • Red-team through your tools by planting injection text in the documents and tickets your agent reads.
  • Confirm that rejected auth really stops a request, since a passing login test proves nothing about the failure path.

The mindset that holds up

Treat your agent as a capable employee who can be tricked by anything it reads. You would not fix that with a stronger instruction, so do not rely on a better system prompt here either. Model-level defenses keep improving, but the durable protection is architecture: least privilege, isolation, approval gates, and egress control. Then a successful injection becomes a logged, contained event rather than a breach.

Shipping agents that touch real customer data? I help startups design them safely through remote AI product work.

Work with a senior Next.js developer from India.

I help US and UK startups build fast SaaS products, dashboards, AI interfaces, and full-stack web apps.

Hire Me

Related blogs.

More notes connected by category, topic, and technical context.

All Blogs