Skip to content

Same-origin dynamic client registration bypasses the OAuth destination guard under legacy SSE #2802

Closed

Description

@cliffhall

Problem

#2749 (PR #2796) sends every client's OAuth requests through the destination guard (core/mcp/node/fetchGuard.ts) and leaves MCP traffic on the plain fetch. The split is routeOAuthRequests plus exemptMcpEndpoint.

For legacy SSE, exemptMcpEndpoint treats the server's whole origin as MCP traffic, because the message endpoint is negotiated inside the stream. #2796 carves out two kinds of OAuth request from that exemption:

  • well-known URIs (discovery), which always go to the guard;
  • form-encoded token and revocation requests, which exemptMcpEndpoint already classifies as OAuth.

Dynamic client registration is neither. It is a JSON POST. If an SSE server's authorization-server metadata names a registration_endpoint on the server's own origin, that request is classified as MCP traffic and goes out unguarded. A redirect from it to 169.254.169.254 is then followed without the guard's checks, and the response can surface in the Network log or an error message.

Expected

Same-origin OAuth registration under legacy SSE goes through the guard, the same way discovery and token requests do.

Possible approaches

  • Route a request to the guard when its URL matches the registration_endpoint from the authorization-server metadata the client fetched. InspectorClient / OAuthManager know it, but createBackendBaseFetch on the web backend does not.
  • Classify MCP messages positively, as a JSON-RPC POST to the negotiated message endpoint, rather than by origin.
  • Pass the MCP-side fetch through a redirect check of its own, so an MCP-classified request still can't be redirected into a blocked range. This also covers the user's own MCP endpoint, which Port v1's link-local/metadata destination guard to v2's /api/fetch proxy #2749 deliberately left unguarded.

Priority score

Severity 3, Urgency 2, +1 milestone, Total 6 → Medium.

Activity

  1. added this to the v2.14.0 milestone on Oct 25, 2026
  2. added
    bugSomething isn't working
    v2Issues and PRs for v2
    on Oct 25, 2026
  3. cliffhall commented on Oct 25, 2026

    @cliffhall
    MemberAuthor

    Fixed in #2796 (903c04c). During review the router changed to identify MCP traffic by request shape (JSON-RPC POST, event-stream GET, session DELETE) as well as destination, so same-origin registration under legacy SSE now goes through the guard.

  4. modified the milestones: v2.14.0, v2.13.0 on Oct 25, 2026
  5. cliffhall commented on Oct 25, 2026

    @cliffhall
    MemberAuthor

    Shipped in #2796 (fae1aa2).

  6. self-assigned this
    on Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingv2Issues and PRs for v2

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions