From ea34c17f4e004350e5e08faab44076de069317a0 Mon Sep 17 00:00:00 2001 From: Sebastion Date: Fri, 27 Mar 2026 01:35:20 +0000 Subject: [PATCH 1/2] fix: reject requests with missing Origin header in origin validation middleware The originValidationMiddleware only checked whether a present Origin header matched the allowlist. When the Origin header was absent (as with curl, scripts, or any non-browser HTTP client), the check was skipped entirely, allowing unauthenticated access to all protected endpoints. Changed the condition from `if (origin && !allowedOrigins.includes(origin))` to `if (!origin || !allowedOrigins.includes(origin))` so that requests without an Origin header are also rejected with 403 Forbidden. This prevents non-browser CSRF and unauthorized access from tools that do not send an Origin header, which is especially critical when combined with DANGEROUSLY_OMIT_AUTH=true. CWE-346: Origin Validation Error --- server/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/index.ts b/server/src/index.ts index 4d1fffa29..4570d512f 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -203,7 +203,7 @@ const originValidationMiddleware = ( defaultOrigin, ]; - if (origin && !allowedOrigins.includes(origin)) { + if (!origin || !allowedOrigins.includes(origin)) { console.error(`Invalid origin: ${origin}`); res.status(403).json({ error: "Forbidden - invalid origin", From 5bb03428dd65a65ab62ab78159b7e1c6909c0c36 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Wed, 19 Aug 2026 16:57:31 -0400 Subject: [PATCH 2/2] fix: distinguish missing vs invalid Origin, and document the fail-closed check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the CWE-346 fix, addressing review feedback on PR #1161. The middleware now fails closed on a missing Origin header, but both rejection causes logged the same line — a missing header printed "Invalid origin: undefined", which reads as a malformed value rather than an absent one. Log the two cases distinctly so an operator can tell a genuine cross-origin attempt from a non-browser client that sent no Origin at all. Behavior is unchanged: both still return 403. Also widen the 403 response message and document the new posture in the README. Browsers always send Origin on the cross-origin requests the Inspector client makes, so normal use is unaffected, but a non-browser client driving the proxy API directly (curl, Postman, CI) must now send the header explicitly. That requirement was previously undocumented. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01JTHVxSu8AUgHRLvo1ntZ8H Signed-off-by: cliffhall --- README.md | 2 ++ server/src/index.ts | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) 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 4570d512f..bdbc88916 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -204,11 +204,17 @@ const originValidationMiddleware = ( ]; if (!origin || !allowedOrigins.includes(origin)) { - console.error(`Invalid origin: ${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; }