← All fixes

Fix it

No rate limiting on login (brute force), how to fix it

Medium severityCWE-307 (Improper Restriction of Excessive Authentication Attempts)
We scanned nearly 2,000 AI-built apps and 1 in 8 shipped a high-severity flaw. Is this one in yours?Scan free →

If your login, password-reset, or verification endpoint accepts unlimited attempts, an attacker can try thousands of passwords or codes per minute until one works. Rate limiting caps how many attempts an IP or account can make in a window, which turns an easy brute-force into an impractical one. Add it to every authentication route.

Why it's a problem

Without a limit, a six-digit reset code has only a million possibilities and can be exhausted quickly, and weak passwords fall to a dictionary in seconds. The endpoint works normally for real users, so the missing limit is invisible until someone points an automated tool at it.

The pattern

// unlimited attempts
app.post("/login", async (req, res) => {
  const ok = await checkPassword(req.body);
  res.json({ ok });
});

The fix

import rateLimit from "express-rate-limit";

const loginLimiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 min
  max: 10,                   // per IP
});

app.post("/login", loginLimiter, async (req, res) => {
  const ok = await checkPassword(req.body);
  res.json({ ok });
});

Why AI tools write this

Generating a working login route answers the request as asked; rate limiting was not part of it. The endpoint authenticates correctly in testing, so the absence of a limit does not surface until it is attacked.

The quick fix

  • Add rate limiting to login, password-reset, and verification endpoints.
  • Limit by IP and, where possible, by account.
  • Consider a short lockout or increasing delay after repeated failures.

Common questions

Should I rate limit by IP or by account?

Both, where possible. IP-based limiting is easy to implement but can be bypassed with rotating proxies. Account-based limiting or a lockout after N failures protects accounts regardless of the IP used.

What is a reasonable rate limit for a login endpoint?

Five to ten attempts per IP per 15-minute window is a common starting point. After that, a short lockout or a CAPTCHA. Adjust based on your expected legitimate traffic patterns.

Does rate limiting alone protect against credential stuffing?

Not fully. Credential stuffing uses many IPs, so per-IP limits slow but do not stop it. Add anomaly detection, breach password checking, and consider a CAPTCHA for high-failure-rate IPs.

Want to know if this pattern is already in something you shipped? Scan your live app or a public repo free, no account needed.

Scan my app →

Catch this automatically: scan your GitHub repo · website vulnerability scanner · review every pull request · SAST for AI code · OWASP Top 10 for AI code

No Rate Limiting on Auth Routes (Brute Force), How to Fix It | Prbl