CertC++-MSC50

Do not use std::rand() for generating pseudorandom numbers

Required inputs: IR

Pseudorandom number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random.

The C Standard  rand() function, exposed through the C++ standard library through <cstdlib> as std::rand(), makes no guarantees as to the quality of the random sequence produced. The numbers generated by some implementations of  std::rand() have a comparatively short cycle, and the numbers can be predictable. Applications that have strong pseudorandom number requirements must use a generator that is known to be sufficient for their needs.

Noncompliant Code Example

The following noncompliant code generates an ID with a numeric part produced by calling the rand() function. The IDs produced are predictable and have limited randomness. Further, depending on the value of  RAND_MAX, the resulting value can have modulo bias.

#include <cstdlib>
#include <string>
 
void f() {
  std::string id("ID"); // Holds the ID, starting with the characters "ID" followed
                        // by a random integer in the range [0-10000].
  id += std::to_string(std::rand() % 10000);
  // ...
}
Compliant Solution

The C++ standard library provides mechanisms for fine-grained control over pseudorandom number generation. It breaks random number generation into two parts: one is the algorithm responsible for providing random values (the engine), and the other is responsible for distribution of the random values via a density function (the distribution). The distribution object is not strictly required, but it works to ensure that values are properly distributed within a given range instead of improperly distributed due to bias issues. This compliant solution uses the  Mersenne Twister algorithm as the engine for generating random values and a uniform distribution to negate the modulo bias from the noncompliant code example.

#include <random>
#include <string>
 
void f() {
  std::string id("ID"); // Holds the ID, starting with the characters "ID" followed
                        // by a random integer in the range [0-10000].
  std::uniform_int_distribution<int> distribution(0, 10000);
  std::random_device rd;
  std::mt19937 engine(rd());
  id += std::to_string(distribution(engine));
  // ...
}

This compliant solution also seeds the random number engine, in conformance with  MSC51-CPP. Ensure your random number generator is properly seeded.

Risk Assessment

Using the  std::rand() function could lead to predictable random numbers.

Rule Severity Likelihood Remediation Cost Priority Level
MSC50-CPP Medium Unlikely Low P6 L2
Related Guidelines
SEI CERT C++ Coding Standard MSC51-CPP. Ensure your random number generator is properly seeded
SEI CERT C Coding Standard MSC30-C. Do not use the rand() function for generating pseudorandom numbers
CERT Oracle Secure Coding Standard for Java MSC02-J. Generate strong random numbers
MITRE CWE CWE-327, Use of a Broken or Risky Cryptographic Algorithm
CWE-330, Use of Insufficiently Random Values
Bibliography
[ ISO/IEC 9899:2011] Subclause 7.22.2, "Pseudo-random Sequence Generation Functions"
[ ISO/IEC 14882-2014] Subclause 26.5, "Random Number Generation"
Excerpt from SEI CERT C++ Coding Standard [https://cmu-sei.github.io/secure-coding-standards/sei-cert-cpp-coding-standard/rules/miscellaneous-msc/rand-for-generating-pseudorandom-numbers], Copyright (C) 1995-2026 Carnegie Mellon University. See section 9.4. "3rd-Party Licenses" in the documentation for full details.

Possible Messages

Key

Text

Severity

Disabled

forbidden_libfunc_call

Call to forbidden function.

None

False

Options

blacklist

blacklist

Type: dict[bauhaus.analysis.config.FileGlobPattern, list[bauhaus.analysis.config.GlobPattern]]

Default:

{
   '*stdlib.h': ['rand']
}
Dictionary of header globbing to (list of) function name globbing(s) of forbidden functions.