Skip to content

Hosted MCP rejects browser-extension origins with 403 "Invalid Origin": please treat extension schemes as trusted origins #343

Description

@daoluc

Summary

Since early August 2026, https://mcp.notion.com/mcp rejects requests from browser extensions with 403 {"jsonrpc":"2.0","error":{"code":-32000,"message":"Invalid Origin: <extension-id>"},"id":null}. Browsers forcibly attach Origin: chrome-extension://<id> (or moz-extension://…, safari-web-extension://…) to every extension fetch, and the Fetch spec forbids overriding it, so extension-based MCP clients cannot work around this without extra browser permissions. This broke our extension's previously working Notion integration.

Reproduction

With a valid OAuth access token from the standard DCR + PKCE flow:

# Accepted — no Origin (native clients):
curl -X POST https://mcp.notion.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
# → 200

# Rejected — same request from a browser extension:
curl ... -H "Origin: chrome-extension://<extension-id>"
# → 403 {"jsonrpc":"2.0","error":{"code":-32000,"message":"Invalid Origin: <extension-id>"},"id":null}

Observed allowlist behavior: no Origin, http://localhost[:port], and https://mcp.notion.com pass; chrome-extension://…, moz-extension://…, Origin: null, and even https://www.notion.so are rejected. The OAuth endpoints (/token, /register) do not enforce this — only the MCP endpoint.

Why extension origins are safe to allow

The Origin check exists for DNS-rebinding / CSRF protection: preventing a malicious website from driving the MCP server through a victim's browser. Extension origins cannot be forged by web content — a webpage can never cause a request carrying Origin: chrome-extension://…, and DNS rebinding only yields http(s) origins. Rejecting extension schemes therefore adds no protection against the threat the check addresses, while breaking a legitimate class of MCP clients that, unlike native apps, cannot omit or modify the header.

Request

Either:

  1. Treat non-web origin schemes (chrome-extension://, moz-extension://, safari-web-extension://) as trusted, the same as an absent Origin; or
  2. Provide a way for clients to register their extension origin (e.g. during dynamic client registration) so it is allowlisted for tokens issued to that client.

Environment

  • Client: SurfMind browser extension (Chrome MV3), hand-rolled Streamable HTTP
    client, protocol version 2025-06-18
  • Auth: standard OAuth via DCR (token_endpoint_auth_method: none) + S256 PKCE
  • Started failing: ~August 2026 (previously worked; timing coincides with the
    August 4, 2026 MCP OAuth hardening release)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions