I was one of the implementers of JScript and on the ECMA committee in the mid to late 1990s, so I can provide some historical perspective here.
The JavaScript Math.random() function is designed to return a floating point value between 0 and 1. It is widely known (or at least should be) that the output is not cryptographically secure
First off: the design of many RNG APIs is horrible. The fact that the .NET Random class can trivially be misused in multiple ways to produce long sequences of the same number is awful. An API where the natural way to use it is also the wrong way is a "pit of failure" API; we want our APIs to be pits of success, where the natural way and the right way are the same.
I think it is fair to say that if we knew then what we know now, the JS random API would be different. Even simple things like changing the name to "pseudorandom" would help, because as you note, in some cases the implementation details matter. At an architectural level, there are good reasons why you want random()
to be a factory that returns an object representing a random or pseudo-random sequence, rather than simply returning numbers. And so on. Lessons learned.
Second, let's remember what the fundamental design purpose of JS was in the 1990s. Make the monkey dance when you move the mouse. We thought of inline expression scripts as normal, we thought of two-to-ten line script blocks as common, and the notion that someone might write a hundred lines of script on a page was really very unusual. I remember the first time I saw a ten thousand line JS program and my first question to the people who were asking me for help because it was so slow compared to their C++ version was some version of "are you insane?! 10KLOC JS?!"
The notion that anyone would need crypto randomness in JS was similarly insane. You need your monkey movements to be crypto strength unpredictable? Unlikely.
Also, remember that it was the mid 1990s. If you were not there for it, I can tell you it was a very different world than today as far as crypto was concerned... See export of cryptography.
I would not have even considered putting crypto strength randomness into anything that shipped with the browser without getting a huge amount of legal advice from the MSLegal team. I didn't want to touch crypto with a ten foot pole in a world where shipping code was considered exporting munitions to enemies of the state. This sounds crazy from today's perspective, but that was that was the world that wasthat was the world that was.
why do browsers not replace it with a CSPRNG?
Browser authors do not have to provide a reason to NOT do a change. Changes cost money, and they take away effort from better changes; every change has a huge opportunity cost.
Rather, you have to provide an argument not just why making the change is a good idea, but why it is the best possible use of their time. This is a small-bang-for-the-buck change.
I understand that it could not be re-defined as a CSPRNG as the standard explicitly gives no guarantee for suitability for cryptographic use, but there seems to be no downside to doing it anyway
The downside is that developers are still in a situation where they cannot reliably know whether their randomness is crypto strength or not, and can even more easily fall into the trap of relying on a property that is not guaranteed by the standard. The proposed change doesn't actually fix the problem, which is a design problem.