Where should Origin validation be enforced: SDK transport defaults or application middleware? #748
Replies: 1 comment
-
|
My instinct is that origin validation wants a secure default in the transport/SDK layer, with room for stricter application middleware on top.\n\nThe reason is that origin checks are like seatbelts: if they are optional and pushed outward, too many integrations will ship without them or will implement them inconsistently. But if they live only as a hardcoded transport default with no application-level escape hatches, teams lose context-specific policy controls.\n\nSo the split I would aim for is:\n- transport/SDK defaults enforce the baseline trust boundary correctly\n- application middleware can tighten policy for specific deployments, origins, or sensitive capabilities\n\nThat also matches the broader MCP pattern I keep seeing: baseline channel integrity belongs low in the stack, while capability-specific or semantics-aware policy usually belongs closer to execution. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Pre-submission Checklist
Discussion Topic
Context
The Streamable HTTP transport specification (
2025-11-25) states:Origin validation has been a server-side MUST since the HTTP+SSE transport in 2024-11-05; 2025-11-25 clarifies that a present invalid Origin must receive HTTP 403 Forbidden.
We tested the default server configurations across 9 official MCP SDK server implementations. Swift was not included in this pass. In that default setup, 6 out of 9 accepted requests with invalid
Originheaders, dispatching the JSON-RPC request normally with HTTP 200.I am not filing this as a per-SDK bug because the divergence appears to be about enforcement placement rather than a single SDK-specific implementation mistake.
However, this does not appear to be simply a matter of missing functionality. SDKs provide Origin validation mechanisms; they default to disabled and delegate enforcement to application-level middleware or deployment configuration.
This raises a question that we believe is worth discussing at the spec level: does the spec's "Servers MUST" apply to SDK transport defaults, or to the deployed server stack, which may include middleware?
Default behavior observed across SDKs
We sent requests with a clearly invalid
Originheader (http://evil.example.com) to each SDK's default conformance/example server configuration.SDKs that reject invalid
Originby default (3/9)TransportSecurityMiddleware; auto-configured for localhost. (Stable release v1.27.1 was default-off; fixed via CVE-2025-66416)SDKs that accept invalid
Originby default (6/9)allowedOrigins,enableDnsRebindingProtection)CrossOriginProtection)AllowedHostsconfigurationDnsRebindingProtection,allowedOrigins)allowedOriginsis nullOriginheader is not checked without an explicit allowlistallowed_origins)allowed_originsis empty (default)Access-Control-Allow-Origin: *by defaultActivation behavior
When Origin validation is explicitly enabled or configured, SDKs generally reject invalid Origins as follows:
http.StatusForbiddenAccess-Control-Allow-Origin, causing the browser to block the response; not a direct HTTP 403The enforcement placement question
The SDKs with Origin validation disabled by default can be understood as fitting a middleware-delegation model: Origin enforcement is treated as an HTTP-layer concern that may be handled by deployment middleware rather than directly by the MCP transport library. I do not want to overstate this as a formal maintainer position for every SDK; it is a neutral framing of the trade-off suggested by the implementations and documentation.
That model has reasonable motivations:
Deployment diversity. MCP servers run in contexts ranging from localhost dev tools to enterprise-hosted agent workflows. An SDK cannot always know which Origins are legitimate for a given deployment. Localhost-only defaults can break remote deployments; permissive defaults can leave localhost exposed.
Framework collision. HTTP frameworks (ASP.NET, Express, Gin, Actix) have mature CORS middleware. SDK-level Origin validation may conflict with or duplicate framework-level CORS handling, creating confusing double-enforcement or inconsistent behavior.
Separation of concerns. The SDK provides the MCP protocol logic; the HTTP server, reverse proxy, API gateway, or framework middleware handles transport-layer security. This mirrors how many HTTP APIs handle CORS — at the infrastructure or framework layer rather than inside the application protocol library.
The opposite model is also reasonable: for many deployments, the SDK effectively is the server, and secure defaults reduce the risk of missing middleware configuration. That model emphasizes:
No guaranteed middleware. When an MCP server is run directly (e.g., a standalone Java servlet), there may be no reverse proxy or framework middleware in the request path. The SDK transport may be the only enforcement point.
Secure-by-default principle. Requiring opt-in for security protections means every developer must know to enable them. The Python SDK's CVE-2025-66416 (CVSS 7.6) illustrates why default-off Origin protection can matter in practice: DNS rebinding was exploitable until v1.23.0.
Spec intent. The specification says "Servers MUST validate" without qualifying which component of a composed server is responsible. One straightforward reading is that the entity accepting HTTP requests, often the SDK transport in direct-exposure deployments, must validate.
Deployment patterns and implications
The middleware-delegation model works well when a reverse proxy, API gateway, or framework CORS middleware is reliably present before the MCP transport, so invalid Origins are rejected before MCP request handling.
The risk is in direct-exposure deployments. If the SDK transport receives browser-originated HTTP requests directly and Origin validation is disabled by default, there may be no effective enforcement point.
Both deployment shapes appear to exist in practice: enterprise deployments often use gateways or framework middleware, while developer tools, local servers, and quick-start examples may expose the SDK transport more directly.
Questions for the community
Spec subject scope. The spec says "Servers MUST validate the
Originheader." Does "Server" mean the SDK transport component, the deployed application stack, or any component in the request path as long as invalid Origins are rejected before MCP request handling?Conformance testing. The conformance repository (v0.1.16) does not include Origin validation tests. When Origin tests are added, should they exercise the SDK's default server configuration, or a "correctly configured" deployment profile?
Default posture. Should the spec express a preference for secure-by-default behavior, where Origin validation is enabled unless explicitly disabled, versus opt-in behavior, where it must be explicitly configured?
Framework integration guidance. For SDKs that delegate to framework middleware (C#/ASP.NET, TypeScript/Express), would spec-level guidance on what the middleware must enforce help clarify the boundary?
Related
allowedOrigins = null.Beta Was this translation helpful? Give feedback.
All reactions