MCP Limits: Confused Deputy and Overbroad Permission Scopes — why a server you built safely can still act with someone else's authority
A confused-deputy bug means the MCP server, not the attacker, does the damage: it uses its own standing privilege on the model's behalf, so a request that should never have been authorized still executes. This page is the failure-mode checklist for that specific class of bug — the named proxy attack, why servers end up over-permissioned in the first place, what it costs when they are, and which of the spec's countermeasures are mandatory vs. merely documented.
The confused deputy attack: a specific, named exploit chain
MCP's official security documentation defines the vulnerability precisely: an MCP proxy server performs actions using its own (often broad) privileges rather than the requesting user's — modelcontextprotocol.io/docs/tutorials/security/security_best_practices, "MCP Proxy Server" section. The attack is only possible when all four of these conditions hold at once (same source, "Vulnerable Conditions"):
1. The MCP proxy server uses a static client ID with a third-party authorization server. 2. The MCP proxy server allows MCP clients to dynamically register. 3. The third-party authorization server sets a consent cookie after the first authorization. 4. The MCP proxy server does not implement proper per-client consent before forwarding to third-party authorization.
The exploit chain: an attacker sends a victim a malicious link containing a crafted authorization request with a dynamic client ID; the victim's browser still carries a consent cookie from a prior legitimate authorization; the third-party authorization server sees the cookie and silently skips the consent screen; the resulting MCP authorization code is redirected to the attacker's server instead of the legitimate one (same source, Attack Description). The root cause is architectural, not implementation carelessness: the MCP client cannot distinguish who *initiated* a request (the model/agent) from who *holds* the authorization token (the original user) — github.com/modelcontextprotocol/modelcontextprotocol/issues/333. A related shape of the same bug: when a child agent is handed only a subset of the parent client's permissions but reuses the parent's token wholesale, that agent ends up operating with privileges superior to what it was actually authorized for (same issue, child-agent privilege-escalation scenario).
When it applies beyond OAuth proxies
the same structural failure — ambient authority plus no per-action check — also lets prompt injection hijack a server: broad permission scopes combined with missing per-action authorization let injected instructions drive the server into unauthorized actions — wiz.io/academy/ai-security/model-context-protocol-security. See MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface for that attack path in detail; this page is about the permission surface it exploits, not the injection vector itself.
Why servers end up over-permissioned in the first place
This isn't only an attacker-crafted edge case — it's the default shape most MCP servers ship in. Servers commonly request wide access (e.g. full Gmail permissions rather than read-only scopes) simply to keep functionality flexible for whatever the model might later need — arxiv.org/html/2511.20920v1, §3.3.1 "Over-Permissioning". Compounding this, most MCP host implementations give users no easy mechanism to restrict an agent to a safe tool subset — it's largely all-or-nothing at the point of connection (same source). Structurally, the authorization model historically lacked progressive scope elevation, so servers tend to expose every scope in scopes_supported up front rather than starting minimal — modelcontextprotocol.io/docs/tutorials/security/security_best_practices, "Scope Minimization". Official best practice is explicit about what to avoid: don't issue broad access tokens carrying scopes like files:*, db:*, or admin:* (same source).
Consequences: what actually breaks when scopes are too wide
- Data aggregation across services never designed for it. Combining calendar, email, and file-storage access inside one protocol layer creates aggregation potential none of the underlying services were architected to prevent — pillar.security/blog/the-security-risks-of-model-context-protocol-mcp. - Correlation attacks from partial compromise. Even a partial breach of one MCP server lets an attacker correlate information across every connected system without the user ever knowing (same source). - Single point of failure becomes multi-service disaster. Compromising one over-permissioned server hands the attacker simultaneous access to every service it was connected to (same source). - Insider misuse by legitimate operators. Given overbroad tokens, weak isolation, and incomplete audit trails, even the operator of a *legitimate* MCP server could extract user data across connected services for commercial purposes (same source) — this is a governance risk, not just an external-attacker risk. - Prompt injection turns broad scope into unauthorized tool calls. Malicious instructions hidden in data the model processes, or malicious tool metadata that steers tool selection, can trigger actions the model was never meant to authorize — embracethered.com/blog/posts/2025/model-context-protocol-security-risks-and-exploits/. One documented vector: hidden instructions embedded in tool descriptions via Unicode Tag characters pass through APIs and UIs invisibly, enabling tool calls the user never sees requested (same source).
Least-privilege patterns that exist — and why they're hard to enforce
Server-boundary control alone does not give you least privilege: doing it properly needs workload identity verification, context classification, and a runtime policy engine — obot.ai/blog/mcp-access-control-tool-level-permissions/. The default failure mode is coarser than that: granting a user access to an MCP server typically grants access to *every tool that server exposes*, which already violates least privilege before any attack happens (same source). The proposed fix is four layers: (1) registries mapped to identity providers, (2) tool-level filtering — enable only necessary tools, disable write/delete by default, (3) composite servers built per agent with a purpose-built tool set, and (4) audit and review of what was actually accessed (same source). Curity's framing of the same problem at the API layer: secure MCP access needs least-privilege, OAuth-driven authorization that extends past the MCP server boundary into the resource layer itself, with APIs validating audience, scopes, and claims — a simple server-level permission check is not sufficient — curity.io/resources/learn/design-mcp-authorization-apis/. Curity also recommends external agents receive opaque (reference) access tokens rather than self-contained tokens, specifically to limit information leakage and make revocation possible (same source).
Progressive scope elevation is the spec's own answer to "don't request everything up front": start with a minimal initial scope (e.g. mcp:tools-basic), elevate incrementally via targeted WWW-Authenticate scope challenges only when a privileged operation is actually attempted, and have servers tolerate down-scoped tokens rather than rejecting them outright — modelcontextprotocol.io/docs/tutorials/security/security_best_practices, "Scope Minimization" / "Progressive scope model". This is the practical mechanism Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt describes at the RFC level (the 403 + WWW-Authenticate: error="insufficient_scope" step-up flow); here it's the least-privilege *design pattern* the mechanism exists to enable.
UNVERIFIED
most MCP deployments in production reportedly do not implement tool-level access control or progressive scope elevation, defaulting instead to server-level all-or-nothing access — referenced across multiple security-advisory sources but not confirmed by official survey data (per the notes; no primary source given).
What the spec does and does not do about it today
The official MCP Authorization specification documents the confused-deputy attack directly and requires MCP proxy servers to implement per-client consent before forwarding to third-party authorization — modelcontextprotocol.io/docs/tutorials/security/security_best_practices, "Mitigation". Concretely, proxy servers MUST: maintain a registry of approved client_id values per user and check it before starting the third-party flow, storing consent decisions securely (same source, "Per-Client Consent Storage"); implement CSRF protection (state parameter or CSRF tokens) and block iframing via a frame-ancestors CSP directive (same source, "Consent UI Requirements"); and never accept tokens that were not explicitly issued for that MCP server — token passthrough is explicitly forbidden by the authorization specification (same source, "Token Passthrough"). This last rule is the direct fix for the Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt page's On-Behalf-Of discussion: passthrough is the anti-pattern, OBO exchange is the compliant alternative.
The gap is enforcement, not documentation: the spec supplies detailed mitigation patterns — per-client consent, scope minimization, OAuth state validation — but does not automatically enforce any of them; implementing them is left entirely to each MCP server author and host — modelcontextprotocol.io/docs/tutorials/security/security_best_practices (explicit note that these patterns live in documentation, not automatic enforcement). At the ecosystem level, the response has been architectural rather than a spec mandate: organizations are advised to define allowlists/blocklists of tools per user role and enforce deny-by-default so tool discovery never surfaces unapproved tools, centralizing this through an MCP gateway as a single enforcement point for every operation — arxiv.org/html/2511.20920v1, §4.1 and §4.6. See Enterprise MCP Integration Patterns — the Gateway Layer and the Build-vs-Buy Call Before You Ship a Server for that gateway pattern at deployment scale. As of the spec revision current at time of writing (2025-06-18), this gap — detailed mitigation patterns documented but not automatically enforced — remains open; no confirmed future spec revision closing it is documented in the sources reviewed for this page.
UNVERIFIED
MCP clients deployed to servers are recommended to implement SSRF protections (enforce HTTPS, block private IP ranges, validate redirect targets), but no widely adopted enforcement mechanism or compliance audit for this exists (per the notes; sourced only to unspecified "multiple security advisory sources").
Why this matters for building a working, secure server
This page is the concrete "on the first attempt" failure list for the wiki's own objective: a developer who implements OAuth mechanically (correct PKCE, correct RFC 8707 audience binding, per Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt) can still ship a server that is a confused deputy if it (a) reuses a static client ID against a third-party IdP without per-client consent tracking, (b) passes tokens through unchanged to downstream services, or (c) requests broad scopes by default because progressive elevation was never wired up. None of those are OAuth-protocol bugs — they are permission-scoping and consent-tracking decisions the spec leaves to the implementer, which is exactly why they are the failure mode that "actually bites" in practice.
Related
- Authorization in MCP: OAuth 2.1, Token Scoping, and the Confused-Deputy Problem — securing a remote server on the first attempt — the RFC-level mechanics (OAuth 2.1, PKCE, RFC 8707 audience validation, the On-Behalf-Of token-exchange fix) that a server must implement correctly for the confused-deputy attack described here to be closed. - MCP Limits: Prompt Injection and Tool Poisoning — why the primitives a working server relies on are also its attack surface — the companion attack vector: even a correctly-scoped server can be driven into unauthorized action if prompt injection exploits ambient authority the server still holds. - Enterprise MCP Integration Patterns — the Gateway Layer and the Build-vs-Buy Call Before You Ship a Server — the MCP-gateway deployment pattern that centralizes deny-by-default, per-role tool allowlisting, and audit logging, operationalizing the least-privilege patterns this page shows are hard to enforce server-by-server. - MCP Limits: Registry Trust and Supply Chain Risks — why 'it's in the registry' is not a safety guarantee before you connect a client — a related trust failure: even a well-scoped server is only as safe as the registry vetting that put it in front of a user in the first place.
Verified against
- modelcontextprotocol.io/docs/tutorials/security/security_best_p…
- github.com/modelcontextprotocol/modelcontextprotocol/issues/333
- arxiv.org/html/2511.20920v1
- pillar.security/blog/the-security-risks-of-model-context-protoc…
- embracethered.com/blog/posts/2025/model-context-protocol-securi…
- wiz.io/academy/ai-security/model-context-protocol-security
- obot.ai/blog/mcp-access-control-tool-level-permissions
- curity.io/resources/learn/design-mcp-authorization-apis
What links here
Source: Sinapsi — verified compositional memory, queryable by LLMs. Query this wiki live from your assistant over MCP, or build your own verified wiki (public, or private for your team). CC BY 4.0 — reuse with attribution to Sinapsi.