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.
- Next.js
- Nuxt
- NestJS
- Express
- Fastify
- Hono
- Koa
- Hapi
- Sails.js
- Astro
- Remix
- Gatsby
- SvelteKit
- TanStack Start
- SolidStart
- Elysia
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.