MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy
← Threat Catalog

Configuration & Environment

redirect_uri validated with loose matching

HIGHCWE: CWE-601Rule: MCP-261

An MCP OAuth proxy validates the `redirect_uri` parameter using `.startswith` / `.endswith` / regex / glob matching instead of exact string equality — letting a maliciously-registered client choose a `redirect_uri` that passes validation but redirects to attacker infrastructure.

What it is

OAuth requires `redirect_uri` to be validated by exact string match against the registered URI. Any looser matcher creates a bypass: `startswith("https://app.example.com/")` is satisfied by `https://app.example.com.attacker.example`, regex with `.*` is satisfied by anything matching the prefix. The official MCP security best practices explicitly require exact match.

Why it matters for MCP

OAuth-proxy MCP servers receive registered `redirect_uri` values from MCP clients (RFC 7591 dynamic client registration) and need to validate them at every authorize request. Developers reach for `startswith` because it accepts trailing query-string parameters or paths — but the looseness lets an attacker steal the auth code via a different host that happens to share a prefix.

Vulnerable example

example.py
1
@app.get("/authorize")
2
def authorize(redirect_uri: str) -> dict:
3
    if not redirect_uri.startswith("https://app.example.com/"):
4
        return {"error": "invalid_redirect_uri"}
5
    return {"ok": True}

Secure example

example.py
1
REGISTERED_URIS = {
2
    "https://app.example.com/callback",
3
    "https://app.example.com/cb-mobile",
4
}
5
6
@app.get("/authorize")
7
def authorize(redirect_uri: str) -> dict:
8
    if redirect_uri not in REGISTERED_URIS:
9
        return {"error": "invalid_redirect_uri"}
10
    return {"ok": True}

How MCPSafe detects this

Per-occurrence detection in MCP-server-context files. Fires on `redirect_uri.startswith(...)` / `.endswith(...)` (Python) / `redirectUri.startsWith(...)` / `.endsWith(...)` (JS), `re.match`/`re.search`/`re.fullmatch` with `*` in the pattern, JS `regex.test(redirectUri)` with wildcard, or `fnmatch(redirect_uri, ...)`. The canonical safe patterns are `==`/`===` against the registered URI string or set/list membership against a registered URI set. `urlparse` component-by-component compare is accepted only when every component (scheme, host, port, path, query) is checked against a registered URI — partial-component comparison fails the spec's exact-match requirement.

See the full threat catalog for every documented detection.

Further reading

  • MCP Security Best Practices — Redirect URI Validation
  • CWE-601: URL Redirection to Untrusted Site

Scan an MCP server for this issue

MCPSafe runs this check — and every other rule in the catalog — on any MCP server you paste in.

Scan now