fix(security): add API key authentication to MCP HTTP server - #1932
Open
PiedPiper911 wants to merge 1 commit into
Open
fix(security): add API key authentication to MCP HTTP server#1932PiedPiper911 wants to merge 1 commit into
PiedPiper911 wants to merge 1 commit into
Conversation
Add built-in Bearer token authentication to the mcp-http-server Express server to address unauthenticated access to all MCP tools (bytedance#1931). - Support API key via `apiKey` param or `MCP_API_KEY` env var - Reject requests without a valid `Authorization: Bearer <token>` (401) - Use timing-safe comparison to avoid timing side-channels - Backward compatible: when no key is configured, the server keeps its previous behavior but logs a clear security warning (extra warning when binding to a non-localhost address) - Add tests covering auth enforcement and backward compatibility
✅ Deploy Preview for agent-tars-docs canceled.
|
✅ Deploy Preview for tarko canceled.
|
Author
|
Friendly ping - this PR adds API key auth to the MCP HTTP server endpoint (currently open without authentication). Happy to adjust the approach if the team prefers a different solution. Thanks for your time! |
Author
|
Hi! Friendly follow-up on this PR — it has been open for over a week. Happy to make any adjustments needed to get this merged. Let me know if there are any concerns with the approach. Thanks! |
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
This PR adds built-in API key (Bearer token) authentication to the
mcp-http-serverpackage, addressing the unauthenticated-access vulnerability reported in #1931.Previously, the Express server exposed every MCP endpoint (SSE, message, streamable HTTP) without any built-in authentication. When deployed with
host: '0.0.0.0'(common for containerized deployments), any network client could access all registered MCP tools — browser automation, file operations, etc. — without credentials.Fixes #1931
Security Impact
initializeand gain full access to all MCP tools when the server was bound to a non-localhost address.Authorization: Bearer <token>header. Requests without a valid token are rejected with401 Unauthorizedbefore reaching any MCP endpoint.crypto.timingSafeEqualto avoid timing side-channel attacks.WWW-Authenticate: Bearerheader is returned on401responses, following RFC 6750.Implementation Details
apiKeyparameter tostartSseAndStreamableHttpMcpServer.apiKeyparam first, then from theMCP_API_KEYenvironment variable.createApiKeyAuthMiddleware, an Express middleware registered before custom middlewares and all MCP routes. It:Authorizationheader →401with a JSON-RPC error body.401with a JSON-RPC error body.next()only when the token matches (constant-time comparison).Backward Compatibility
This change is fully backward compatible:
apiKeyparam norMCP_API_KEYenv var), the server keeps its previous unauthenticated behavior — no requests are blocked.host: '0.0.0.0'), so operators are aware of the exposure.apiKeyis purely additive.Files Changed
packages/agent-infra/mcp-http-server/src/startServer.ts— addapiKeyoption, Bearer token auth middleware, timing-safe comparison, and security warnings.packages/agent-infra/mcp-http-server/tests/startServer-auth.test.ts— new tests covering: rejection without a token (401), rejection with an invalid token (401), acceptance with a valid token, SSE endpoint protection, and backward-compatible behavior when no key is set.Usage
Set the
MCP_API_KEYenvironment variable before starting the server:Or pass it programmatically:
Clients must then include the token on every request:
Requests without a valid token receive:
{ "jsonrpc": "2.0", "error": { "code": -32600, "message": "Unauthorized: missing Authorization header. Expected \"Authorization: Bearer <MCP_API_KEY>\"." }, "id": null }Happy to adjust the approach (e.g. make auth mandatory when binding to non-localhost, or add HTTPS/TLS support) based on maintainer preference. Thanks for reviewing!