Skip to content

Commit 11122db

Browse files
Improve clarity of host and origin validation guidance
Co-authored-by: Stephen Halter <halter73@gmail.com>
1 parent 21b7006 commit 11122db

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

docs/concepts/getting-started.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,15 @@ public static class EchoTool
103103

104104
#### Host name validation
105105

106-
If you need to limit which host names the server will respond to, use ASP.NET Core host filtering. Set `AllowedHosts` in configuration, commonly in `appsettings.Development.json` for local loopback development and in environment-specific configuration for deployed hosts. See [Host filtering with ASP.NET Core Kestrel web server | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/host-filtering).
106+
For local HTTP servers, keep the set of accepted host names limited to loopback values. This helps protect against DNS rebinding, where a browser reaches a local server through an attacker-controlled DNS name while sending that DNS name in the HTTP `Host` header. ASP.NET Core's Kestrel server doesn't validate `Host` headers by default, so configure `AllowedHosts` with known host names rather than `"*"`.
107107

108-
#### Request origin validation
108+
For production servers, configure the exact public host names for the deployment, and validate the host name at the proxy or load balancer when one is responsible for forwarding client requests. This also avoids reflecting untrusted host names through ASP.NET Core features such as absolute URL generation. See [Host filtering with ASP.NET Core Kestrel web server | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/host-filtering) and [URL generation concepts | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/routing#url-generation-concepts).
109109

110-
If you need to limit which browser origins can call the MCP endpoint, use a restrictive ASP.NET Core CORS policy. This is ASP.NET Core's built-in mechanism for validating the browser `Origin` header on cross-origin requests. See [Enable Cross-Origin Requests (CORS) in ASP.NET Core | Microsoft Learn](https://learn.microsoft.com/aspnet/core/security/cors).
110+
#### Browser cross-origin access
111+
112+
**Only** enable CORS if you intentionally want browser-based cross-origin access to this server.
113+
114+
CORS is not a substitute for host name validation. When browser-based cross-origin access is required, limit which browser origins can call the MCP endpoint by using the most restrictive ASP.NET Core CORS policy possible. See [Enable Cross-Origin Requests (CORS) in ASP.NET Core | Microsoft Learn](https://learn.microsoft.com/aspnet/core/security/cors).
111115

112116
For the full HTTP security examples, including `AllowedHosts` and restrictive CORS on `MapMcp`, see [Streamable HTTP transport](transports/transports.md#request-origin-validation).
113117

docs/concepts/transports/transports.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ By default, the HTTP transport uses **stateful sessions** — the server assigns
135135

136136
#### Host name validation
137137

138-
If you need to limit which host names the server will respond to, use ASP.NET Core host filtering. Configure `AllowedHosts` in app configuration, such as `appsettings.Development.json` for local loopback values and environment-specific configuration for deployed hosts. See [Host filtering with ASP.NET Core Kestrel web server | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/host-filtering).
138+
For local HTTP servers, keep the set of accepted host names limited to loopback values. This helps protect against DNS rebinding, where a browser reaches a local server through an attacker-controlled DNS name while sending that DNS name in the HTTP `Host` header. ASP.NET Core's Kestrel server doesn't validate `Host` headers by default, so configure `AllowedHosts` with known host names rather than `"*"`. This also avoids reflecting untrusted host names through ASP.NET Core features such as absolute URL generation. See [Host filtering with ASP.NET Core Kestrel web server | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/host-filtering) and [URL generation concepts | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/routing#url-generation-concepts).
139139

140140
```json
141141
// appsettings.Development.json
@@ -144,11 +144,15 @@ If you need to limit which host names the server will respond to, use ASP.NET Co
144144
}
145145
```
146146

147-
For local development, we recommend keeping `AllowedHosts` limited to loopback values such as `localhost;127.0.0.1;[::1]`.
147+
For production servers, configure `AllowedHosts` to the exact public host names for the deployment. If Kestrel is behind a reverse proxy or load balancer, validate the host name at the layer that receives or forwards the client `Host` header. ASP.NET Core's Host Filtering Middleware is appropriate when Kestrel is public-facing or the `Host` header is directly forwarded; Forwarded Headers Middleware has its own `AllowedHosts` option for cases where the proxy doesn't preserve the original `Host` header. See [Host filtering with ASP.NET Core Kestrel web server | Microsoft Learn](https://learn.microsoft.com/aspnet/core/fundamentals/servers/kestrel/host-filtering) and [Configure ASP.NET Core to work with proxy servers and load balancers | Microsoft Learn](https://learn.microsoft.com/aspnet/core/host-and-deploy/proxy-load-balancer).
148148

149-
#### Request origin validation
149+
If you intentionally expose the server through another host name, such as a tunnel, container host, reverse proxy, or deployed domain, add that exact host name to `AllowedHosts` instead of using `"*"`.
150150

151-
If you need to limit which browser origins can call the MCP endpoint, use a restrictive ASP.NET Core CORS policy. This is ASP.NET Core's built-in mechanism for validating the browser `Origin` header on cross-origin requests. See [Enable Cross-Origin Requests (CORS) in ASP.NET Core | Microsoft Learn](https://learn.microsoft.com/aspnet/core/security/cors). Only enable CORS if you intentionally want browser-based cross-origin access to this server.
151+
#### Browser cross-origin access
152+
153+
**Only** enable CORS if you intentionally want browser-based cross-origin access to this server.
154+
155+
CORS is not a substitute for host name validation. When browser-based cross-origin access is required, limit which browser origins can call the MCP endpoint by using the most restrictive ASP.NET Core CORS policy possible. See [Enable Cross-Origin Requests (CORS) in ASP.NET Core | Microsoft Learn](https://learn.microsoft.com/aspnet/core/security/cors).
152156

153157
For a **stateless** browser client, a narrowly scoped CORS policy usually only needs the headers the browser would otherwise preflight: `Content-Type` for JSON, `Authorization` when the endpoint is protected, and `MCP-Protocol-Version`. If you enable sessions or resumability, also allow `Mcp-Session-Id` and `Last-Event-ID`, and expose `Mcp-Session-Id` on responses so browser code can read it. `Accept` normally doesn't need to be listed because browsers can already send it without extra CORS configuration.
154158

@@ -174,8 +178,9 @@ builder.Services.AddCors(options =>
174178
options.AddPolicy("McpBrowserClient", policy =>
175179
{
176180
policy.WithOrigins(allowedOrigins)
177-
.WithMethods("POST")
178-
.WithHeaders("Content-Type", "Authorization", "MCP-Protocol-Version")
181+
// Add GET for standalone/resumable SSE streams and DELETE for stateful session termination.
182+
.WithMethods("POST", "GET", "DELETE")
183+
.WithHeaders("Content-Type", "Authorization", "MCP-Protocol-Version", "Mcp-Session-Id")
179184
.WithExposedHeaders("Mcp-Session-Id");
180185
});
181186
});

0 commit comments

Comments
 (0)