Stop 9 of 42 · The ID Desk · Password reset flaws

The “I lost my key” process that opens the door for anyone

When a customer loses their key, the bank mails a one-time reset slip to the address on file. But this clerk is sloppy. Mallory says “Alice lost her key”, and the clerk mails the slip to Alice and also hands a copy to Mallory across the counter.

Severity Medium to CriticalCategory Auth WeaknessThe ID DeskSources checked 25 Oct 2026

Watch it happen

Play it as

Mallory asks for a reset for Alice. The clerk puts the reset slip in the reply to Mallory, who uses it to set a new PIN.

Arrival

Mallory walks up to the bank. She does not know Alice’s PIN, and she does not need to.

1 / 5

In bank terms and app terms

In the bankIn your app
“I lost my key” processThe forgot-password flow
Reset slipThe reset token or link
Handing the slip across the counterReturning the token in the API response instead of only emailing it
Alice’s mailbox on fileThe email address that owns the account

Are you exposed?

You might be exposed if…
  • Your forgot-password endpoint returns a token, link or “user found” flag in its JSON response.
  • Reset tokens are short, numeric, sequential or never expire, and can be used more than once.
  • Your reset form answers differently for emails that exist and emails that do not.
What to do about it
  1. Send the token only by email, and respond with the same message for every request.
  2. Generate long random tokens (use your auth provider’s built-in reset), expire them in minutes, and make them single-use.
  3. Rate limit reset requests per email and per IP so nobody can flood inboxes or guess tokens.

Track these in your to-do list →

It has happened to real companies

Real-world breaches

Snapchat (2013–14) — Snapchat's Find Friends feature let phone numbers be matched to usernames, and Snapchat itself warned that attackers could upload huge sets of numbers, "like every number in an area code". At the start of 2014 a group published about 4.6 million usernames matched to phone numbers (last two digits hidden), after the security firm Gibson Security had warned Snapchat about the flaw. Snapchat then promised better rate limiting. Enumeration without limits is the same weakness that makes reset flows leak who has an account.

What it looks like in code

// GOOD: Same response regardless of email validity
return NextResponse.json({ message: "If an account exists, a reset link was sent." })
// Never reveal whether the email exists

// GOOD: Rate limit reset requests
// GOOD: Never return the token in the HTTP response
// Send it via email only:
await sendEmail(email, `Reset: https://app.com/reset?token=${token}`)
return NextResponse.json({ message: "If an account exists, a reset link was sent." })

Ask your AI tool to fix it

Paste this into Cursor, Claude, Lovable, Bolt or whatever you build with.

Prompt
Review my password reset flow. Make sure the reset token is never returned in any API response and is only sent by email. Use long random single-use tokens that expire within 15 minutes, return the same message whether or not the email exists, store only a hash of the token, invalidate it after use and after a password change, and add rate limiting. Prefer my auth provider’s built-in reset if available.

Where this comes from

The facts, figures and fixes on this page were checked against these sources on 25 Oct 2026. They are linked so you can check for yourself.

Spot a mistake or something out of date? Report a correction · How these guides are made and checked

Go deeper in isitsecure

The free, open-source scanner checks for most of the problems in these guides.