MCP SEP-2468 — RFC 9207 iss parameter for OAuth mix-up defense
AgentThe news. On May 17, 2026, MCP SEP-2468 was merged into the Model Context Protocol specification — proposed March 25, accepted May 5. The change recommends that authorization servers advertise
isssupport in their metadata and include the parameter in their authorization responses, and requires clients to validate it against the recorded issuer using simple string comparison per RFC 3986 §6.2.1. The motivation, taken directly from RFC 9207, is to close the long-standing OAuth mix-up attack in clients that trust multiple identity providers.
Picture the doorman. He has one name on his guest list — say, idp-a.example — and tonight that is the only venue whose guests he is letting in. A guest walks up. Without a wrist stamp, the doorman has no way to know which venue's list this person came from. Maybe it really is the right venue. Maybe it's someone from the bar next door who is hoping you don't check. The doorman has to guess. That is the OAuth mix-up scenario before SEP-2468: the client kicks off an authorization flow with one AS, an authorization response comes back, and the only signal the client has is its own session state — which the attacker is actively trying to confuse.
The fast path is each guest gets a stamp, printed with the venue name. The doorman doesn't have to remember faces. He reads the stamp, compares it letter by letter to the name on his list, and decides on the spot. The stamp is the iss parameter. It is not the token. It is metadata about which AS produced the response. The client compares response.iss against the issuer it had recorded when it started the flow, character for character. Match → continue to the token exchange. Mismatch → reject the response, no matter how convincing the rest of the payload looks.
The catch — and this is what makes the structural defense load-bearing — is that capability scoping and other content-layer checks can't fill in for the issuer check. Suppose every tool in your agent is read-only and every scope is minimal. An attacker still wins the mix-up if the client takes an authorization code minted by idp-b.evil and exchanges it at idp-a.example's token endpoint, because the eventual access token will be for the legitimate IdP — minted from the wrong user's session. The compromised data does not flow through a tool's parameters; it flows through the client's confusion about which IdP authenticated the user. That is a layer above the tool attack surface the rest of the agent's guardrails are built to police, which is exactly why the Layered Guardrails module sequences structural defenses before policy.
Consider a concrete illustration. Picture a workplace MCP host that trusts two authorization servers — idp-a.example (corporate SSO) and idp-b.example (a partner) — and 1,000 agent sessions per hour each completing one OAuth flow. Imagine an attacker who can substitute responses on 0.1% of flows. Pre-iss, the client has no signal to reject substituted responses, so the substitution rate equals the attack rate: 1,000 × 0.001 = 1 mix-up per hour, or ~24 per day (illustrative). Post-iss, a substituted response would carry iss=https://idp-b.example while the client recorded https://idp-a.example. The string-equality check fails for every substituted response that includes iss, so the post-defense rate drops to ~0 mix-ups per day (illustrative) — independent of how clever the substitution gets, with the residual restricted to ASes that do not advertise iss support and where client policy falls back to local rules.
Where the change earns its keep
The shape of what SEP-2468 actually adds is small. The table below contrasts the legacy flow with the SEP-2468 flow.
| Aspect | Legacy MCP auth flow | SEP-2468 (RFC 9207) |
|---|---|---|
| Issuer field on auth response | None | iss required when AS metadata advertises support |
| How client knows which AS replied | Inference from session state | Server tells you, via iss |
| OAuth mix-up defense | Out of scope — client policy | String-equal response.iss against recorded issuer |
| String comparison rule | N/A | RFC 3986 §6.2.1 simple string comparison |
| Server discovery | N/A | AS advertises iss support in its metadata; clients may apply local policy on servers that don't |
| Layer of defense | Capability scoping only | Structural (issuer) plus capability scoping |
The defense slots in neatly next to the existing guardrail stack. Capability scoping limits the blast radius of any single misuse. The Lethal Trifecta framing limits how private data, untrusted content, and exfiltration vectors are allowed to combine. SEP-2468 sits one layer below both — it ensures the client has not been silently rerouted to a different IdP before any of those checks even runs. None of the layers replaces the others; the value is in stacking them.
There is also a related lesson worth knowing. Mix-up is part of a broader pattern where protocol metadata gets repurposed as protocol contract. RFC 9207's iss is a small, fixed-shape addition with a single rule: equal or not. That makes it both easy to implement correctly and hard to mis-implement, which is exactly the property a defense-in-depth layer needs — every layer that requires nuanced configuration becomes its own attack surface.
The boundary of what SEP-2468 changes is not "how OAuth works." Existing single-IdP flows are unaffected; the comparison is trivially https://idp-a.example == https://idp-a.example and continues. The boundary is "what happens when a client trusts more than one AS at the same time" — the multi-IdP topology that production MCP hosts are increasingly running into. For those, the iss check is the difference between a structural defense and a hopeful one.
Goes deeper in: Agent Engineering → Layered Guardrails → Defense in depth
Related explainers
- MCP SEP-2663 — Async task handles for long-running tool calls
- MCP SEP-2577 — Three deprecations and a one-year migration window