Six digits, endless guesses
Your app signs people in with a 6-digit code sent by email. A security researcher writes: 'I got into your demo account without access to its inbox.'
This answers: Can someone guess a 6-digit login code? No coding needed. 3 quick decisions.
- Who is signed in
Step 1 of 3
This is the code that checks the 6-digit code. How did they get in?
export async function POST(req: Request) { const { email, code } = await req.json(); const saved = await db.loginCodes.find({ email }); if (saved && saved.code === code) { return startSession(email); } return Response.json({ error: "Wrong code" }, { status: 401 });}Can someone guess a 6-digit login code?
Yes, if wrong guesses aren't limited. Six digits is one million possibilities, which a script can try in hours. Limit wrong attempts per code, for example to five, then cancel it; expire codes within minutes; make each code single use; and the endpoint that checks codes, not only the one that sends them.
Breaks at Your server: Unlimited guesses at the code check
Why AI tools write this bug
Hand-built login code flows from AI tools often compare the code and stop there, or add rate limiting to sending codes while leaving the check open.
How to fix it
- Limit wrong attempts per code and cancel it after the limit.
- Expire codes after a few minutes.
- Make codes single use.
- Prefer your auth provider's built-in email codes.
Check your own app
Paste this into Lovable, Cursor or Claude Code:
Without changing anything, find every place this project checks a login code, magic link, password or reset token. For each, tell me whether wrong attempts are limited, whether the code or token expires and after how long, and whether it can be used more than once.
Common questions
- Does Supabase Auth limit code guesses?
- Hosted auth providers include protections like expiry and rate limits for their own email codes. The risk is mostly in custom code that checks its own codes.