github / codeql

CodeQL: the libraries and queries that power security researchers around the world, as well as code scanning in GitHub Advanced Security

Home Page:https://codeql.github.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Insecure randomness - Documentation issue - Code example is misleading and could be improved

thariq-nugrohotomo opened this issue · comments

I'm reviewing a pull-request made by coworker that working on fixing vulnerabilities found by CodeQL, surprised by his fixes for Insecure randomness vulnerability, seems like he is simply copying the code example from this documentation https://codeql.github.com/codeql-query-help/javascript/js-insecure-randomness/#example

My coworker simply replacing Math.random() with window.crypto.getRandomValues(new Uint32Array(1))[0], and those changes may break many stuffs. The code example in the documentation uses the same code.

Note that both codes are not equivalent:

  1. Math.random() will return a decimal number in a half-open interval [0,1) (or in human term "greater than or equal to 0 and less than 1").
    Thus if var x = Math.random();, then x>=0 && x<1 will always return true.
  2. window.crypto.getRandomValues(new Uint32Array(1))[0] will always return an unsigned-32bit integer between 0 and 4294967295 (inclusive).

Possible solution = change the corrected example into nearly equivalent code, e.g.

window.crypto.getRandomValues(new Uint32Array(1))[0] / 4294967296

Note that I use 4294967296 instead 4294967295, since Math.random() always return a value less than 1.

Hi @thariq-nugrohotomo 👋

Thanks for letting us know about this. I believe the intention of the example is not to provide a like-for-like replacement, but to demonstrate how to generate random data in a cryptographically secure manner in JavaScript -- the objective of the example is to generate an unpredictable password, so in that case it doesn't really matter what that looks like in the end.

That said, obviously there's room for improvement here to make this clearer and I will pass this on to the JavaScript team as some feedback.

The examples are meant to show in general how to fix the vulnerability.
Concretely our examples show how strings with a random suffix could be created, and in that case the value range of the number doesn't matter.

So our example is not misleading, it just doesn't fit nicely with the case you encountered.

The examples cannot cover every case that might be flagged by the query, that would be way to long and wouldn't help anyone.

That being said, we could definitely add a line about how to create cryptographically secure random values between 0 and 1, and I've done so here: #16507

I merged the PR. It should land in code-scanning within a few weeks.

Wow thanks for a very quick follow-up. Really appreciated.

That being said, we could definitely add a line about how to create cryptographically secure random values between 0 and 1, and I've done so here: #16507

var secret = window.crypto.getRandomValues(new Uint32Array(1))[0] * Math.pow(2,-32);

I believe it's supposed to be / (division) instead of * (multiplication)
EDIT: sorry I misread -32 as 32. That should do the trick already.
I think that will be good enough to make the developer aware and careful about the value range.

Thanks again.