hyperdxio / hyperdxio/hyperdx

Rate limiting: the API-key limiter is bypassable via the Authorization header, and /login/password has none

Open
#2,775 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug external
Dominant language
TypeScript
Stars
9.9k
Forks
471
Avg merge
2d 4h
Merged PRs (30d)
117

Description

1. The v2/MCP limiter buckets on the raw Authorization header.

rateLimiterKeyGenerator (packages/api/src/utils/rateLimiter.ts:5) keys on req.headers.authorization verbatim, but validateUserAccessKey (packages/api/src/middleware/auth.ts:89) parses it as authHeader.split('Bearer ')[1], which accepts any prefix. One credential, unlimited bucket spellings. Jest harness, real middleware pair, max=3, 8 requests:

Bearer <key>      -> 200,200,200,429,429,429,429,429
n<i> Bearer <key> -> 200 x8, same authenticated user

That defeats the 100 req/min cap on /api/v2/* and the 600 req/min on /mcp — and /mcp is where LLM agents hammer, the traffic that cap bounds. Needs a valid API key first, so DoS/cost only: no confidentiality or integrity impact.

2. POST /login/password has no limiter. Locally (API + a mongo container, our clone): 60 wrong-password attempts from one client in 1.9s, no 429, no lockout, account still usable after. The password policy is strong (12 chars, mixed case, digit, symbol), so not a break by itself; the point is asymmetry — utils/rateLimiter.ts covers /api/v2/* and /mcp, but not the one endpoint facing anonymous traffic.

Direction, not a design: key the bucket on the token the auth middleware actually parses, hashed rather than verbatim (the raw bearer secret is currently the limiter's in-memory map key), and apply a limiter to the login route. Happy to implement whichever shape you want; steer me first.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with packages/api/src/utils/rateLimiter.ts and packages/api/src/middleware/auth.ts, then trace the POST /login/password route and the existing Jest harness. Confirm that equivalent bearer credentials share a bucket and that anonymous password attempts are rate-limited, with tests covering both behaviors.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, authentication, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
54/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.