Skip to content
>_ITDITDWeb Security Platform

Security Guides

Password reset design flaws: 5 ways accounts get taken over despite strong login, and how to fix them

A long password and multi-factor authentication do not help if 'Forgot your password?' is weak: an attacker can take over the account through reset instead of login. The five ways reset flows actually break, the requirements OWASP states explicitly, and how to decide the parts the guidance deliberately leaves to you.

Published 2026-09-05 Updated 2026-10-04 Last verified 2026-09-05 9 min read

"Forgot your password?" leads to a mechanism for letting someone who does not know the password set a new one. That makes it an authentication path — and usually the weakest one the service has.

Why strengthening login alone does not prevent this

Usual path: sign-in

Long passwords · multi-factor · rate limiting · brute-force detection

─────── same account ───────

Separate path: password reset

Works if mail arrives · often no second factor · token strength is invisible

Reset is a separate authentication path from login. However strong the login is, a weak reset flow sets the real strength.

Reset gets built as a convenience for users, which means it is often not designed or reviewed with the same severity as authentication. Functionally, though, it hands control of an account to someone who does not know the password. It belongs in the same category as the login itself.

This lines up with what we found when we sorted the 2026 Japanese incidents by how attackers got in: getting in with valid credentials is more common than exploiting a vulnerability. A reset flow is where a service issues those credentials through its own official procedure.

The five shapes it takes

What CWE-640 looks like in practice
1. Guessable tokens
Sequential values, timestamps, short strings, or non-cryptographic randomness. Someone else's reset can be completed by guessing or brute force
2. Tokens that never die
No expiry, still valid after use, reusable. A link issued once keeps working indefinitely
3. Links that live on in a mailbox
Whoever reads the mailbox can read the reset link. Forwarding rules, shared accounts, a departed colleague's inbox — mail is seen by more eyes than you picture
4. Destinations set from outside
Build the reset URL from the request's Host header and an externally supplied value can end up as the link in your email (Host header injection)
5. Responses that give the account away
A helpful "not registered" message, or a difference in response time, turns the form into a way to check from outside who holds an account (user enumeration)

CWE-640, "Weak Password Recovery Mechanism for Forgotten Password", is the name given to this class. Its definition: the product "contains a mechanism for users to recover or change their passwords without knowing the original password, but the mechanism is weak." Note what that says — the problem is not having the feature, it is the feature not being as strong as the authentication it can replace.

Do not make security questions the only route

OWASP's position on security questions is that they should not be used as the sole mechanism for resetting passwords, because their answers are frequently easily guessable or obtainable by attackers — while noting they can provide an additional layer when combined with other methods. A mother's maiden name is not a secret in an era of social profiles and public records.

What the guidance requires, and what it leaves to you

This is where implementations hesitate. Keep the two apart.

Stated explicitly by OWASP

・Generate tokens with a cryptographically secure random number generator
・Make them long enough to resist brute force
・Invalidate them after use
・Return a consistent message for accounts that exist and accounts that do not
・Keep response times consistent too, to prevent enumeration
・Use rate limiting, CAPTCHA or similar controls against automated submissions
・Invalidate existing sessions automatically, or ask the user whether to
・Email the user that their password was reset — and do not put the password in it
・Do not rely on the Host header when building reset URLs (hard-code it, or validate against a list of trusted domains)
・Ensure the URL uses HTTPS

Numbers the guidance does not fix (yours to decide)

・The actual token length — only "long enough" is stated
・The expiry window — invalidation on use is required; a time limit is not given a number

Do not read the absence of a number as "this does not need deciding". It needs deciding with a reason, and writing down.

Our practical defaults: at least 128 bits of randomness in a URL-safe encoding; an expiry measured in tens of minutes; invalidation on use; and invalidation of older tokens whenever a new one is issued for the same account. The numbers matter less than the three properties — unguessable, not reusable, not immortal.

Implementation order

1

Make the token unguessable (first priority)

Generate it with a cryptographic random source and encode it URL-safely. Do not use a general-purpose random function — "looks random" and "cannot be predicted" are different properties. Store a hash of the token rather than the token itself, so that a readable database does not immediately yield usable tokens (the same reasoning as in password storage, hashing and salting).

2

Give it a lifetime, and spend it once

