Broken cryptographic primitive protecting a secret

A hash, cipher, or random source that cannot carry the weight it has been given: MD5 or SHA-1 over a password, a DES or ECB cipher, or Math.random() producing a token. Each has a drop-in replacement in the standard library, so the fix is small - the cost of not making it is that the protection is decorative.

high likely application source OWASP A02:2021 / CWE-327

What it looks like

HIGH likely Broken cryptographic primitive protecting a secret A02:2021 app/lib/crypto.ts:8:35 6 │ export function hashPassword(password: string): string { 7 │ // weak-crypto: MD5 over a password. 8 │ const passwordHash = createHash('md5').update(password).digest('hex') │ ~~~~~ fast hash protecting a credential 9 │ return passwordHash 10 │ }

From app/lib/crypto.ts in the fixture suite. The fixture test asserts this finding.

How to fix it

Use a slow, salted hash for passwords and a cryptographic random source for tokens. Both are in the Node standard library; neither needs a dependency.

import { randomBytes, randomUUID, scrypt } from 'node:crypto'

// Tokens and session ids: unpredictable, not merely random-looking.
const sessionId = randomUUID()
const resetToken = randomBytes(32).toString('base64url')

// Passwords: a slow hash with a per-password salt. bcrypt and argon2 are
// equally correct; scrypt needs no dependency.
const salt = randomBytes(16)
const hash = await new Promise<Buffer>((resolve, reject) =>
  scrypt(password, salt, 64, (error, key) => (error ? reject(error) : resolve(key))),
)

The fix for your framework

Choose the API used by your project.

Check your own repository

npx owlwarden scan --preset deep
npx owlwarden explain weak-crypto

explain prints the rule and fixes in the terminal. It does not use the network.

All 25 rules / owlwarden