Insights Business| SaaS| Technology Confused Deputies, Token Passthrough and the Credential Failures in MCP Deployments
Business
|
SaaS
|
Technology
•
Sep 24, 2026

Confused Deputies, Token Passthrough and the Credential Failures in MCP Deployments

AUTHOR

James A. Wondrasek James A. Wondrasek
Confused Deputies, Token Passthrough and the Credential Failures in MCP Deployments

MCP’s credential failures are not a novelty problem. The specification already has a correct answer written as MUSTs, with a recent revision that tightened the previously vague parts. Deployments diverge from it anyway, and they do so where consent and credentials cross trust boundaries.

Three artefacts show how wide the gap is: a confused deputy that hands over authorisation codes without consent, a token passthrough the spec forbids, and a reality where only 8.5% of authenticating MCP servers use OAuth 2.1 against a 53% static-key majority. Each fails the same test: does your credential handling preserve audience binding and minimise scopes, or reuse tokens across trust boundaries?

The reason each failure follows the last is the authorisation model that assumed human consent; the MCP security overview traces that assumption through to the credential layer.

What is the confused deputy problem in MCP, and how does it yield authorisation codes without consent?

A confused deputy is a privileged intermediary induced to exercise its own authority on an attacker’s behalf. In MCP the deputy is the proxy server: it holds legitimate OAuth authority to a third-party API but applies it against the wrong principal. A static client ID and a consent cookie bound only to that ID let an attacker ride the shared consent artefact to an attacker-controlled redirect URI, without consent.

The flaw sits at the consent boundary. The user authenticates and the third-party authorisation server drops a consent cookie bound to the proxy’s single static client ID, which records that this user has consented without checking which client is asking. An attacker registers a new client, with its own redirect URI, through unauthenticated Dynamic Client Registration, and the proxy fronts that client upstream under the same shared static ID. The authorisation server sees the static ID it already trusts, skips consent, and sends the code to the attacker’s redirect URI.

Four preconditions stack into this: a static client ID, unauthenticated DCR, a consent cookie instead of per-client consent, and redirect-URI validation that accepts the attacker’s URI. The specification’s answer is per-client consent, a server-side registry of approved client IDs per user checked before forwarding upstream. But the attack rides the shared cookie past the authorisation server, which skips consent for the static ID it already trusts. It is the same weakness as state handle hijacking: an artefact minted in one principal’s context is accepted as proof of another’s authority — one of the trust-boundary failures mapped in the broader MCP security landscape.

What is token passthrough in MCP, and why does the specification forbid it?

Token passthrough means an MCP server accepts a token without verifying it was issued to that server, then forwards it unmodified to a downstream API. It is the only MUST NOT in the authorisation specification’s security considerations, because it breaks audience binding: a token minted for one service is replayed against another, which accepts a credential never meant for it.

Audience binding is what stops this, and it is the assumption the authorisation model was built on. Resource indicators (RFC 8707) bind a token to one audience at request time, and RFC 9068 tells a resource server to check the aud claim and reject anything not minted for it. The compliant alternative is a token exchange, RFC 8693’s on-behalf-of pattern, which swaps the inbound token for a new one scoped to the specific upstream.

LiteLLM’s MCP endpoint fell back to an empty auth object when key validation failed, so an unauthenticated attacker could open an authenticated session with an arbitrary bearer token. CVE-2026-59822, rated 8.8 High, sits on CISA’s Known Exploited Vulnerabilities list. When exchange fails, the correct behaviour is to fail closed.

The third instance of the same audience-binding failure is the static API key, and it is the credential most MCP servers ship with.

Why do only 8.5% of MCP servers adopt OAuth 2.1 over static API keys?

The answer is friction. OAuth 2.1 asks for PKCE, metadata discovery, per-client registration and consent before a first server ships. A static API key in an .env file works today, so developers take it. Astrix’s scan of 5,205 open-source MCP servers found 53% relying on static API keys or personal access tokens that never expire, against 8.5% using OAuth. A separate BlueRock scan of roughly 7,000 servers found 41% with no authentication at all. The two scans measure different populations and their methods are openly disputed, but the direction is not in dispute.

A static key carries no per-caller identity, no audience restriction, no scope minimisation and no granular revocation; revoke it for one bad actor and you break every caller at once. Long-lived keys pile up across config files, environment variables, CI/CD and collaboration tools, and the bill is secrets sprawl: GitGuardian counted 24,008 unique secrets in public MCP config files in 2025, with 2,117 still valid.

The clearest case is the shadow MCP server, an unregistered stdio server a developer drops into settings.json with a personal access token. It never touches an authorisation server and leaks by design. The 8.5% figure is therefore a governance decision.

What to do about it

The three failures share one boundary problem at three altitudes: consent, audience, and the ecosystem’s default credential. A shared consent cookie, a forwarded token and a static API key all fail the same test, and the spec already answered each: per-client consent, token exchange, audience-bound OAuth 2.1. Enforcement is the gap, and enforcement is a governance decision. Demand evidence before trusting a server with credentials, and treat the gateway as the identity boundary that brokers or degrades them.

So judge every credential against one question: was this token minted for the audience now receiving it, and does it carry only the scopes this request needs? If not, you have found a boundary failure, whether it wears a cookie, a forwarded token or a long-lived key. The specification already said no to passthrough and yes to per-client consent; nobody enforced it. Closing that gap starts with putting MCP credential risk in context.

Frequently Asked Questions

Is the confused deputy a flaw in the MCP specification, or in how deployments use it?