Invalidate on use, and expire on time as well. When a new token is issued for the same account, invalidate the older ones too — forget that and you are back at shape 2.

3

Never build the URL from external input

Generate the reset link from configuration, or validate it against a list of trusted domains. Do not pass a request header through into the email. OWASP names this one directly.

4

Make responses uniform, and rate-limit

Return the same wording and the same timing either way, and send mail only when an account actually exists. Add per-account rate limiting or a CAPTCHA against automated submissions. Users are not inconvenienced; from outside, the two cases are indistinguishable.

5

Finish the job on completion

On a completed reset, invalidate existing sessions — if the account was already taken over, this is the only way to lock the attacker out — and send a notification that the password was reset (without the password in it). Where you can, require a second factor on the reset path as well, so reset does not become the way around multi-factor authentication.

What reset really depends on is the mailbox

Do all of the above and the safety of reset still rests on whether only the account holder can receive the mail. If the email account is compromised, a well-built reset flow hands the account to the attacker more reliably than a sloppy one. Which is why the user-side priority lands in the same place: give the email account your strongest protection — a strong unique password and multi-factor authentication, ideally a passkey. It is also the route by which a provider-side breach spreads to you (what to do when your hosting provider is breached).

How it looks from the user's side

  • A reset email you did not request is a notification that somebody tried. Do not follow the link — sign in to the service yourself and check (phishing arrives looking exactly the same).
  • Being signed out of other devices after a reset is a sign of a correct implementation. A service that leaves other sessions alive after a reset gives you no way to cut off an intruder.
  • No second factor asked for during reset means multi-factor authentication may be bypassable on that path for that service. Worth testing once on the accounts that matter.
  • Ending password reuse is work best handed to a password manager.

This site's view: build it as authentication, not as a convenience

Reset flows go weak not because they are technically hard but because they are filed under the wrong heading. Sign-in is built carefully by the authentication people; "Forgot your password?" gets built lightly as a support path. That difference in treatment is the weakness. Our position is simple: any operation that hands over control of an account is an authentication feature — reset, changing the email address, re-enrolling a second factor, manual recovery by a support agent. Strength is set by the weakest path, not the strongest. Write out every route that reaches an account in your own service; there are usually more than you pictured.

Sources (primary)

  • OWASP Cheat Sheet Series, "Forgot Password Cheat Sheet" — cheatsheetseries.owasp.org (every requirement listed above as "stated explicitly" comes from this document; it does not state a token length or an expiry duration)
  • MITRE, CWE-640 "Weak Password Recovery Mechanism for Forgotten Password" — cwe.mitre.org

FAQ

QIf multi-factor authentication is enabled, does a weak password reset still matter?
A

Yes. Plenty of implementations do not require a second factor on the reset path, and where that is true, reset is a way to take the account back while stepping around the second factor. What you are protecting is not the strength of the login screen but the strength of every path that reaches the account. Invalidate existing sessions when a reset completes, and require the second factor on the reset path too where you can.

QHow long should a reset token be, and how long should it live?
A

The OWASP Forgot Password Cheat Sheet says tokens must be generated with a cryptographically secure random number generator, be long enough to resist brute force, and be invalidated after use — it does not state a number of characters or minutes. Those are yours to decide. Our practical defaults: at least 128 bits of randomness in a URL-safe encoding, an expiry measured in tens of minutes, invalidation on use, and invalidation of older tokens whenever a new one is issued for the same account. The numbers matter less than the three properties: unguessable, not reusable, not immortal.

QIsn't 'that email address is not registered' the helpful thing to show?
A

Helpful to your users, and a free way for an attacker to check which addresses hold accounts with you. OWASP asks for a consistent message for accounts that exist and accounts that do not, and for responses to return in a consistent amount of time. Show the same thing either way, and send mail only when there is actually an account — users are not inconvenienced and the difference is invisible from outside.

QWhat can I do as a user?
A

A reset email you did not ask for is a notification that somebody tried to reset your account. Do not follow the link — sign in to the service yourself and check that the password is not reused anywhere and that multi-factor authentication is on. And remember what reset actually depends on: your mailbox. If someone can read your email, they can reset the passwords of many of your accounts in a row. Give the email account your strongest protection.