Does Panther's MCP OAuth endpoint validate redirect_uri against a trusted hosts allowlist?

Last updated: June 24, 2026

QUESTION:

A security review found that the Panther MCP OAuth /v1/oauth/authorize endpoint accepts arbitrary https:// redirect URIs and returns a 302 redirect, even when the Remote MCP Client Allowlist is empty. Domains such as https://evil.com and lookalike subdomains are allowed to initiate the OAuth flow.

We assumed an empty allowlist would be deny-all. Is our environment exposed, or how does Panther actually enforce the redirect URI restriction?

ANSWER

Your environment is not exposed. This behavior is working as designed. Panther uses a two-phase validation model for OAuth redirect URIs:

Phase 1 — Structural validation at /authorize (initial request)

The /v1/oauth/authorize endpoint performs only structural validation when it first receives a request. This means:

  • Structurally invalid schemes (e.g. redirect_uri=javascript://...) are rejected with HTTP 400.

  • Structurally valid HTTPS URIs (e.g. redirect_uri=https://any-domain.com) receive HTTP 302 — but this redirect goes to the Panther sign-in page, not to the submitted domain. Nothing is delivered to the redirect_uri at this stage.

Phase 2 — Allowlist enforcement at the approve step (after authentication and consent)

After the user authenticates and explicitly approves permissions on the consent screen, Panther validates the redirect_uri against the configured trusted redirect hosts allowlist. This check runs before any authorization code is minted. If the URI does not match an allowlisted host, the request is rejected and no OAuth code is issued.

The /v1/oauth/authorize endpoint is already protected by WAF, including a dedicated rate-limit rule on OAuth paths.

What happens if I have an empty allowlist:

An empty Remote MCP Client Allowlist is fail-closed. With no hosts configured, no redirect_uri will pass the Phase 2 allowlist check, and no authorization codes will be delivered to any non-trusted destination. The 302 response from /authorize is expected and does not represent a security gap.