CWE-330: Use of Insufficiently Random Values

When programming cryptographic functions ensure to use a Pseudo-Random Number Generator (PRNG) source that is random enough to be suitable for encryption.

Certain algorithms can create sequences of numbers that approximate random distributions [sonar 2024]. These algorithms, known as pseudorandom number generators (PRNGs) are numbers generated by a computational process and appear random, even though they are produced by a deterministic algorithm. This means that, unlike truly random numbers, which are inherently unpredictable, pseudorandom numbers are generated in a predictable sequence as long as you know the starting point, or the seed, and the algorithm used to generate them.

PRNGs suitable for encryption must mix non-computational sources such as a mouse, keyboard, or even Lava Lamps [LavaRnd] to be random enough for encryption.

Python’s random module is a standard library module that provides functions to generate pseudorandom numbers for various distributions. This module can lead to a vulnerability due to its predictability. The random module is based on the Mersenne Twister MT19937 [MATSUMOTO, NISHIMURA 1998], which is a deterministic algorithm, that, given a particular input, will always produce the same output [Mansi 2023]. An attacker knowing or guessing the seed value can predict the entire sequence of the pseudorandom numbers. This also means that if two Random class objects are created using an identical seed, they will generate the same sequence of numbers, regardless of the Python environment.

Therefore, the random module is unsuitable for applications requiring security as it does not incorporate cryptographic randomness, which means it is predictable. Its use makes it easy for attackers to deduce the internal state of the generator and predict future outputs.

Instead, for generating random numbers for security purposes, use an appropriate option, such as Python’s secrets module.

Code Example

example01.py, demonstrates how the same seed value produces identical sequences of random numbers, showing the predictable nature of Python’s random module.

example01.py:

# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
"""Example Code Example"""
import random


def generate_web_token():
    """Poor random number generator"""
    return random.randrange(int("1" + "0" * 31), int("9" * 32), 1)


# Show that tokens are predictable with same seed
for seed_value in [12345, 67890]:
    print(f"\nUsing seed {seed_value}:")

    # Generate tokens with same seed twice
    for attempt in [1, 2]:
        random.seed(seed_value)
        tokens = [generate_web_token() for _ in range(3)]
        print(f"  Attempt {attempt}: {tokens}")

Non-compliant Code Example

In noncompliant01.py, we generate a random web token using Python’s random module. This makes the token predictable and vulnerable to exploitation, as the sequence of numbers is always the same for any specified seed value.

noncompliant01.py:

# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
import random


def generate_web_token():
    """Poor random number generator"""
    return random.randrange(int("1" + "0" * 31), int("9" * 32), 1)


#####################
# attempting to exploit above code example
#####################
TOKEN = generate_web_token()
print(f"Your insecure token is: {TOKEN}")

Compliant Code Example

[!NOTE]

The secrets module os.urandom() is called by "secrets.token_urlsafe()" causing its cryptographic strength to depend on the operating system and its entropy sources. Pure randomness can not be produced in software alone [cloudflare 2017].

The compliant01.py solution uses the secrets module to generate the random numbers. The secrets module provides access to the most secure source of randomness that an OS provides through os.urandom().

compliant01.py:

# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Compliant Code Example """
import secrets


def generate_web_token():
    """Better cryptographic number generator"""
    return secrets.token_urlsafe()


#####################
# attempting to exploit above code example
#####################
TOKEN = generate_web_token()
print(f"Your secure token is: {TOKEN}")

Automated Detection

Tool Version Checker Description
sonarlint 9.0.0.75308 SonarQube 9.7+ When in Connected mode Sonarlint can be configured to detect the Sonar rule “Using pseudorandom number generators (PRNGs) is security-sensitive”
Bandit 1.7.4 B311 Standard pseudo-random generators are not suitable for security/cryptographic purposes.
   
SEI CERT C Coding Standard MSC30-C. Do not use the rand() function for generating pseudorandom numbers
SEI CERT C++ Coding Standard MSC50-CPP. Do not use std::rand() for generating pseudorandom numbers
SEI CERT Java Coding Standards MSC02-J. Generate strong random numbers
MITRE CWE Pillar CWE-693: Protection Mechanism Failure (4.12) (mitre.org)
MITRE CWE Class CWE-330, Use of Insufficiently Random Values

Biblography

   
[Python docs - random] Python Software Foundation. (2023). random- Generate pseudo-random numbers [online]. Available from: https://docs.python.org/3/library/random.html [accessed 23 August 2023].
[Python docs - secrets] Python Software Foundation. (2023). secrets - Generate secure random numbers for managing secrets [online]. Available from: https://docs.python.org/3/library/secrets.html [accessed 23 August 2023]
[Python docs - os] Python Software Foundation. (2023). os - Miscellaneous operating system interfaces [online]. Available from: https://docs.python.org/3/library/os.html [accessed 23 August 2023].
[sonar 2024] Sonar Rules - Using pseudorandom number generators (PRNGs) is security-sensitive [online]. Available from: https://rules.sonarsource.com/python/RSPEC-2245/ [accessed 7 September 2023]
[Cloudflare 2017] Randomness 101: LavaRand in Production (cloudflare.com) [online]. Available from:https://blog.cloudflare.com/randomness-101-lavarand-in-production/. [accessed 12 December 2024]
[LavaRnd] LAVARND … truly random since 2000 [online]. Available from: https://www.lavarand.org/ [accessed 12 December 2024]
[MATSUMOTO, NISHIMURA 1998] Mersenne Twister: A 623-Dimensionally Equidistributed Uniform Pseudo-Random Number Generator [online]. Available from: https://dl.acm.org/doi/pdf/10.1145/272991.272995 [accessed 12 December 2024]
[Mansi 2024] Deterministic and Non-Deterministic Algorithms [online]. Available from: https://www.scaler.com/topics/deterministic-and-non-deterministic-algorithm/ [accessed 20 October 2025]