diff --git a/README.md b/README.md index 36e9f3dee..8bd387457 100644 --- a/README.md +++ b/README.md @@ -237,6 +237,8 @@ To prevent DNS rebinding attacks, the MCP Inspector validates the `Origin` heade ALLOWED_ORIGINS=http://localhost:6274,http://localhost:8000 npm start ``` +Validation fails closed: a request whose `Origin` header is **missing** is rejected with `403` just like one whose `Origin` is not on the allow list. Browsers always send `Origin` on the cross-origin requests the Inspector client makes, so normal use is unaffected — but a non-browser client (curl, Postman, a CI script) driving the proxy API directly must send the header explicitly, for example `-H "Origin: http://localhost:6274"`. The unauthenticated `/health` endpoint is not origin-checked, so container health checks are unaffected. + ### Configuration The MCP Inspector supports the following configuration settings. To change them, click on the `Configuration` button in the MCP Inspector UI: diff --git a/server/src/index.ts b/server/src/index.ts index 4d1fffa29..bdbc88916 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -203,12 +203,18 @@ const originValidationMiddleware = ( defaultOrigin, ]; - if (origin && !allowedOrigins.includes(origin)) { - console.error(`Invalid origin: ${origin}`); + if (!origin || !allowedOrigins.includes(origin)) { + // Distinguish the two rejection causes so operators can tell a genuine + // cross-origin attempt from a non-browser client that sent no Origin at all. + console.error( + origin + ? `Invalid origin: ${origin}` + : "Missing origin header - request rejected", + ); res.status(403).json({ error: "Forbidden - invalid origin", message: - "Request blocked to prevent DNS rebinding attacks. Configure allowed origins via environment variable.", + "Request blocked to prevent DNS rebinding attacks. Requests must send an Origin header matching an allowed origin; configure allowed origins via the ALLOWED_ORIGINS environment variable.", }); return; }