Skip to content

OAuth debugger SSRF guard blocks intranet MCP servers on CGNAT (100.64/10) — no opt-out for self-hosted use #3694

Description

@anengineerdude

Summary

The OAuth debugger's backend proxy (/api/mcp/oauth/debug/proxy) refuses to send requests to MCP servers whose hostname resolves into 100.64.0.0/10 (CGNAT / RFC 6598 shared address space). The SSRF guard in sdk/src/oauth/ssrf-guard.ts classifies that range as disallowed:

if (a === 100 && b >= 64 && b <= 127) return true; // 100.64/10 CGNAT

Every OAuth debugger step then fails at request_without_token with Backend debug proxy error: 400 Bad Request — before any request reaches the server, so from the user's perspective a perfectly healthy server "fails OAuth" with no actionable detail.

Why this matters

Self-hosted Inspector on a corporate network is exactly the environment where an internal MCP server lives behind a load-balancer VIP in shared address space. The server in our case returns a spec-correct 401 + WWW-Authenticate: Bearer resource_metadata=... challenge (verified with curl byte-for-byte against the debugger's request), and other clients (Claude Code, Open WebUI) complete the full OAuth flow against it. Only the Inspector's guarded proxy path is unable to test it.

The SSRF guard is entirely reasonable for the hosted product; for a locally-run Inspector pointed at intranet infrastructure it blocks the primary use case.

Repro

  1. Run the Inspector locally (localhost:6274).
  2. Add an HTTP MCP server whose DNS resolves to an address in 100.64.0.0/10 (OAuth-protected, returns a standard 401 challenge).
  3. Open the OAuth debugger and start the flow.
  4. First step fails: Backend debug proxy error: 400 Bad Request; the server never receives a request.

Ask

An explicit opt-out for self-hosted/local mode — e.g. an env var like MCPJAM_ALLOW_PRIVATE_TARGETS=1 (or a per-server "trust this private host" toggle in the UI) that relaxes the SSRF guard for the debug proxy when the Inspector is not running in hosted mode. Even limiting the exemption to 100.64/10 + RFC 1918 while keeping loopback/link-local rules intact would cover the corporate-intranet case.

Happy to test a patch against our environment.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions