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
java.util.Random and Math.random() are predictable: their output is seeded from system time and the internal state can be recovered from a few observed values, so an attacker can reconstruct the "random" secret (CWE-330). This is a common AI-generated mistake: new Random().nextInt(...) gets pasted in to produce a token because it looks random enough.
Use java.security.SecureRandom instead. For example, new SecureRandom().nextBytes(buf) to fill a byte buffer, then encode it (Base64/hex) to build the token or secret.
VULNERABLE
vulnerable.java
import java.util.Random;class TokenFactory { String makeToken() { // ruleid: auth.java.crypto.insecure-random long token = new Random().nextLong(); return Long.toHexString(token); } double makeSecret() { // ruleid: auth.java.crypto.insecure-random double secret = Math.random(); return secret; } int makeOtp() { // ruleid: auth.java.crypto.insecure-random int otp = new java.util.Random().nextInt(1000000); return otp; } byte[] makeKeyBytes() { Random rnd = new Random(); byte[] keyMaterial = new byte[32]; // ruleid: auth.java.crypto.insecure-random rnd.nextBytes(keyMaterial); return keyMaterial; }}
SAFE
safe.java
import java.security.SecureRandom;import java.util.Random;class SafeTokenFactory { byte[] makeKeyBytes() { SecureRandom rnd = new SecureRandom(); byte[] keyMaterial = new byte[32]; // ok: auth.java.crypto.insecure-random rnd.nextBytes(keyMaterial); return keyMaterial; } long makeSecureToken() { // ok: auth.java.crypto.insecure-random long token = new SecureRandom().nextLong(); return token; } int pickShardIndex() { // ok: auth.java.crypto.insecure-random int idx = new Random().nextInt(10); return idx; } int jitterMillis() { Random rnd = new Random(); // ok: auth.java.crypto.insecure-random int jitter = rnd.nextInt(500); return jitter; }}
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.