lowCWE-204A07:2021

User Enumeration via Distinct Error Messages

Login or password reset endpoints returning different error messages for 'email not found' vs 'wrong password', allowing attackers to confirm which email addresses are registered.

How It Works

If your login says 'No account found with this email' for unknown users and 'Incorrect password' for known users, attackers can run through email lists to discover which ones are registered. This powers targeted phishing, credential stuffing, and knowing who to pursue. A single response covers both cases.

Vulnerable Code
// BAD: different messages reveal account existence
if (!user) return Response.json({ error: 'No account with this email' }, { status: 401 });
if (!await bcrypt.compare(password, user.passwordHash)) {
  return Response.json({ error: 'Incorrect password' }, { status: 401 });
}
Secure Code
// GOOD: same message regardless of which check failed
if (!user || !await bcrypt.compare(password, user.passwordHash)) {
  return Response.json({ error: 'Invalid email or password' }, { status: 401 });
}

Real-World Example

Password reset flows are especially prone to this: 'We sent you a reset email' vs 'No account with that email' tells attackers exactly who's registered. Many major platforms got bounty reports for this, including LinkedIn and Twitter.

How to Prevent It

  • Use the same error message for both 'user not found' and 'wrong password' cases
  • For password reset, always say 'If that email is registered, you'll receive a link' — regardless
  • Apply the same response time delay whether or not the user exists (prevents timing attacks)
  • Rate limit enumeration attempts by IP

Affected Technologies

nodejsNext.jsPythonPHP

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities