October 1, 2026
Password Reset Flows: Three Token Tests Every Bug Hunter Should Know
Password reset functionality is one of those features that looks simple from the outside.

By Molapo Manuel
5 min read
A user clicks:
Forgot password โ enters email โ receives an email โ clicks a link โ chooses a new password.
But behind that simple flow is a security-sensitive token that can become an account takeover primitive if it is predictable, reusable, or remains valid longer than it should.
When testing password-reset functionality, I focus on one question:
What happens to the reset token throughout its entire lifecycle?
This article covers three tests I use when assessing password-reset flows.
Understanding the attack surface
A typical password-reset flow looks like this:
โโโโโโโโโโโโโโโโโโโ
โ Forgot Password โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Reset request โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Token generated โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Email delivered โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Link clicked โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ New password โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Forgot Password โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Reset request โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Token generated โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Email delivered โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Link clicked โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ New password โ
โโโโโโโโโโโโโโโโโโโThe important part isn't only whether the token works.
The important questions are:
- Can the token be reused?
- Can the token be predicted?
- Does the token remain valid after the account state changes?
1. Can the reset token be reused?
This is the first test I perform.
A properly implemented reset token should normally be single-use and expire after an appropriate period.
Test
Start with an account you are authorized to test.
Request a password reset.
You might receive something like:
https://example.test/reset?token=7f91c2a8...https://example.test/reset?token=7f91c2a8...Click the link.
Set a new password.
Now return to the original reset link and try it again.
Expected secure behavior
The application should reject the token.
For example:
Reset successful
โ
โผ
Token invalidated
โ
โผ
Second attempt
โ
โผ
"Token expired or already used"Reset successful
โ
โผ
Token invalidated
โ
โผ
Second attempt
โ
โผ
"Token expired or already used"Potential vulnerability
If the same token can be used again:
Token
โ
โโโโบ Reset password
โ
โโโโบ Reset password againToken
โ
โโโโบ Reset password
โ
โโโโบ Reset password againthat indicates the token may not be invalidated after use.
This becomes especially interesting if the token can be obtained through another compromise.
For example:
Email compromise
โ
โผ
Reset email obtained
โ
โผ
Reset token obtained
โ
โผ
Password changedEmail compromise
โ
โผ
Reset email obtained
โ
โผ
Reset token obtained
โ
โผ
Password changedA reusable token increases the amount of time an exposed token can remain useful.
Reset links can also appear in browser history, logs, copied URLs, screenshots, or other places depending on the application's implementation. OWASP notes that URL-based credentials can be exposed through mechanisms such as browser history, bookmarks, logs, and referrers, which is why their lifetime and handling matter.
2. Is the reset token predictable?
This is where the testing becomes more interesting.
A secure reset token should be generated using a cryptographically secure random source and should be difficult to predict.
The goal isn't to "guess a token."
The goal is to determine whether there is evidence that the token generation process is predictable.
Request multiple reset tokens
For an account you control, request several password resets.
For example:
Request #1
token=8f3c91d7...
Request #2
token=4a91c2e8...
Request #3
token=b71e5f04...
Request #4
token=0d9ac821...Request #1
token=8f3c91d7...
Request #2
token=4a91c2e8...
Request #3
token=b71e5f04...
Request #4
token=0d9ac821...Now compare them.
Look for obvious relationships.
Test A โ Sequential values
For example:
100001
100002
100003
100004100001
100002
100003
100004If reset tokens behave like counters, that deserves investigation.
Test B โ User ID encoded into the token
Imagine the user ID is:
123456123456and the reset token contains something that decodes into:
123456123456Base64 is encoding, not encryption.
For example:
123456
โ
โผ
MTIzNDU2123456
โ
โผ
MTIzNDU2If sensitive information is simply encoded into a reset token, the token may not provide the secrecy expected from a password-reset credential.
However, finding Base64 characters alone does not prove a vulnerability.
The important question is whether the encoded value is actually sufficient to authenticate the reset operation.
Test C โ Timestamp-based values
Another thing to investigate is whether the token contains predictable time information.
For example, imagine several tokens appear around the same time:
Reset #1 โ 1710001200...
Reset #2 โ 1710001214...
Reset #3 โ 1710001227...Reset #1 โ 1710001200...
Reset #2 โ 1710001214...
Reset #3 โ 1710001227...That doesn't automatically mean the token is vulnerable.
But if the token can be reproduced from a timestamp, user identifier, or other predictable values, the situation becomes much more serious.
The test is therefore:
Can I identify a predictable input?
โ
โผ
Can I reproduce the token?
โ
โผ
Can the reproduced token reset the password?Can I identify a predictable input?
โ
โผ
Can I reproduce the token?
โ
โผ
Can the reproduced token reset the password?The final step is what turns an interesting token-generation observation into a security issue.
Important: Don't confuse encoding with predictability
Suppose you receive:
token=YjYxY2Q4...token=YjYxY2Q4...It may look like Base64.
You decode it and obtain:
b61cd8...b61cd8...That alone doesn't prove anything.
A secure random token can also be represented using Base64.
For example:
Random bytes
โ
โผ
Cryptographically secure token
โ
โผ
Base64 representationRandom bytes
โ
โผ
Cryptographically secure token
โ
โผ
Base64 representationThe encoding isn't the security boundary.
The underlying entropy and generation process are what matter.
3. Does the old token survive a password change?
This test looks at the relationship between the reset token and the account's state.
The question is:
If the account's password changes through another legitimate mechanism, does an old reset token remain valid?
For an authorized test account, create a reset request but don't immediately consume the link.
For example:
Step 1
Request password reset
โ
Step 2
Receive reset token
โ
Step 3
Do NOT use token
โ
Step 4
Change password through the normal
authenticated "Change Password" feature
โ
Step 5
Return to the old reset link
โ
Step 6
Test whether the old token is still acceptedStep 1
Request password reset
โ
Step 2
Receive reset token
โ
Step 3
Do NOT use token
โ
Step 4
Change password through the normal
authenticated "Change Password" feature
โ
Step 5
Return to the old reset link
โ
Step 6
Test whether the old token is still acceptedThe interesting result is whether the application's state change invalidates previously issued recovery credentials.
For example:
Password: OLD
Reset Token: VALID
โ
โผ
Normal password change
โ
โผ
Password: NEW
Reset Token: ???Password: OLD
Reset Token: VALID
โ
โผ
Normal password change
โ
โผ
Password: NEW
Reset Token: ???If the old token remains usable indefinitely, that deserves investigation.
The impact depends heavily on the application's design and the privileges granted by the token.
Putting the three tests together
I like to think about the password-reset token as having a lifecycle:
TOKEN LIFECYCLE
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token generated โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token delivered โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token consumed โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โโโโโโโโดโโโโโโโโ
โ โ
โผ โผ
INVALID VALID
โ โ
โ โโโโบ Password reset again?
โ
โผ
ExpectedTOKEN LIFECYCLE
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token generated โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token delivered โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ Token consumed โ
โโโโโโโโโโโโฌโโโโโโโโโโโโ
โ
โโโโโโโโดโโโโโโโโ
โ โ
โผ โผ
INVALID VALID
โ โ
โ โโโโบ Password reset again?
โ
โผ
ExpectedThe three questions are therefore:
1. SINGLE USE?
โ
โโโ Can the token be consumed twice?
2. UNPREDICTABLE?
โ
โโโ Can another valid token be derived or predicted?
3. STATE INVALIDATION?
โ
โโโ Does changing the password invalidate old recovery credentials?1. SINGLE USE?
โ
โโโ Can the token be consumed twice?
2. UNPREDICTABLE?
โ
โโโ Can another valid token be derived or predicted?
3. STATE INVALIDATION?
โ
โโโ Does changing the password invalidate old recovery credentials?Building a simple testing checklist
When I encounter a password-reset feature during an authorized assessment, I can record the results like this:
TestQuestionExpectedToken reuseCan the same token reset the password twice?NoExpirationDoes the token expire?YesRandomnessAre tokens unpredictable?YesUser bindingIs the token tied to the correct account?YesPassword changeDoes changing the password invalidate old recovery credentials?Should be evaluatedMultiple resetsWhat happens when several tokens are generated?Previous tokens should be handled deliberatelyRate limitingCan reset requests be spammed?Should be controlled
OWASP also recommends rate limiting password-reset requests and avoiding account enumeration through inconsistent responses.
What makes a strong finding?
Not every strange-looking token is a vulnerability.
For example:
Token looks like Base64Token looks like Base64is not enough.
Instead, look for a complete security story:
Predictable token
+
Ability to generate another user's token
+
Token accepted by reset endpoint
=
Potential account takeoverPredictable token
+
Ability to generate another user's token
+
Token accepted by reset endpoint
=
Potential account takeoverLikewise:
Token can be reusedToken can be reusedis important, but the impact depends on whether an attacker can obtain a token and whether the token remains valid after password changes.
The strongest reports connect the technical weakness to the actual security consequence.
A secure implementation
A stronger implementation should use:
Cryptographically secure random token
โ
โผ
Store securely
โ
โผ
Send via HTTPS link
โ
โผ
Short validity period
โ
โผ
Token consumed
โ
โผ
Token invalidatedCryptographically secure random token
โ
โผ
Store securely
โ
โผ
Send via HTTPS link
โ
โผ
Short validity period
โ
โผ
Token consumed
โ
โผ
Token invalidatedOWASP recommends reset tokens be random, sufficiently long, securely stored, linked to the individual account, invalidated after use, and time-limited.
The reset flow should also avoid exposing whether an account exists through different responses, and reset requests should have appropriate abuse controls.
Final takeaway
Password reset isn't just an email feature.
It's an authentication mechanism.
The moment an application says:
"Possessing this token allows you to choose a new password."
that token becomes extremely sensitive.
So when I test a password-reset flow, I don't stop after clicking the link.
I follow the token.
I ask:
Can I reuse it?
Can I predict it?
Does it die when the account state changes?Can I reuse it?
Can I predict it?
Does it die when the account state changes?Those three questions can turn a seemingly ordinary password-reset feature into a much more interesting area for security research.