Password Reset Code Review and Pentest Checklist

Published: 02 Jan 2025

A secure password reset process is a cornerstone of account security for any web application. If not implemented correctly, it can expose users to severe security risks, including unauthorized account access. When a password reset process is broken, even the strongest authentication and authorization mechanisms are rendered irrelevant.

This article outlines a comprehensive checklist to help you identify potential risks, avoid common pitfalls, and implement best practices for a secure password reset process.


Classic Implementation

A classic implementation of a password reset process usually follows these steps:

  1. Users submit their email address to request a password reset.
  2. They receive a link containing a random token via email.
  3. Clicking the link prompts them to enter a new password.
  4. Users submit the new password.
  5. They can then proceed to log in with the new password.

However, this seemingly simple process is full of potential risks::

  • Token Reuse: Attackers could reuse tokens if they are not invalidated after a single use or expiration.
  • Phishing: Poorly implemented password reset links can be exploited in phishing attacks, directing users to malicious sites.
  • Token Interception: Tokens exposed in logs, headers, or unsecured channels can be intercepted by attackers.
  • Brute-Force Attacks: Weak or predictable tokens can be guessed through automated attacks.

URL in Email Should Not Be Based on Host Header

When sending a reset link by email, the application needs to determine where the link should point. This can be done in two main ways:

  • Hardcoding the value in the code or setting it via configuration.
  • Using the Host header provided by the client.

If the application relies on the Host header, an attacker can forge a request pointing to their own server. If a victim clicks the malicious reset link, the attacker can intercept the secret token and reset the user’s password.

Pentest vs Code Review Check: Testing this vulnerability is easier through pentesting, as it can be confirmed in a single request. However, code reviews are more reliable since server configurations or application architecture (e.g., reverse proxies) may block exploitation.


Limit Link Usage (Time-Based or Attempt-Based)

Password reset links should have strict limitations:

  • Implement time-based expiration.
  • Restrict the number of attempts to use the token.
  • Invalidate the token once the password is successfully reset.

Failing to implement these restrictions increases the risk of brute force attacks or delayed exploitation by attackers.

Pentest vs Code Review Check: This is definitely easier to verify through a code review, as it is not always clear how this is managed over time during a black-box audit.


Use Cryptographically Random Tokens

The security of a password reset process depends on the randomness of the tokens. Ensure tokens are generated using cryptographically secure random number generators.

Pentest vs Code Review Check: Code reviews are better suited for verifying token randomness, as black-box testing may not uncover issues such as the use of predictable values that only appear random (e.g., MD5 hashes of timestamps).


Validate Tokens Correctly

Tokens must be validated securely to prevent bypasses or timing attacks:

  • Use constant-time comparison functions to avoid timing attacks.
  • Ensure the token value is matched securely (e.g., avoid using SQL LIKE for token lookups).
  • Validate the token at all relevant steps (e.g., both before displaying the reset form and when resetting the password).

Pentest vs Code Review Check: Dynamic testing may identify some of these issues, but a source code review provides comprehensive coverage and assurance.


Ensure Tokens Are User-Specific

Tokens should be tied to specific users. A token valid for one user must not work for another. This requires pairing tokens with user identifiers (e.g., email or user ID) during validation.

Pentest vs Code Review Check: Black-box testing might reveal token reuse issues, but white-box testing ensures a thorough understanding of token handling.


Store Passwords Securely

Password storage must meet modern security standards:

  • Never store passwords in plain text.
  • Avoid weak hashing algorithms like MD5, SHA1 or SHA2.
  • Use algorithms designed for password storage (e.g., BCrypt, SCrypt, PBKDF2) with sufficient iteration counts.

Refer to the OWASP Password Storage Cheat Sheet for recommended settings.

Pentest vs Code Review Check: This is best reviewed through code review. To verify it via black-box testing, you would need access to a database dump and an understanding of the hashed password format.
Enforce Password Complexity

Ensure the application enforces a reasonable level of password complexity, ideally during both registration and password reset. Verifying complexity at these stages helps maintain consistent security across functionalities.

Pentest vs Code Review Check: Code reviews are more effective for verifying password complexity requirements, though black-box tests can highlight weak or missing enforcement.


Prevent Link Leakage

Password reset links can be leaked through several channels:

  • Using HTTP instead of HTTPS.
  • Sending emails without TLS encryption.
  • In the application's logs.
  • Exposing links through the Referer header.

Pentest vs Code Review Check: Preventing link leakage often requires a combination of black-box testing and code reviews to ensure proper implementation and secure deployment.


Final Thoughts

A secure password reset process demands meticulous attention to detail and adherence to best practices. By addressing the risks and following this checklist, you can build a robust system that protects user accounts and maintains trust in your application.

Remember, this checklist is a starting point—the bare minimum for a secure implementation. Regular reviews and updates are essential to staying ahead of emerging threats.

To deepen your understanding of secure coding practices, explore our Live Web Security Code Review Training and earn the PentesterLab Code Review Badge to showcase your expertise.

Photo of Louis Nyffenegger
Written by Louis Nyffenegger
Founder and CEO @PentesterLab