It is a deployment flaw, not a specification gap. The MCP authorisation specification already mandates per-client consent, audience binding and scope minimisation to prevent exactly this, and the confused deputy only appears when a proxy substitutes a shared consent cookie or static client ID for those controls. Treat it as a boundary-enforcement failure in your configuration, not something the MCP authors left open.

What is the difference between a confused deputy and state handle hijacking?

Both are stateless-boundary failures where an artefact minted in one principal’s context is later accepted as proof of another’s authority. The confused deputy rides a shared consent cookie through an MCP proxy server to obtain authorisation codes; state handle hijacking rides a reused server-side state handle. Different artefacts, same root cause, which is why a single evaluation lens catches both.

What is Dynamic Client Registration, and why does unauthenticated DCR matter?

Dynamic Client Registration (DCR) lets a client register itself with an authorisation server and receive a client ID without manual approval. It suits MCP’s many ephemeral clients, but when DCR is unauthenticated and a proxy reuses one static client ID, an attacker registers under that proxy and inherits the user’s prior consent. Registration without verification is the precondition that makes the confused deputy reachable.

What is OAuth token exchange, and how is it different from token passthrough?

Token exchange (RFC 8693), also called on-behalf-of, swaps an incoming token for a new one minted for the downstream audience, with its own scopes and lifetime. Passthrough forwards the original token unchanged. Exchange preserves audience binding; passthrough destroys it. If your gateway cannot exchange, its correct behaviour is to fail closed, not to degrade open as LiteLLM’s OAuth2 fallback (CVE-2026-59822) did.

What actually happens if one of my services forwards a token to a downstream API?

The downstream resource server sees a token that does not name it as the audience. If it validates the aud claim as RFC 9068 requires, the request is rejected and your integration breaks loudly. If it does not validate, it accepts a credential minted for someone else, recreating a confused deputy at the third-party service. Silent success is the dangerous outcome here.

How do I tell whether my MCP gateway or server is passing tokens through?

Inspect the token your downstream service receives and check its aud claim. If it is unchanged from the token your client presented, and its audience is a different service, you are passing through. A compliant path shows a new, audience-bound token with reduced scopes produced by a token exchange. Logging the aud claim at the boundary makes the difference visible.

Can I safely keep using static API keys if I rotate them often?

Rotation reduces the exposure window but does not restore the properties the specification expects. A static key still carries no per-caller identity, no audience restriction, no scope minimisation and no granular revocation, so it fails the same audience-binding test as a shared consent cookie. Frequent rotation shrinks risk time; it does not make the credential audience-bound, and it still compounds into secrets sprawl.

What is a shadow MCP server, and why does it leak credentials by design?

A shadow MCP server is an unregistered stdio server, often added to a developer’s settings.json, that holds a personal access token or static API key directly. Because it never touches an authorisation server, there is no consent step, no audience binding and no revocation path, so its credential leaks by default. It is the practical mechanism behind much of the secrets sprawl GitGuardian counted in public configs.

How do I evaluate whether my credential management preserves audience binding and scope minimisation?

Ask one question of every credential: was this token minted for the audience now receiving it, and does it carry only the scopes that request needs? A shared consent cookie, a forwarded token and a static PAT all fail that test; a token issued via resource indicators (RFC 8707) with narrowed scopes passes it. Apply the same lens at every trust boundary.

What should I ask before trusting a third-party MCP server with credentials?

Demand evidence, not assurances. Ask which OAuth 2.1 flows it supports, whether it validates the aud claim per RFC 9068, whether it exchanges rather than forwards tokens, what scopes it requests and why, and how it revokes access. A server relying on a static key or a shared consent model has not met the specification’s expectations, however mature its product appears.

Are the 53% and 8.5% figures reliable enough to act on?

Treat them as directional, not definitive. The 53% static-key and 8.5% OAuth 2.1 shares come from secondary scans of roughly 5,205 servers (Astrix) whose methodology is openly disputed, and BlueRock’s separate scan found 41% requiring no authentication at all. The precision is contestable; the direction, that the specification’s model remains a minority practice, is not.

What is a credential broker, and does it fix secrets sprawl?

A credential broker issues short-lived, audience-bound, narrowly scoped credentials on request, so applications never hold long-lived static keys. It is the scalable remediation: it replaces the static PAT that leaks by default with a token that expires and names its audience. It does not remove the governance decision, but it turns audience binding and scope minimisation into defaults rather than developer discipline.

AUTHOR

James A. Wondrasek James A. Wondrasek

SHARE ARTICLE

Share
Copy Link

Related Articles

Need a reliable team to help achieve your software goals?

Drop us a line! We'd love to discuss your project.

Offices Dots
Offices

BUSINESS HOURS

Monday - Friday
9 AM - 9 PM (Sydney Time)
9 AM - 5 PM (Yogyakarta Time)

Monday - Friday
9 AM - 9 PM (Sydney Time)
9 AM - 5 PM (Yogyakarta Time)

Sydney

SYDNEY

55 Pyrmont Bridge Road
Pyrmont, NSW, 2009
Australia

55 Pyrmont Bridge Road, Pyrmont, NSW, 2009, Australia

+61 2-8123-0997

Yogyakarta

YOGYAKARTA

Unit A & B
Jl. Prof. Herman Yohanes No.1125, Terban, Gondokusuman, Yogyakarta,
Daerah Istimewa Yogyakarta 55223
Indonesia

Unit A & B Jl. Prof. Herman Yohanes No.1125, Yogyakarta, Daerah Istimewa Yogyakarta 55223, Indonesia

+62 274-4539660
Bandung

BANDUNG

JL. Banda No. 30
Bandung 40115
Indonesia

JL. Banda No. 30, Bandung 40115, Indonesia

+62 858-6514-9577

Subscribe to our newsletter