criticalCWE-256A02:2021

Passwords Stored in Plaintext

User passwords stored as raw strings in the database instead of being hashed with a proper algorithm like bcrypt or Argon2.

How It Works

If you store passwords as-is, a single database breach exposes every user's real password. Attackers then use those passwords on Gmail, banks, and other sites (credential stuffing). Hashing converts the password into an irreversible digest — even if the hash leaks, the original password stays secret.

Vulnerable Code
// BAD: storing the raw password
async function register(email: string, password: string) {
  await db.users.create({ data: { email, password } });
}
Secure Code
// GOOD: hash before storing
import bcrypt from 'bcrypt';
async function register(email: string, password: string) {
  const hash = await bcrypt.hash(password, 12);
  await db.users.create({ data: { email, password: hash } });
}

Real-World Example

RockYou (2009), Adobe (2013), LinkedIn (2012) — all stored passwords in plaintext or with reversible encryption. Each breach led to hundreds of millions of compromised accounts across other services through credential stuffing.

How to Prevent It

  • Always hash passwords with bcrypt (cost factor 12+) or Argon2id before storing
  • Never log, print, or return passwords anywhere in your code
  • Use a dedicated auth service (Supabase Auth, Auth0, Clerk) which handles this for you
  • Add a check in CI that scans for password fields being stored without hashing

Affected Technologies

nodejsNext.jsPythonPHP

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities