Authentication Bugs

Password Reset Token Can Be Reused

A password reset link contains a one-time token that should be invalidated immediately after the password is changed. If the token is not marked as used, anyone with access to the original reset link — via email forwarding, a shared inbox, or a previously intercepted email — can trigger another password reset and take over the account.

HighBeginnerSecurity testingManual testingAPI testing

// UNDERSTAND

// Symptoms

  • A password reset link works more than once
  • After successfully resetting a password, the same reset URL still shows the reset form
  • The reset token is not invalidated after the password change is confirmed
  • Using the same reset URL a second time does not show an error

// Root Cause

  • The reset token is not deleted or marked as used in the database after a successful password change
  • Token expiry is checked but used-status is not tracked separately
  • Some implementations read and consume the token only on form submission, not on page load — so the reset form renders successfully even for an already-used token when the validity check is deferred to the POST handler

// Where It Appears

  • Password reset flows in any authenticated web application
  • Account recovery pages
  • Shared or forwarded email inboxes and team accounts
  • Applications where password reset emails are logged or archived

// REPRODUCE & TEST

// How to Reproduce

  1. 01Request a password reset for a valid test account
  2. 02In the test inbox, copy the full reset URL from the email before opening it
  3. 03Open the reset URL in the browser
  4. 04Set a new password and complete the reset flow
  5. 05Paste the original reset URL into a new browser tab
  6. 06Confirm whether the reset form appears and accepts a new password — it should not

// Test Data Needed

  • A valid user account with a working test email address or access to the test inbox
  • The original reset link from the email
  • The ability to copy and replay the URL after the first use

// Manual Testing Ideas

  • Request a reset link, use it to change the password, then try the same link again
  • Request two reset links in quick succession; confirm the first is invalidated when the second is issued
  • Wait for the token expiry window to pass and confirm it is rejected
  • Check whether the token looks guessable (sequential integer, short numeric code)
  • Check that the token is at least 32 characters of cryptographically random data

// API Testing Ideas

  • Capture the token value from the reset URL before submitting anything
  • POST to the password reset endpoint with the captured token to change the password
  • POST to the same endpoint again with the same token and a different new password
  • Assert the second request returns 400 Bad Request or 422 Unprocessable Entity — not 200 (410 Gone is a defensible alternative but uncommon in practice)

// Automation Idea

Automate a password reset request, extract the token from the test inbox, submit the reset form once, then replay the same token with a second POST request to the reset API. Assert that the second request is rejected with a 400 or 410 response.

// Expected Result

After a password reset token is used to successfully change a password, any subsequent attempt to use the same token should be rejected with a clear error.

// Actual Result (Example)

After successfully resetting the password, navigating to the same reset URL shows the password reset form again and accepts a new password submission.

// REPORT IT

Example Bug Report

Title
Password reset link can be reused after a successful password change
Severity
High
Environment
Staging environment Chrome 124 Standard user account
Steps to Reproduce
  1. 01Request a password reset for the test account
  2. 02Copy the full reset URL from the email before opening it
  3. 03Open the reset URL in the browser
  4. 04Set a new password (e.g. TestPass123!) and submit the form
  5. 05Confirm the success message appears
  6. 06Open the original reset URL in a new browser tab
  7. 07Enter a new password and submit the form; confirm the submission is accepted
Expected Result
The reset link shows an error such as 'This link has already been used' or redirects to the login page.
Actual Result
The password reset form loads normally and accepts a new password, allowing the password to be changed again with the same link.
Impact
Anyone with access to the original reset email — via a shared inbox, forwarded email, or archived mail — can use the old link to set a new password and gain full account access.

// RELATED