fix(security): require Authorization header for streamable HTTP server [DEVX-806]#46
Open
geethanga-ct wants to merge 5 commits into
Open
fix(security): require Authorization header for streamable HTTP server [DEVX-806]#46geethanga-ct wants to merge 5 commits into
geethanga-ct wants to merge 5 commits into
Conversation
The remote/streamable HTTP MCP server no longer falls back to the startup/system credentials when an incoming request omits the Authorization header. Previously an unauthenticated network caller could be served using the server's own configured token (Cure53 COM-15-004). - Reject requests to /mcp with a missing/malformed Authorization header with 401, before any commercetools call is made - Forward the caller's bearer token directly to the commercetools API (auth_token flow); also fixes a latent bug where a client_credentials startup silently ignored the per-request header token - Stop mutating the shared authConfig; build an isolated per-request auth config instead - Add enforceAuthHeader option (defaults true) so embedders that handle auth via an injected server factory can opt out DEVX-806 / COM-15-004 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: fe214b7 The changes in this PR will be included in the next version bump. This PR includes changesets to release 2 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
ajimae
previously approved these changes
Jun 5, 2026
…EADER env Wire the streamable server's enforceAuthHeader opt-out through the CLI entry point so standalone/containerized deployments can configure it. - Parse --enforceAuthHeader and ENFORCE_AUTH_HEADER (default true, secure by default; only an explicit "false" disables enforcement) - Pass the resolved value into CommercetoolsCommerceAgentStreamable - Log a startup warning when enforcement is disabled in remote mode, since unauthenticated requests then fall back to startup credentials - Document the env var as a transitional migration escape hatch for existing deployments that cannot add the Authorization header yet DEVX-806 / COM-15-004 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This reverts commit 8577d79. Per review feedback, the enforceAuthHeader opt-out should not be exposed as an operator-facing CLI/env toggle on the published binary: disabling it re-opens the exact fallback-to-startup-credentials behavior this change fixes, and operators are the most likely to misuse it. The legitimate "manage auth yourself" case is already served by the SDK constructor option on CommercetoolsCommerceAgentStreamable (default true), which is retained. This keeps the standalone server secure with no off-switch. DEVX-806 / COM-15-004 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Requiring an Authorization header on every remote /mcp request is a behavior-breaking change for existing remote clients, so release both @commercetools/commerce-agent and @commercetools/commerce-mcp as major (2.0.0 -> 3.0.0). Add an explicit BREAKING callout to the changelog entry. DEVX-806 / COM-15-004 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the insecure auth fallback reported in DEVX-806 / Cure53 COM-15-004 (High). When the MCP server runs in remote/streamable HTTP mode (
--remote=true), the/mcphandler treated theAuthorizationheader as optional and fell back to the server's startup/system credentials. An unauthenticated network caller could therefore be served with the same privileges as the configured token.This makes the streamable HTTP server a strict pass-through: every request must present its own commercetools bearer token, which is forwarded directly to the commercetools API. The startup credentials are no longer used to serve network requests.
What changed
streamable.tsextractBearerToken()— structural validation ofAuthorization: Bearer <non-empty-token>(case-insensitive scheme)./mcpreturns401 Unauthorizedimmediately when the header is missing/malformed, before any commercetools call — no fallback to config credentials.type: 'auth_token', so the caller's token is the one forwarded to the CT API. This also fixes a latent bug where a server started withclient_credentialssilently ignored the per-request header token.this.authConfig(one request's token could leak into others);getServer()now accepts a per-requestauthConfig, threaded through stateless and stateful paths./mcpgets the same auth guard.configuration.ts— added optionalenforceAuthHeader?: boolean(defaultstrue) toIStreamServerOptions, so SDK embedders who handle auth via an injectedserverfactory can opt out.README.md— documented the mandatoryAuthorization: Bearer <token>requirement, the pass-through behavior, and theenforceAuthHeaderopt-out.minorbump for@commercetools/commerce-agentand@commercetools/commerce-mcp.Migration
Clients connecting to a remote server (e.g. via
mcp-remote) must now send anAuthorization: Bearer <commercetools-access-token>header on every request. stdio mode is unaffected.Testing
streamablesuite: 28/28 pass (new cases: 401 on missing/malformed header, forwarded-token,enforceAuthHeader: falseopt-out, GET auth).End-to-end (reproduces the exploit)
🤖 Generated with Claude Code