fix: use dedicated header with timing-safe comparison for rate-limit bypass token (CWE-863) - #246
Open
andesyteoss wants to merge 1 commit into
Open
Conversation
…bypass (CWE-863) Replace User-Agent prefix matching (startsWith) with a dedicated X-Bypass-Token header verified via crypto.timingSafeEqual. The old mechanism checked if the User-Agent started with a configured prefix (RATE_LIMIT_BYPASS env var). This is insecure because: 1. User-Agent is a publicly visible, client-controlled header that offers no secrecy guarantees. 2. startsWith allows any suffix, so partial knowledge of the prefix (or a short/guessable value) is enough to bypass rate limits. 3. No timing-safe comparison was used, enabling timing side-channels. The fix: - Reads the token from X-Bypass-Token header (not User-Agent) - Requires exact match via timingSafeEqual (constant-time) - Supports RATE_LIMIT_BYPASS_TOKEN env var (falls back to RATE_LIMIT_BYPASS for backwards compatibility during migration)
|
@sebastiondev is attempting to deploy a commit to the Exa Team on Vercel. A member of the Team first needs to authorize it. |
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.
Vulnerability Summary
CWE: CWE-863 — Incorrect Authorization
Severity: High
File:
api/mcp.tsAffected code path:
handleRequest→ bypass-token check (line ~336)Data Flow
https://mcp.exa.ai/mcp), exported asGET,POST, andDELETE.User-Agentheader (attacker-controlled) is read and compared against theRATE_LIMIT_BYPASSenvironment variable usinguserAgent.startsWith(bypassPrefix).EXA_API_KEY_BYPASSis configured, the request is granted access to the dedicated bypass API key — effectively free, billed-to-operator API usage.Three Distinct Flaws
startsWithprefix match — any string beginning with the secret token passes the checkUser-Agentheader —User-Agentis logged by virtually all infrastructure (CDN, Vercel function logs, WAF, access logs)Exploit Sketch
Preconditions
RATE_LIMIT_BYPASSandEXA_API_KEY_BYPASSenvironment variables must be configured (they are on the production deployment atmcp.exa.ai).RATE_LIMIT_BYPASSvalue — but since it is transmitted inUser-Agent, it is logged by virtually all web infrastructure, making it discoverable by anyone with log access.Fix Description
Single file changed:
api/mcp.ts(+25 / −5 lines)User-Agentto dedicatedX-Bypass-TokenheaderX-Bypass-Tokenis not logged by default in CDN/server access logs, preventing secret leakagestartsWithwith exact-match comparisontimingSafeEqualfromnode:cryptoRATE_LIMIT_BYPASS_TOKENenv var with fallback toRATE_LIMIT_BYPASSWhat the fix does NOT change
X-Bypass-Tokeninstead ofUser-Agent.Test Results
Verification of the fix logic
X-Bypass-Token— bypass is granted (correct behavior)User-Agentwith old token — bypass is no longer granted (migration to new header)RATE_LIMIT_BYPASS_TOKENtakes precedence over legacyRATE_LIMIT_BYPASSwhen both are settimingSafeEquallength check — mismatched lengths returnfalsewithout timing leakDisprove Analysis
We systematically attempted to disprove this finding:
startsWithcheck IS the auth mechanism — and it is the one being fixed.vercel.json). Public internet. No reverse proxy filtering.handleRequestis directly exported asGET,POST,DELETE. Any HTTP request reaches the vulnerable code.User-Agentor any header before the bypass check.SECURITY.mdexists.startsWith-based auth checks remain in the codebase after this fix.EXA_API_KEY_BYPASS— this is it.Mitigations Found
RATE_LIMIT_BYPASSandEXA_API_KEY_BYPASSmust be configured (if the operator does not set these, there is no vulnerability).Verdict
CONFIRMED_VALID — High confidence. The vulnerability is real and exploitable on the internet-facing production deployment. The fix addresses all three identified flaws and is minimal/targeted.