No rate limiting on sensitive routes
What it looks like
// app/api/login/route.ts
export async function POST(req: Request) {
const { email, password } = await req.json();
const user = await signIn(email, password);
return Response.json(user ?? { error: "wrong password" });
}
// no limit on attempts per address, per account or per minuteWhat happens
A script can try thousands of passwords against your login form, hammer a form that sends emails or calls a paid API, or knock the app over, and the bill lands on you.
Where it shows up
Descriptive, not a verdict: builders and stacks whose defaults make this reachable, or that a public incident names. Each hub states the tool's own security features.
Check it yourself
Uses your builder's dashboard and your browser. No tools to install.
- Open your app's login or "forgot password" page in Chrome, press F12 and choose the Network tab.
- Submit the form with a wrong password once and note the request that appears (for example
login,tokenorrecover). - Right-click that request, choose "Replay XHR", and repeat it quickly twenty or thirty times.
- Read the Status column for the replayed requests. If you host on Vercel, also open the project's Firewall tab and check whether any rate limit rule exists.
Bad result: every replay returns the same status as the first attempt and none returns HTTP 429 (too many requests) or a message about too many attempts, and no firewall rule covers the route.
What we check
We run a scripted burst against login, password reset, signup, contact and any endpoint that sends email or calls a paid API, from one address and from many. We record where the app slows, blocks or keeps answering, and the report lists each unprotected endpoint with what a burst against it would cost or expose.
Fix direction
Add a rate limit (a cap on requests per address or account per minute) in front of the sensitive routes and return HTTP 429 when it is hit. A platform rule such as a Vercel Firewall rate-limit rule or a small counter in your API code both work. Check whether your auth provider already limits its own sign-in endpoints, and cover the routes you wrote yourself.
Mechanism documented in: Vercel: WAF Rate Limiting (verified 2026-09-21); OWASP Denial of Service Cheat Sheet (verified 2026-09-21).
Covered by
Pre-launch check ($490, 48 hours) and Full audit ($1,900, 5 business days)
Both include a re-check after your fixes.
Related patterns
- Retries with no pause and no capReliabilityMedium
One outage turns into a flood of retries from every open browser tab, which keeps the service down longer, runs up usage bills and can submit the same order or payment twice.
- No spend cap on model callsAI featuresHigh
A script can hit the route in a loop overnight and the bill lands on your card, or the provider pauses your account mid-day when its own cap trips and every user sees errors.
- Unbounded input length to the modelAI featuresMedium
One oversized paste costs as much as thousands of normal requests, and a burst of them uses up your provider rate limit so real users see errors.
- Default admin credentials left in placeLogin and permissionsCritical
Anyone who reads the code or guesses a common placeholder can sign in as the administrator.
Questions
does my app need rate limiting
Yes, on any route that checks a password, sends an email or text, or calls something you pay for per request. Rate limiting is a cap on how many requests one source can make in a time window. It turns a password-guessing script or a runaway client into a handful of blocked requests instead of a bill or a takeover. Public read-only pages matter less.
how to add rate limiting to a nextjs api route on vercel
Vercel's Firewall lets you add a rate limit rule from the dashboard: choose the path, a time window and a request limit, and the default action returns HTTP 429. The docs note counters are tracked per region and that the Hobby plan allows one rate limit rule per project. Inside the app, a small counter keyed by address or user in a store such as Redis does the same job for routes the firewall does not cover.
how do i test if my login has rate limiting
Submit a wrong password, then replay that request from the Network tab in developer tools twenty or thirty times in a row. With a limit in place, replays start returning HTTP 429 or a message about too many attempts. If every replay gets the same answer as the first, nothing is counting.
Back to the catalogue, or run the self-check for your stack.