Insecure randomness¶
ID: js/insecure-randomnessKind: path-problemSecurity severity: 7.8Severity: warningPrecision: highTags: - security - external/cwe/cwe-338Query suites: - javascript-code-scanning.qls - javascript-security-extended.qls - javascript-security-and-quality.qls
Click to see the query in the CodeQL repository
Using a cryptographically weak pseudo-random number generator to generate a security-sensitive value, such as a password, makes it easier for an attacker to predict the value.
Pseudo-random number generators generate a sequence of numbers that only approximates the properties of random numbers. The sequence is not truly random because it is completely determined by a relatively small set of initial values, the seed. If the random number generator is cryptographically weak, then this sequence may be easily predictable through outside observations.
Recommendation¶
Use a cryptographically secure pseudo-random number generator if the output is to be used in a security-sensitive context. As a rule of thumb, a value should be considered “security-sensitive” if predicting it would allow the attacker to perform an action that they would otherwise be unable to perform. For example, if an attacker could predict the random password generated for a new user, they would be able to log in as that new user.
For JavaScript on the NodeJS platform,crypto.getRandomBytes provides a cryptographically secure pseudo-random byte generator. Note that the conversion from bytes to numbers can introduce bias that breaks the security.
For JavaScript in the browser,crypto.getRandomValues provides a cryptographically secure pseudo-random number generator.
Example¶
The following examples show different ways of generating a password.
In the first case, we generate a fresh password by appending a random integer to the end of a static string. The random number generator used (Math.random) is not cryptographically secure, so it may be possible for an attacker to predict the generated password.
functioninsecurePassword(){// BAD: the random suffix is not cryptographically securevarsuffix=Math.random();varpassword="myPassword"+suffix;returnpassword;}
In the second example, a cryptographically secure random number generator is used for the same purpose. In this case, it is much harder to predict the generated integers.
functionsecurePassword(){// GOOD: the random suffix is cryptographically securevarsuffix=window.crypto.getRandomValues(newUint32Array(1))[0];varpassword="myPassword"+suffix;// GOOD: if a random value between 0 and 1 is desiredvarsecret=window.crypto.getRandomValues(newUint32Array(1))[0]*Math.pow(2,-32);}
References¶
Wikipedia:Pseudo-random number generator.
Mozilla Developer Network:Crypto: getRandomValues().
NodeJS:crypto.randomBytes
Common Weakness Enumeration:CWE-338.