MCP Confused Deputy Attacks: A Practitioner's Guide to Auditing Server Authentication
A step-by-step procedure for finding missing authentication and confused-deputy authorization gaps in your own Model Context Protocol deployments

Proactive Security for the AI Era
NodeZero continuously and autonomously pentests infrastructure, identity, cloud, and now web applications, chaining weaknesses across every domain the way real attackers do. Every finding ships with replayable proof showing exploitable business impact, not theoretical risk.
If your organization has connected a large language model to internal systems through the Model Context Protocol, you have almost certainly stood up at least one MCP server that authenticates a human user once and then executes every subsequent tool call as that same broadly privileged identity, regardless of which client, which agent, or which specific request is actually asking. That pattern is a confused deputy waiting to be triggered.
A confused deputy attack, a term that predates MCP by decades in computer security literature, occurs when a program with legitimate authority to act is tricked into misusing that authority on behalf of a party who should not have access to it. In an MCP context, the "deputy" is the MCP server itself: it typically holds a single set of credentials or a broadly scoped token to reach a backend system (a CRM, a ticketing system, a code repository, a cloud console), and it exercises that authority whenever any connected client asks, without necessarily verifying that the specific requesting agent, session, or tenant is authorized for that specific action against that specific resource. The server is not compromised in the traditional sense. It is doing exactly what it was built to do. The problem is that what it was built to do turns out to be too permissive.
This is a hands-on audit guide, not another explainer of what MCP is or why agentic AI introduces new attack surface. If you want the broader threat landscape first, see our overview of Model Context Protocol security risks and our roundup of MCP server security scanner tools. This piece assumes you already have MCP servers running and walks through exactly how to check whether yours have an authentication gap, a confused-deputy authorization gap, or both, and what to do about each.
What a Confused Deputy Attack Looks Like in MCP, Specifically
The classic confused deputy setup involves three parties: a client that lacks direct authority to perform some action, a deputy that has that authority, and a resource the deputy protects. The attack succeeds when the client can get the deputy to perform the action on its behalf, using the deputy's authority rather than the client's own.
Map that onto MCP. The deputy is the MCP server, sitting between one or more AI agents (clients) and one or more backend systems (resources). Many MCP server implementations authenticate the connection once, often via a static API key, a long-lived personal access token, or a single OAuth grant issued to the server itself rather than to the individual requester, and then treat every tool call arriving over that connection as equally authorized. If the server holds a token scoped broadly enough to read or modify data across multiple users, projects, or tenants, and it does not re-validate on every single request that the requester is actually entitled to the specific resource being touched, then any client that can reach the server, whether a legitimate but compromised agent, a malicious tool description that tricks a legitimate agent into an unintended call, or a second tenant sharing the same server instance, can potentially reach data or actions that belong to someone else.
The OWASP MCP Security Cheat Sheet describes the vulnerability directly: it "occurs when an MCP server executes actions using its own (often overly broad) permissions rather than the requesting user's credentials." The core countermeasure OWASP recommends is equally direct: validate on each request that the session or token belongs to the current requester, and reject the call if it does not. That single sentence is the difference between a server that is merely authenticated and a server that is actually authorization-safe.
Why the 38% No-Auth Figure Matters More Than It Sounds
Independent scans of public MCP server deployments have reported that roughly 38% of servers examined had no authentication mechanism at all, a figure that has circulated widely alongside the OWASP MCP Top 10 project's classification of insufficient authentication and authorization as one of the framework's core risk categories. Separate research from the Cloud Security Alliance's Labs group has documented well over a thousand publicly reachable MCP servers with zero authentication requirements from its own scanning work, and describes the MCP specification's historical treatment of authorization as explicitly optional for implementations, not a bug in any one vendor's product but a gap the spec itself left open until recently.
The reason this number matters for an audit is not the precise percentage, which varies by scan methodology and dataset, but what "no authentication" implies once you understand the confused deputy mechanics above. A server with no authentication at all does not merely lack a login screen. It means any network-reachable client can enumerate every tool the server exposes and, in many configurations, invoke them directly, skipping past the confused deputy problem entirely because there is no gate to be confused about in the first place. Authentication is the precondition for authorization; you cannot meaningfully check whether a request is authorized for a specific resource if you never established who is making the request. That is why step one of any MCP audit has to be confirming authentication exists before you even get to checking whether it is scoped correctly.
Briefings like this, every morning before 9am.
Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.
The November 2025 Spec Update: OAuth 2.1 and PKCE Are No Longer Optional
The MCP authorization specification was revised in November 2025 to close much of the gap described above for remote, internet-reachable servers. The update mandates OAuth 2.1 (aligned with RFC 9700 guidance) as the baseline authorization framework for remote MCP servers, and makes PKCE, Proof Key for Code Exchange, mandatory for public clients rather than a recommended-but-optional hardening step. The revision also removed the plain PKCE code challenge method, requiring S256 only, and shifted the recommended default for client registration toward Client ID Metadata Documents rather than Dynamic Client Registration, which had its own set of trust and impersonation weaknesses.
For local, single-user, stdio-transport MCP servers running entirely on a developer's own machine, the spec's authorization requirements remain lighter, since the trust boundary is different when a server is not reachable over a network. But for any MCP server intended to be accessed remotely by more than one user or agent, which describes the large majority of enterprise deployments connecting an LLM to shared internal systems, the spec now treats OAuth 2.1 with PKCE as the expected baseline, not an advanced option. If your remote MCP servers predate this update or were built against earlier guidance, this is the single most likely place to find a spec-conformance gap during an audit.
It is worth being precise about what OAuth 2.1/PKCE does and does not solve. It authenticates the client and protects the authorization code exchange from interception. It does not, by itself, guarantee that the server checks the resulting token's scope and audience on every downstream tool call, and it does not by itself prevent the confused deputy problem described above. A server can be fully OAuth 2.1/PKCE compliant at the connection layer and still be a confused deputy at the tool-invocation layer if it does not separately validate token audience and per-request authorization. Both checks are required; neither substitutes for the other.
Prerequisites: What You Need Before Starting This Audit
This audit assumes you can answer a few basic questions about your own environment before you start, and assumes read access to the systems listed below. Gather these first so the procedure that follows does not stall partway through.
An inventory of every MCP server your organization runs or connects to
Including internally built servers, third-party servers connecting to SaaS platforms, and any servers bundled with developer tools such as IDE assistants or debugging utilities. Shadow deployments stood up by individual teams are the most common gap here.
Access to each server's configuration and, ideally, source
You need to see how each server authenticates incoming client connections and how it authenticates itself to backend systems, not just how it is documented to work.
A list of what each server's backend credentials can actually reach
The token, API key, or service account each MCP server holds, and the full scope of data or actions that credential is permitted to touch, independent of what the server's tool descriptions claim it does.
Network topology for each server
Whether each server is reachable only from localhost via stdio transport, from an internal network segment, or from the public internet, since remote-reachable servers carry the OAuth 2.1/PKCE spec obligations described above and the highest exposure.
A test account or sandbox tenant, where the deployment is multi-tenant
You cannot safely test cross-tenant isolation against production customer data. If your MCP server serves more than one customer, team, or organization, get a second test identity provisioned before you start step 6 below.
The Audit Procedure: Checking Your Own MCP Deployments for Auth and Confused-Deputy Gaps
Work through these checks in order for every MCP server on your inventory. Each step builds on the one before it: there is little value checking authorization scoping on a server that turns out to have no authentication at all, so do not skip ahead.
1. Confirm authentication exists on every remote-reachable server
For each server reachable outside localhost, attempt to connect and list tools without presenting any credential. If the server responds with a tool list or executes any call, it has no authentication and is in the population OWASP and CSA Labs describe as most exposed. This is a stop-the-line finding, not a backlog item.
2. Verify the authentication mechanism matches the transport and reachability
Confirm remote, multi-user servers use OAuth 2.0 or 2.1 with PKCE rather than a static bearer token or shared API key baked into a config file. A static API key shared across every client connecting to a remote server is functionally equivalent to no per-user authentication, even though a credential is technically required.
3. Check PKCE method and code verifier handling
If OAuth is in use, confirm the authorization code flow uses PKCE with the S256 challenge method, not plain, and that the authorization server rejects requests using the deprecated plain method. Confirm state parameters are cryptographically random and validated on callback to rule out CSRF against the authorization flow itself.
4. Inspect token audience validation on every tool-call endpoint
This is the step most audits skip and the one that matters most for confused deputy specifically. Obtain a valid token issued for a different resource or a different MCP server, and attempt to use it against the server under test. If the server accepts a token whose audience (the JWT aud claim) does not match its own identifier, it is not validating audience, and any token issued for a related service can likely be replayed against it.
5. Confirm the server does not pass user tokens through to backend services unchanged
Trace what credential the server actually presents to the backend system it calls. If it forwards the client's own token verbatim rather than exchanging it for a server-scoped credential or validating it and using its own service identity, a compromised or malicious client can potentially use the MCP server as a relay to reach the backend directly with the user's privileges, bypassing whatever scoping the server was meant to enforce.
6. Test cross-tenant and cross-session isolation directly, using your test account
Using two distinct test identities (or, for multi-tenant SaaS-connected servers, two distinct test tenants), issue near-simultaneous requests for tenant-specific data and confirm each identity only ever receives its own data, including in any caching layer. This is the exact failure class behind the Asana incident described below, and it will not show up in a single-session test.
7. Review scope grants against actual tool capability
For every OAuth scope or permission the server requests, confirm it matches the narrowest capability the connected tools actually need. A server that requests full read-write access to an email account to support a single read-only summarization tool is over-scoped, and every unnecessary scope widens the blast radius if the confused-deputy checks above ever fail.
8. Check for credential and token storage hygiene
Confirm OAuth tokens and API keys are held in OS-native secure storage (a platform keychain or secret service) rather than plaintext configuration files, and confirm no single credential is shared across multiple distinct MCP servers, which would let a flaw in one server's authorization logic expose data reachable through an entirely different server.
9. Confirm session binding to identity, not just to a connection
Verify that session identifiers are bound to a specific user or agent identity (not just a TCP connection or process) and that the server re-validates that binding on each request rather than only at connection setup, closing the gap that allowed the Asana cross-tenant exposure to persist across a cached connection.
10. Check whether sensitive operations require an explicit human approval step
For actions with real-world consequence (sending a message, deleting a record, approving a financial transaction, modifying access controls), confirm the server or client surfaces an explicit confirmation to a human rather than executing autonomously on the agent's decision alone. This does not fix an authorization gap, but it is a practical last line of defense against one that has not yet been found.
How to Validate That a Fix Actually Closed the Gap
Finding a gap and closing it are different exercises, and MCP's request-response model makes it easy to convince yourself a fix worked when it only worked for the specific case you happened to retest. Validate remediation with the following checks before you close the finding.
Re-run the exact negative test that found the original gap, not a variation of it. If step 4 above found that a mismatched-audience token was accepted, the validation test is presenting that same class of token again, not simply confirming that a correctly-scoped token still works (which tells you nothing about whether the vulnerable path was actually closed).
Test under concurrency, not just sequentially. The Asana incident specifically involved cross-tenant contamination that surfaced under overlapping requests from different organizations, a condition single-threaded manual testing will not reproduce. Issue near-simultaneous requests from your two test identities from step 6 and confirm isolation holds under load, not only when tested one request at a time.
Confirm the fix at the server, not the client. If your remediation involved instructing the connecting AI agent or client to only request appropriately-scoped tokens, that is a client-side control an attacker's own client will simply not follow. The server must independently reject an under-scoped or mismatched request regardless of what any client claims about its own intentions; validate that the server rejects the bad case even when you construct the malicious request directly, bypassing the client entirely.
Re-check after any dependency or library update. Several of the concrete CVEs across the MCP ecosystem, including CVE-2025-49596 discussed below, were fixed in a specific point release. Confirm your running version is actually at or above the fixed release, not merely that a patch exists, and re-verify this on a schedule rather than once at initial remediation.
Common Mistakes and Failure Modes Found During These Audits
A few patterns show up repeatedly when organizations run this kind of audit for the first time, and are worth checking for specifically rather than assuming your deployment is the exception.
Treating authentication as a proxy for authorization. A server can require a valid, well-formed OAuth token on every request and still be a confused deputy if it never checks whether that specific token is authorized for the specific resource or tenant the request targets. Authentication answers "who is this," authorization answers "is this identity allowed to do this specific thing to this specific resource," and an audit that stops at the first question has not actually assessed confused-deputy risk.
Assuming development or internal-only servers are out of scope. Internal tooling frequently holds the broadest backend credentials, precisely because it was built quickly for a trusted audience, and "internal-only" is a network assumption that changes the moment a VPN misconfiguration, a compromised endpoint, or a third-party integration extends reachability further than intended.
Relying on tool descriptions as documentation of actual server behavior. An MCP tool's description field is a natural-language string an agent reads to decide when to call it; it is not enforced by the server and is not evidence of what scopes or backend calls the tool actually triggers. Audit the implementation, not the description.
Fixing the authorization flow but leaving long-lived tokens in place. Rotating to OAuth 2.1/PKCE for the initial handshake does not retroactively revoke a static API key or long-lived personal access token that was already deployed for the same server before the change. Confirm old credentials are explicitly revoked, not merely superseded, since an unrevoked legacy credential bypasses the entire upgrade.
Skipping the multi-tenant concurrency test because "we only have one customer today." Authorization logic that has never been exercised under multi-tenant load is untested code, not verified-safe code, and the Asana incident is a direct example of a gap that a single-tenant test plan would never have surfaced.
Real Incidents: The Asana Cross-Tenant Exposure and CVE-2025-49596
Two documented incidents illustrate the difference between an authorization-scoping failure and an authentication-absence failure, and an audit needs to check for both.
Asana launched an experimental MCP server in May 2025 to let connected AI assistants query its Work Graph data. Asana discovered a logic flaw in that server in June 2025 and took the integration offline for roughly two weeks while investigating and patching it. The root cause was a tenant isolation failure: the server did not consistently re-verify tenant context on cached responses, so under certain conditions a request from one organization could receive data cached from a different organization using the same MCP infrastructure, exposing task details, project metadata, comments, and files across organizational boundaries with no external attacker required at all. Reporting indicates roughly a thousand customers were potentially affected before the fix. This is confused-deputy risk in its purest form: the server held broad backend access on behalf of many tenants and did not consistently verify, on each request, that the response it was about to return actually belonged to the tenant asking for it, which maps directly onto audit step 6 and step 9 above.
CVE-2025-49596 is a different failure mode: a critical remote code execution vulnerability, with a CVSS score of 9.4, in Anthropic's MCP Inspector, a developer tool used to test and debug MCP server implementations. The flaw was a straightforward absence of authentication between the Inspector's browser-based client and its local proxy server, which accepted arbitrary commands without validating the source of the request. Combined with a known browser weakness that lets a malicious website reach services bound to localhost, an attacker could get a developer to visit a crafted web page and achieve code execution on that developer's machine simply because the Inspector's proxy trusted any request that reached it. Versions below 0.14.1 are affected; the fix is upgrading to 0.14.1 or later. This incident is a reminder that "no authentication" gaps are not confined to production, internet-facing servers; developer tooling running only on localhost carried the same root problem and produced remote code execution rather than data exposure. For a broader look at the scanner tooling that can help catch this class of issue across a fleet of servers, see our roundup of MCP server security scanners, and for the wider landscape of MCP-specific risks beyond authentication, see our MCP security risks overview.
Tradeoffs: OAuth 2.1/PKCE Enforcement vs. Network-Level Restrictions
Most organizations will end up combining more than one mitigation approach, and it is worth being explicit about what each buys you and what it does not, since teams under time pressure often reach for the weaker control because it is faster to deploy.
OAuth 2.1 with PKCE enforcement, applied correctly, is the strongest available control because it authenticates individual clients and, when paired with audience validation and per-request authorization checks, directly closes the confused-deputy gap rather than merely reducing exposure to it. The tradeoff is implementation cost and complexity: it requires an authorization server, correct redirect URI and state handling, token audience checks on every tool invocation, and ongoing maintenance as client registrations change. Done incompletely, an organization can end up with OAuth 2.1 at the connection layer and still be a confused deputy at the tool layer, as noted above, which is a worse outcome than it looks because it creates false confidence.
Network-level restrictions, limiting an MCP server's reachability to a VPN, a private network segment, or an allowlisted set of source addresses, are faster to deploy and meaningfully reduce the population of potential attackers for a server that has no authentication yet. They are a legitimate interim compensating control, not a substitute for authentication and authorization. Network position says nothing about whether one legitimate, network-reachable client can access another legitimate client's data, which is precisely the confused-deputy and cross-tenant failure mode behind the Asana incident. Two Asana customers with valid access to the same MCP integration were both "inside the network" in every sense that mattered, and isolation still failed. Network restrictions also erode over time as VPN configurations drift, new integrations are added, and third parties are granted access for unrelated reasons, so a server secured only by network position needs its exposure re-verified on a recurring schedule, not assumed to hold indefinitely.
Least-privilege scoping (requesting narrow OAuth scopes, using short-lived tokens instead of long-lived personal access tokens, and giving each server its own credential rather than sharing one across servers) is not a substitute for either of the above but materially limits the damage when the other controls fail. It is comparatively cheap to implement and worth doing regardless of which primary approach you choose.
The practical recommendation across the sources reviewed here is layered: authenticate with OAuth 2.1/PKCE for anything remote and multi-user, validate audience and re-authorize on every request rather than trusting the connection as a whole, scope credentials narrowly and per-server, and use network restrictions as a genuine defense-in-depth layer rather than a primary control you rely on in place of the first two.
The bottom line
An MCP server that authenticates once and then trusts every subsequent tool call from that connection is a confused deputy risk regardless of how strong its initial login step is. The November 2025 spec update makes OAuth 2.1 with PKCE the expected baseline for remote MCP servers, but that alone does not close the gap; it has to be paired with per-request audience validation and authorization checks, the exact control that failed in Asana's cross-tenant exposure and that a straightforward missing-authentication check would have flagged in the CVE-2025-49596 MCP Inspector flaw. Work through the ten-step audit above against every MCP server in your inventory, starting with whether authentication exists at all, before assuming your deployment is the exception to the roughly 38% of scanned public servers reported with none.
Frequently asked questions
What is a confused deputy attack in the context of MCP servers?
It occurs when an MCP server, which typically holds broad backend credentials shared across many clients or tenants, executes a tool call using its own authority rather than verifying that the specific requesting agent or session is actually authorized for that exact action and resource, allowing unauthorized access without the server itself being compromised.
Is a confused deputy attack the same thing as an MCP server having no authentication?
No. Missing authentication means the server does not verify who is connecting at all. A confused deputy gap can exist even on a server with strong authentication, if it fails to re-check per-request authorization, such as token audience or tenant scope, once a client is already connected.
What did the November 2025 MCP specification update change about authentication?
It made OAuth 2.1, aligned with RFC 9700, the required baseline authorization framework for remote MCP servers and made PKCE mandatory for public clients using the S256 challenge method only, replacing the previously optional and less consistently enforced authorization guidance in earlier spec versions.
What happened in the Asana MCP data exposure incident?
Asana's experimental MCP server, launched in May 2025, contained a tenant isolation logic flaw discovered in June 2025 that allowed cached responses to cross organizational boundaries under certain conditions, exposing task, project, and file data between different customer organizations for roughly a month before Asana took the integration offline to patch it.
What is CVE-2025-49596 and how does it relate to MCP authentication gaps?
CVE-2025-49596 is a critical (CVSS 9.4) remote code execution vulnerability in Anthropic's MCP Inspector developer tool, caused by its local proxy server accepting commands without authenticating the source of the request, allowing a malicious website to trigger code execution on a developer's machine. It is fixed in version 0.14.1 and later.
Does enforcing OAuth 2.1 with PKCE fully prevent confused deputy attacks in MCP?
Not by itself. OAuth 2.1/PKCE secures the authentication handshake and protects the authorization code exchange, but a server must separately validate token audience and re-check authorization on every individual tool call to close the confused deputy gap; a server can be fully OAuth 2.1 compliant at the connection level and still act as a confused deputy at the tool-invocation level.
Sources & references
- Aembit: MCP Authentication and Authorization Patterns
- OWASP MCP Security Cheat Sheet
- CSA Labs: MCP Security Crisis Research Note
- BleepingComputer: Asana warns MCP AI feature exposed customer data to other orgs
- Recorded Future: Anthropic MCP Inspector CVE-2025-49596 Vulnerability Disclosure
- Oligo Security: Critical RCE in Anthropic MCP Inspector (CVE-2025-49596)
Free resources
Critical CVE Reference Card 2025–2026
25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.
Ransomware Incident Response Playbook
Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.
Get threat intel before your inbox does.
50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.
Unsubscribe anytime. We never sell your data.

Founder & Cybersecurity Evangelist, Decryption Digest
Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.
