Why MCP servers are a security surface
The Model Context Protocol connects agents to tools and data, and that is exactly what makes it risky. An MCP server is third-party code your agent loads and trusts at runtime, often discovered and connected outside any single IDE’s view. The moment an agent can call it, that server’s tool descriptions become instructions the agent may follow, and its access becomes access the agent inherits. MCP server security treats each server the way you would treat any dependency you pull into production: as an untrusted supply-chain surface until proven otherwise.
The MCP threat taxonomy
The risks the community is cataloguing around MCP, including the emerging OWASP MCP Top 10, come down to a handful of failure modes. The ones that bite hardest in practice:
| Threat | What happens |
|---|---|
| Tool poisoning | Malicious instructions hidden in a tool’s description or metadata, followed by the agent even though the user never sees them |
| Rug pull | A server behaves well through approval, then changes its tool definitions or behavior afterward |
| Cross-origin escalation | One connected server reaches data or tools that belong to another context it should not touch |
| Credential exposure | Secrets are handed to a server, pulled into prompts and logs, or leaked through it |
| Token passthrough | A server forwards a token meant for it to an upstream API, breaking the audience boundary: a confused-deputy attack the MCP spec explicitly forbids |
| Audience confusion | A server accepts a token issued for a different resource, letting an attacker reuse tokens across services |
| Excessive scope | A server or agent is granted more permission than the task needs, so a single compromise reaches further |
| Command injection | A tool that shells out or evaluates its input lets crafted arguments run code on the host |
| Insufficient audit | No attributable record of which agent called which tool, so an incident can’t be reconstructed |
| Unscanned third-party servers | Servers adopted with no review, over-permissioned by default, and never re-checked |
None of these are exotic. They are the ordinary failure modes of loading someone else’s code and letting it act, applied to a protocol built for exactly that.
Tool poisoning and rug pulls
The two that surprise teams most are tool poisoning and rug pulls, because both defeat a one-time review. In tool poisoning, the attack lives in text the model reads but a human usually doesn’t: a tool description that quietly instructs the agent to exfiltrate a file or call another tool. A rug pull is the time-shifted version: the server is clean when you approve it and malicious later, after it has your trust and your traffic. Both mean approval at connect time is not a security control on its own.
Credential exposure
An MCP server frequently needs a downstream credential, a GitHub token, a database password, to do its job. The unsafe pattern is handing that credential into the agent’s environment, where a prompt injection or a poisoned tool can reach it. The safer pattern keeps credentials out of the agent entirely and brokers them at a governed boundary, so the agent acts without ever holding the secret it could leak.
What the MCP authorization spec requires
A lot of MCP security is won or lost in authentication. For HTTP transports the MCP authorization spec builds on OAuth 2.1: the MCP server is a resource server, a separate authorization server issues audience-bound tokens (RFC 8707), PKCE is mandatory, redirect URIs are validated exactly, and a server must never pass a client’s token through to an upstream API. Our MCP Authorization guide walks the full flow, discovery through token exchange, as animated diagrams.
The security-relevant upshot for hardening is this: OAuth scopes are coarse. They gate which server a token is good for, not which tool call with which arguments, which is why per-action authorization has to sit on top of the spec, not instead of it. A governed gateway is where these requirements become real controls rather than per-server good intentions: it validates token audience, refuses passthrough, brokers a separate upstream credential, holds scopes to least privilege, and then authorizes each individual tool call.
The named MCP attack vectors
The MCP project publishes a security best practices guide that names the attacks specific to MCP and the mitigations each requires. Build against these:
- Confused deputy. An MCP proxy using a static client ID to a third-party authorization server, combined with dynamic client registration and a lingering consent cookie, lets an attacker skip the consent screen and steal an authorization code. Mitigation: per-client consent stored server-side and checked before forwarding upstream, with exact redirect-URI and single-use
statevalidation. - Token passthrough. A server accepting or forwarding a token that was not issued to it. Mitigation: validate audience; never forward the client’s token to an upstream API.
- Session hijacking. A guessable or leaked session ID lets an attacker impersonate a client, or inject a malicious payload through a shared event queue. Mitigation: non-deterministic session IDs bound to the user (a
<user_id>:<session_id>key); never use sessions for authentication; verify every inbound request. - SSRF via metadata discovery. A malicious server points OAuth metadata URLs at internal services or a cloud-metadata endpoint (
169.254.169.254) to exfiltrate credentials. Mitigation: require HTTPS, block private and reserved IP ranges, route through an egress proxy, and guard against DNS rebinding. - Malicious authorization URLs. A server hands the client a
javascript:or shell-injecting authorization URL, leading to XSS or remote code execution. Mitigation: allowlisthttps:(loopbackhttp:only in dev), rejectjavascript:/data:/file:, and never open a URL through a shell. - Local server compromise. A one-click local-server config runs a malicious startup command with the user’s privileges. Mitigation: show the exact command and require explicit consent, sandbox local servers, and restrict their file and network access.
- Over-broad scopes. Granting omnibus scopes (
files:*,admin:*) up front widens the blast radius of a stolen token. Mitigation: least-privilege, progressive step-up scopes; never publish or request the full catalog.
A governed gateway enforces most of these centrally, audience validation, no passthrough, credential brokering, scope minimization, and per-tool authorization, instead of relying on every server to get them right on its own.
Hardening MCP servers
A workable baseline:
- Scan before load. Check each server and its tool definitions for poisoning, rug-pull risk, and known-bad patterns before an agent can use it. Open-source scanners like Ramparts do this for MCP specifically.
- Pin and re-verify. Treat a server like a pinned dependency and re-check it, so a post-approval change is caught rather than trusted.
- Broker credentials. Keep downstream secrets out of the agent’s runtime; issue scoped, short-lived access at a boundary instead.
- Enforce per call. Authorize each tool call at runtime against policy, not just the connection once at setup.
- Attribute and audit. Tie every tool call to an agent identity and owner so a bad one is traceable and revocable.
How Highflame secures MCP servers
Highflame treats MCP as a governed surface. Servers and their tool definitions are scanned before an agent can load them, with findings mapped to the OWASP MCP Top 10, and every tool call flows through a gateway that checks it against one policy at runtime, binds it to a verifiable agent identity, and can revoke access in under a second. Credentials are brokered rather than handed to the agent. It works with the MCP gateway you already run or ours. See the platform for the full picture.