Security Guides
Password reset design flaws — harden login all you like, this is the way in
A long password and multi-factor authentication do not help if 'Forgot your password?' is weak — an attacker does not have to go through the front door. The five ways reset flows actually break, the requirements OWASP states explicitly, and how to decide the parts the guidance deliberately leaves to you.
"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 "we hardened authentication" does not cover this
Front: sign-in
Long passwords · multi-factor · rate limiting · brute-force detection
─────── same account ───────
Side: password reset
Works if mail arrives · often no second factor · token strength is invisible
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: arriving with a key is more common than breaking a lock. A reset flow is the place where a service issues that key through its own front counter.
The five shapes it takes
- 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 as a spare key
- 3. Links that live on in a mailbox
- Read the mailbox, read the key. 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
Hostheader 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 lookup service for 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
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 is not immediately a set of keys (the same reasoning as in password storage, hashing and salting).
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.
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.
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.
Finish the job on completion
On a completed reset, invalidate existing sessions — if the account was already taken over, this is the only thing that cuts the connection — 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 over the key 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 asymmetry is the hole. 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 thinnest path, not the thickest. 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
Read next
FAQ
QIf multi-factor authentication is enabled, does a weak password reset still matter?
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?
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?
Helpful to your users, and a free lookup service for an attacker checking 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 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, a great many keys open at once. Give the email account your strongest protection.