highCWE-338A02:2021

Weak PRNG for Security

Using Math.random() or Date.now() to generate tokens, session IDs, or reset codes produces predictable values that attackers can guess or reproduce.

How It Works

Math.random() uses a pseudo-random number generator (PRNG) that is designed for speed, not security. Its output is deterministic given the seed state, and the state can be reconstructed from observed outputs. An attacker who sees a few generated values can predict all future values. Date.now() is even worse — it returns the current timestamp in milliseconds, which is trivially guessable. When these are used to generate password reset tokens, API keys, session IDs, or verification codes, an attacker can predict or brute-force the generated values. A 13-digit timestamp has only about 100,000 possible values if the attacker knows the approximate time. A Math.random() value has at most 2^52 bits of entropy but is reducible to the internal state with just a few observations.

Vulnerable Code
// Weak token generation
function generateResetToken() {
  return Math.random().toString(36).substring(2);
}
function generateApiKey() {
  return 'key_' + Date.now().toString(36);
}
function generateSessionId() {
  return Math.random().toString(16).slice(2) +
    Math.random().toString(16).slice(2);
}
Secure Code
const crypto = require('crypto');
function generateResetToken() {
  return crypto.randomBytes(32).toString('hex');
}
function generateApiKey() {
  return 'key_' + crypto.randomBytes(24).toString('base64url');
}
function generateSessionId() {
  return crypto.randomUUID();
}

Real-World Example

In 2020, researchers found that a popular CMS generated password reset tokens using Math.random(). By observing a few tokens, they reconstructed the PRNG state and predicted future tokens. This allowed them to generate valid password reset links for any account, including admin, without access to the user's email.

How to Prevent It

  • Always use crypto.randomBytes() or crypto.randomUUID() for security-sensitive values
  • Never use Math.random() or Date.now() for tokens, keys, or identifiers
  • Generate at least 32 bytes (256 bits) of entropy for security tokens
  • Use established libraries like uuid v4 which internally use crypto-secure randomness

Affected Technologies

Node.jsPythonJavaGoC#

Data Hogo detects this vulnerability automatically.

Scan Your Repo Free

Related Vulnerabilities