criticalLogins and sessions
Password Stored in Plain Text
Passwords are stored or compared in plain text without cryptographic hashing.
Why it matters
If your database is breached, every user's password is immediately exposed. Attackers can use these passwords to access user accounts on other services (credential stuffing). Hashing makes passwords unrecoverable even if the database is stolen.
What it looks like
This is the shape of code that triggers the rule. AI tools produce it because it works, and nothing tells them it is unsafe.
Direct password assignment from request
app.post('/register', async (req, res) => {
const user = {
username: req.body.username,
password: req.body.password,
};
await db.insert(user);
res.json({ ok: true });
});The smallest fix
minimal patch
// Hash before storing:
import bcrypt from 'bcrypt';
const hashedPassword = await bcrypt.hash(password, 12);
// Compare with hash:
const isValid = await bcrypt.compare(password, user.hashedPassword);The better fix
If you have a few more minutes, this is the approach that holds up as the app grows.
safe alternative
// Use argon2 for stronger hashing:
import argon2 from 'argon2';
const hash = await argon2.hash(password);
const isValid = await argon2.verify(hash, password);Let your AI tool fix it
When the scanner finds this in your project, it fills in the file and line for you. This is the prompt it gives you to paste into Claude Code, Cursor or whatever you use.
The file [the file] at line [the line number] stores or compares passwords in plain text: [the flagged code]. Hash passwords with bcrypt (salt rounds 12+) before storing, and use bcrypt.compare() for verification.
How to check the fix worked
1. Register a user and check the database — password must be hashed, not plain text 2. Verify bcrypt.compare() is used for login verification 3. Confirm salt rounds are at least 10