Login routes with no rate limit
AI scaffolds often ship bcrypt and JWT sign-in with no throttle in front of them. Unlimited attempts mean brute-force and sign-up spam can run as fast as the network allows.
What can go wrong
If the login handler runs a bcrypt compare or signs a JWT with nothing counting attempts before it, an attacker can try passwords at wire speed, spray sign-ups, or hammer the forgot-password flow to spam your email quota. Paired with distinct login error messages, the same loop first harvests which addresses exist, then guesses their passwords.
How to check yours
Seatbelt flags this automatically (partial). Repo read puts a rate-limit line on the agent checklist when auth-shaped routes exist with no project-wide limiter in sight; URL read soft-flags auth endpoints on the wire with no throttle signals. A checklist line means confirm it yourself, not that a limiter is missing for certain.
Honest holes: limits enforced at the edge (Cloudflare rules, a WAF, platform middleware outside the repo) are invisible to a static read and will look missing when they are not.
Ask your agent: "Open every login, register, and forgot-password route. Does a rate limiter run before the credential check in each one?"
Manual check: open each auth handler (or app/api/auth/), and search the file and middleware.ts for rateLimit, @upstash/ratelimit, express-rate-limit, or an edge limiter. If bcrypt compare or JWT sign runs with no throttle before it, the route is open to the loop.
Fix direction
Put a limiter in front of credential checks on login, register, and forgot-password, whether in the handler, shared middleware, or an edge rule.
Paste into your agent: "Add rate limiting before credential checks on every auth route: login, register, and forgot-password. Use Upstash Ratelimit, express-rate-limit, or an edge rule, and return 429 when the limit is hit."