v0.14 is out: a mobile auth pack for Swift/iOS and Android, catching insecure token storage, cleartext traffic, and OAuth in embedded WebViews. Read more →
HIGH AI PREVALENCE: HIGH auth.java.crypto.insecure-random

A security-sensitive value (token, secret, key, password, nonce, OTP, or salt) is generated with a non-cryptographic PRNG.

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.

// oauthlint-disable-next-line auth.java.crypto.insecure-random -- <reason>

References

https://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html ↗https://cwe.mitre.org/data/definitions/330.html ↗