Why AI tools produce this: AI coding tools generate this anti-pattern by default, it appears in a large share of AI-written auth code.
Why this matters
The value is assigned to (or computed for) a token, a CSRF value, an OAuth state, a session id, a nonce, or a verification code. Math.random() is NOT cryptographically secure and is predictable enough for an attacker with enough samples to recover the seed.
Use crypto.randomBytes(N) (Node) or crypto.getRandomValues() (browser) and base64url-encode the result.
OWASP ASVS V2.5: all security-sensitive random values must come from a CSPRNG.
import { randomBytes } from 'node:crypto';// ok: auth.flow.insecure-randomexport const csrfToken = randomBytes(32).toString('base64url');// ok: auth.flow.insecure-random -- non-security valueexport const animationDelay = Math.random() * 200;// ok: auth.flow.insecure-random -- non-security valueexport const pickColor = Math.random();// These names contain security-word *substrings* but are not secrets, and use// Math.random() legitimately — regression guards against substring matches.// ok: auth.flow.insecure-random -- "barcode" is not a security tokenexport const barcode = Math.random().toString(36);// ok: auth.flow.insecure-random -- "zipcode" is not a security tokenexport const zipcode = Math.random().toString().slice(2, 7);// ok: auth.flow.insecure-random -- camelCase, unrelated UI stateexport const gameState = Math.random();
Suppressing this rule
If a finding is a genuine false positive, scope the suppression to the exact line and leave a reason, never disable the rule project-wide. Disable directives are line-scoped by design.