Authentication Bugs

Login Rate Limit Not Enforced

The login endpoint POST /api/auth/login accepts an unlimited number of credential attempts per client with no rate limiting, no account lockout, and no CAPTCHA. An attacker can automate thousands of password guesses per minute against any account without triggering any throttle or block.

HighBeginnerSecurity testingAPI testingManual testing

// UNDERSTAND

// Symptoms

  • Sending 200 consecutive POST /api/auth/login requests with incorrect passwords returns 401 every time โ€” no 429 is ever returned
  • There is no account lockout or temporary block after N failed attempts
  • The response time remains consistent across all attempts, indicating no backoff or throttle
  • Server logs show thousands of failed login attempts from the same IP with no automated response

// Root Cause

  • No rate-limiting middleware (e.g. a per-IP or per-username request counter with a cooldown) is applied to the login endpoint โ€” every request is processed regardless of how many the same client has sent recently
  • Account lockout logic is absent: the application does not track failed attempts per username or IP and does not temporarily block further attempts after a configurable threshold of failures

// Where It Appears

  • Login and authentication endpoints in any web application
  • Admin login pages that are exposed to the public internet
  • API authentication endpoints consumed by mobile or third-party clients
  • Applications using username+password auth without MFA as the only factor

// REPRODUCE & TEST

// How to Reproduce

  1. 01Send POST /api/auth/login with body { "email": "victim@example.com", "password": "WrongPass1" } and confirm the response is 401 Unauthorized
  2. 02Send the identical POST /api/auth/login request 200 times in rapid succession โ€” use a script or Postman's collection runner
  3. 03Record the HTTP status code of every response
  4. 04If all 200 responses are 401 (none are 429 Too Many Requests), rate limiting is absent

// Test Data Needed

  • A valid test account email address (e.g. victim@example.com) โ€” the password does not matter since the test uses wrong credentials intentionally
  • A way to send many requests in rapid succession (Postman collection runner, curl loop, or a short script)

// Manual Testing Ideas

  • Submit the login form with an incorrect password 20 times in quick succession and observe whether the UI or API imposes any delay, lockout, or CAPTCHA
  • Check whether the same account shows a lockout warning in the UI after repeated failures
  • Test both the UI form and the raw API endpoint โ€” some applications add rate limiting only at the web layer, leaving the API unprotected
  • Try alternating between two IP addresses (e.g. using a VPN) to check whether the limit is per-IP or per-account
  • Check the response headers for RateLimit-Remaining, Retry-After, or X-RateLimit-* headers that would indicate a limit is configured

// API Testing Ideas

  • Send POST /api/auth/login with an incorrect password; confirm the response is 401
  • Send the same request 50 times without any delay
  • Assert that at least one response in the 50 is 429 Too Many Requests โ€” if none are, the rate limit is absent
  • If a 429 is received, note the Retry-After header value and confirm that re-sending after that interval succeeds or returns 401 (not another 429)
  • Repeat the test with different email addresses to confirm the rate limit is per-IP or per-account, not per email string

// Automation Idea

Send POST /api/auth/login with an incorrect password 50 times in a tight loop with no delay. Assert that at least one response has HTTP status 429 Too Many Requests. If all 50 return 401, fail the test and report that no rate limiting is in effect. Optionally assert that the 429 response includes a Retry-After header.

// Expected Result

After a configurable number of failed login attempts from the same client (typically 5โ€“10), the login endpoint returns 429 Too Many Requests and optionally locks the account temporarily.

// Actual Result (Example)

All 200 POST /api/auth/login requests with an incorrect password return 401 Unauthorized. No 429 is returned at any point, confirming there is no rate limit or account lockout on the login endpoint.

// REPORT IT

Example Bug Report

Title
Login endpoint has no rate limiting โ€” 200 failed attempts all return 401 with no throttle
Severity
High
Environment
Staging environment Postman collection runner Endpoint: POST /api/auth/login
Steps to Reproduce
  1. 01Open Postman and create a POST request to /api/auth/login with body { "email": "victim@example.com", "password": "WrongPass1" }
  2. 02Use the Collection Runner to send the request 200 times with no delay between iterations
  3. 03Record the HTTP status code of each response
Expected Result
The endpoint returns 429 Too Many Requests after a threshold of failed attempts.
Actual Result
All 200 responses are 401 Unauthorized. No 429 is returned at any point. The login endpoint accepts unlimited credential-guessing attempts with no throttle.
Impact
An attacker can automate a brute-force attack against any known email address at thousands of guesses per minute. Accounts with weak passwords are vulnerable to takeover with no time or rate constraint.

// RELATED