Heimdall
Heimdall ScanOpen Beta
CriticalProSecrets & Credentials

Plain text and weakly hashed passwords

If your app stores passwords directly, those passwords have to be hashed with a slow, salted algorithm before they touch the database. MD5 and SHA1 do not count. Plain text definitely does not count.

#What goes wrong

Some AI scaffolds save the password field from a signup form straight into a users table. Others apply SHA256 because it sounds secure. Neither is acceptable in 2026. Modern password hashing has to be slow on purpose, so that an attacker who steals the database table cannot crack the hashes with a consumer GPU.

#Why it matters

Database leaks happen. When they do, the difference between a 'we are sorry' email and a class action lawsuit is whether the passwords were properly hashed. Most users reuse passwords across sites, so a breach of your app becomes a breach of their email, bank, and everything else.

#How Heimdall checks for this

Heimdall reads your authentication and signup files and looks for any usage of bcrypt, argon2, scrypt, or pbkdf2. If none of them appear, and the app is not delegating auth entirely to a provider like Supabase Auth or NextAuth, it flags the route. Plain text storage and MD5/SHA1 usage are flagged as critical regardless.

#How to fix it

Use bcrypt with a cost factor of 12, or argon2id if you want the newer standard. Hash on signup, compare with bcrypt.compare on login, and never roll your own comparison. Existing plain text passwords cannot be retroactively secured. The fix is to hash on the next successful login, or to send a forced password reset email to every user.

Frequently asked questions

Should I use bcrypt or argon2?

Is delegating to Supabase Auth or Clerk safe?

How do I migrate existing plain text passwords?

Run this check on your own repo

Heimdall scans your GitHub repo for this and 16 other issues in under a minute.