MD5, SHA-1, and plain SHA-256 are designed to be fast, which is exactly what you do not want for passwords. If your database leaks, an attacker can try billions of guesses per second against those hashes and recover most passwords quickly. Use a slow, salted password hash built for the job, like bcrypt or argon2.
Why it's a problem
Fast general-purpose hashes make offline cracking cheap, so a stolen users table with MD5 or SHA-1 hashes is effectively a list of plaintext passwords within hours. Purpose-built password hashes are deliberately slow and salted per user, which makes mass cracking impractical even after a breach.
The pattern
// far too fast, and unsalted
const hash = crypto.createHash("md5").update(password).digest("hex");The fix
import bcrypt from "bcrypt"; // hash on signup (bcrypt salts automatically) const hash = await bcrypt.hash(password, 12); // verify on login const ok = await bcrypt.compare(password, hash);
Why AI tools write this
createHash('md5') is a short, familiar line that produces a hash, so when the task is 'hash the password' it is a common completion, especially since MD5 examples are everywhere in training data. It runs and stores a hash; nothing signals that the hash is unsafe for passwords.
The quick fix
- Hash passwords with bcrypt, scrypt, or argon2, never MD5, SHA-1, or plain SHA-256.
- Let the library handle salting; do not roll your own.
- On your next login for each user, re-hash with the strong algorithm and migrate.