Skip to content

CWE-330: Use of Insufficiently Random Values

Overview

Insufficient Randomness occurs when an application uses a predictable or weak random number generator for a security-sensitive operation, letting an attacker guess or influence the outcome.

Relationship to Other CWEs

A finding that lands on CWE-330 is a starting point rather than a destination. MITRE marks it DISCOURAGED for mapping and asks you to "examine children of this entry to see if there is a better fit", so work out which randomness failure you actually have and report it against that child. This page is the right level to stand at only while that is still undecided.

The children differ by which part of the generation went wrong, and the fix differs with them:

  • CWE-330 (this page) - a security decision rests on a value that is not unpredictable enough, with the cause not yet pinned down
  • CWE-338 (Use of Cryptographically Weak Pseudo-Random Number Generator (PRNG)) - the algorithm is wrong: a fast non-cryptographic generator whose internal state an attacker can recover by watching its output. Replacing it with a CSPRNG fixes this and nothing else
  • CWE-331 (Insufficient Entropy) - the algorithm is fine but the result carries too few unpredictable bits to survive guessing, a 6-digit code drawn from a CSPRNG included. Here the fix is a longer value, which does nothing for a Mersenne Twister
  • CWE-329 (Generation of Predictable IV with CBC Mode) - the predictable value is a CBC initialization vector, where the consequence is a confidentiality break in the ciphertext rather than a guessable secret. It sits on a separate branch of this page's subtree, under CWE-1204 (Generation of Weak Initialization Vector (IV))

MITRE's remaining children have no page here, and each is worth a look before settling on this one: CWE-334 for a space small enough to enumerate, such as a 4-digit PIN; CWE-335 for a fixed, reused, or predictable seed; CWE-340 for a value that is unpredictable in principle but observable or derivable in practice; CWE-344 for a value that is meant to change per use and does not; and CWE-1241 for a generator whose algorithm is predictable by design.

OWASP Classification

A04:2025 - Cryptographic Failures

Risk

High: Attackers can predict session tokens, passwords, cryptographic keys, or other sensitive values, and present a predicted value to take over the account or session it protects.

Remediation Steps

Core Principle: Security tokens and secrets must come from a CSPRNG; never use predictable values.

Locate the insecure random value generation

  • Start from the file and line in the finding and identify which generator is in use (random, Math.random, a predictable seed)
  • Follow the value to where it is used: session tokens, passwords, keys, salts, nonces
  • Work out what that use requires: how much randomness, what length, and how unpredictable the value must be

Use cryptographically secure random generators (Primary Defense)

  • Replace the standard random function with the platform's secure API:
    • Python: secrets module or os.urandom() instead of random
    • Java: java.security.SecureRandom instead of java.util.Random
    • JavaScript/Node.js: crypto.randomBytes() or crypto.getRandomValues() instead of Math.random()
    • .NET: System.Security.Cryptography.RandomNumberGenerator instead of System.Random or Random.Shared
    • PHP: random_bytes() or random_int() instead of rand(), mt_rand(), uniqid(), shuffle(), array_rand() or str_shuffle()
    • Go: crypto/rand instead of math/rand or math/rand/v2
  • random, Math.random(), rand(), java.util.Random, System.Random and math/rand are not cryptographically secure, whatever they are seeded with

Seed random generators securely and validate randomness requirements

  • Do not seed by hand. A CSPRNG such as SecureRandom or secrets takes its entropy from the operating system; a seed you supply (time, PID, a counter) is predictable
  • Size the output for the use: at least 128 bits for session tokens, 256 bits for cryptographic keys
  • Judge unpredictability by the source and the size, not by testing the output: statistical tests run in the application cannot show that a generator is cryptographically secure

Apply additional randomness protections

  • Generate password salts with a CSPRNG and make each one unique
  • Do not mix weak and strong sources, such as combining random with secrets; use only the secure source
  • Generate a fresh value for every session and user; never reuse one
  • Encode tokens as base64url or hex to avoid character set problems

Monitor and audit random value usage

  • Search the codebase for random(, Math.random, rand( and mt_rand to find remaining insecure call sites
  • Log only metadata and failures for security-critical random generation; never log generated token, key, nonce, or salt values
  • Alert on generation failures and on repeated or sequential values
  • Track collisions in production; with a proper generator they should be extremely rare

Test the randomness fix

  • Verify the weak generator named in the finding is no longer used for security purposes
  • Generate many values and check that they are unique, the right length and correctly encoded, and that error paths behave; do not treat chi-square or runs tests as proof that the generator is secure
  • Re-scan with the security scanner to confirm the finding is resolved

Common Vulnerable Patterns

  • Using random or Math.random for session tokens or passwords
  • Seeding PRNGs with predictable values (e.g., time, PID)
  • Using insufficient entropy for security-critical operations
  • Mixing weak and strong random sources

Common Pitfalls

  • Swapping the seed, not the algorithm: Replacing a fixed or obvious seed with a "less guessable" one (a timestamp, a process ID, a hash of a few environment values) while still using a non-cryptographic PRNG - the algorithm is still deterministic, and the new seed is often still within a range an attacker can brute-force offline.
  • Losing entropy after generation: Drawing bytes from a CSPRNG correctly, then mapping them into a short output alphabet with plain modulo instead of rejection sampling, or truncating the result "for readability" - this biases the distribution or shrinks the effective keyspace far below what the CSPRNG produced.
  • Fixing the generator but not the old values: Switching new token generation to a secure source without rotating or invalidating tokens issued under the old, predictable generator - previously guessable values keep working until they naturally expire or are explicitly revoked.
  • Correct source, same insufficient length: Moving to a CSPRNG but keeping an output size that was only ever sized for a weak generator (a 4-digit PIN, a 32-bit token) - a secure source does not compensate for too few bits of output.

Language-Specific Guidance

For implementation examples in specific languages:

  • C#/.NET - RandomNumberGenerator, avoiding System.Random for security
  • Go - crypto/rand.Reader for secure randomness, avoiding math/rand for security
  • Java - java.security.SecureRandom, avoiding java.util.Random for security
  • JavaScript/Node.js - crypto.randomBytes(), crypto.getRandomValues(), avoiding Math.random() for security
  • PHP - random_bytes(), random_int(), avoiding rand() and mt_rand() for security
  • Python - secrets module, os.urandom(), avoiding random module for security

Additional Resources