Password storage: hash with bcrypt, scrypt or Argon2
A database of plaintext passwords is a list of logins to other sites, because people reuse passwords. Whoever reads the table — through a backup, an injection or an insider — gets all of them.
Example
this.addUser = (userName, password, callback) => {
users.insertOne({ userName, password }, callback);
};const bcrypt = require("bcrypt");
this.addUser = async (userName, password) => {
const hash = await bcrypt.hash(password, 12);
return users.insertOne({ userName, password: hash });
};
// at login: await bcrypt.compare(attempt, user.password)How it goes wrong
Passwords written straight to the users table are the obvious case. Fast hashes are the subtle one: MD5, SHA-1 and plain SHA-256 can be computed billions of times per second on a GPU, so a leaked table of them is cracked in days. Unsalted hashes also let one precomputed table cover every user.
How to fix it
Use a slow, salted password hash and the library's verify function.
- bcrypt (cost 12 or more), scrypt or Argon2id
- Verify with the library's constant-time compare, never by comparing strings
- Rehash on login when you raise the cost
- Rate-limit login attempts and do not reveal whether the username exists
How RepoVerse finds it
- HighPassword stored without hashing
Anyone who reads the database — a backup, an injection, an insider — gets every user's password, and with it their accounts on other sites.
data flow · CWE-256
- ModeratePassword or token hashed with a broken digest
MD5 and SHA-1 are fast and collision-prone, which is exactly wrong for a secret — a commodity GPU walks a stolen table of them.
pattern
Questions
- Is SHA-256 with a salt good enough for passwords?
- No. Salting stops precomputed tables, but SHA-256 is designed to be fast, which is what an attacker cracking passwords wants. Password hashes are deliberately slow and tunable.
- How does RepoVerse detect plaintext passwords?
- It looks for password fields written to a database through insert, save or create calls with no hashing call anywhere near them and no pre-save hashing hook in the model.
Related
- Hardcoded secrets: API keys in code, commits and bundlesFind API keys, tokens and passwords committed to a repository or shipped in a website's JavaScript (CWE-798), why deleting the file is not enough, and how to rotate them.
- Secure session cookies: the flags and the login stepSet session cookies safely: Secure, HttpOnly and SameSite flags (CWE-614, CWE-1004), regenerating the session at login against fixation, with Express examples.
- NoSQL injection: rewriting MongoDB queries from a requestHow MongoDB $where expressions and operator objects like {"$ne": null} let request data rewrite a query (CWE-943), with vulnerable and fixed examples.
Updated 2026-10-11