Security: The Confused Deputy Problem in MCP Proxies
Overview
A vulnerability where an MCP proxy server with valid credentials to a third-party API is tricked into misusing those credentials on behalf of a malicious or unauthorized client.
Because relying solely on a third-party API's one-time consent cookie and a static client ID allows attackers to bypass authorization screens and hijack the proxy's privileges.
Where used: Enterprise MCP proxies, OAuth integration layers, Multi-tenant agent architectures
Why learn this
- Because 'confused deputy' is a distinct vulnerability class from prompt injection or tool poisoning.
- To correctly implement per-client consent tracking when building MCP proxy servers.
- To understand the limits of third-party OAuth one-time consent in distributed AI systems.
Code walkthrough
def handle_auth_secure(request):
client_id = request.query.client_id
# The proxy enforces its OWN consent boundary per-client
if not has_user_consented(user_id=request.user.id, client_id=client_id):
return render_proxy_consent_screen(client_id)
# Only forward to the third-party AFTER the proxy validates consent
return redirect(
f'https://oauth.example.com/auth'
f'?client_id={STATIC_CLIENT_ID}'
f'&redirect_uri={request.query.redirect_uri}'
)
Focus: Notice how the secure version blocks the forwarding until the user explicitly consents to the *specific* requesting client.
Common mistakes
- One-time consent is permanently safe: Developers assume that once a user approves an MCP proxy's connection to a third-party API, every future authorization request routed through that proxy is safe. In reality, a static client ID plus a consent cookie lets an attacker dynamically register a malicious client. Because the cookie is present, the third-party skips consent and hands the authorization code to the attacker. The fix is per-client consent tracking at the proxy.
- Confused deputy is just tool poisoning: Developers often blur these together. Confused deputy is an authorization boundary bug where the server misuses its own valid credentials. Tool poisoning is a content-trust bug where the LLM acts on malicious instructions inside a tool's response. Securing against one does not secure against the other.
Recall questions
- A developer builds an MCP proxy to Salesforce that shows the OAuth consent screen only the first time any user connects, then silently reuses the same static client ID. An attacker sends a link with a spoofed redirect_uri and a new client_id. What happens when the user clicks the link?
- What is the specific mitigation the MCP specification recommends to prevent confused deputy attacks in OAuth proxies?
- How does a confused deputy attack structurally differ from tool poisoning?
Understanding checks
A security team audits an MCP proxy and ensures that all tool descriptions are sanitized and no prompt instructions can be injected into the LLM context. Does this secure the proxy against confused deputy attacks?
No. Sanitizing tool outputs prevents tool poisoning, but it does nothing to fix authorization boundary flaws. If the proxy still uses a static client ID without per-client consent tracking, it is still vulnerable to confused deputy attacks.
Confused deputy is about who the proxy authorizes with its credentials, not what content it feeds back to the LLM.
A proxy uses a static client ID and the user's browser holds a consent cookie from yesterday. An attacker sends the user to the third-party authorization endpoint with a malicious `redirect_uri`. Will the user see a warning screen?
No. The third-party server sees the valid cookie and assumes consent was already granted, silently redirecting the authorization code to the attacker's URI.
The third-party server cannot distinguish between the proxy making a legitimate request and the attacker piggybacking on the existing session unless the proxy enforces per-client consent.
Practice tasks
Trace the Attack Flow
Explain how a static client ID and a consent cookie combine to bypass the OAuth consent screen in a confused deputy attack.