First, insecure PRNGs are typically faster than CSPRNGs. CSPRNGs based on /dev/urandom (if you're familiar with Linux), for example, have to call the crypto kernel module driver every time. For reference:
the BearSSL implementation of ChaCha20, which can be used as a CSPRNG, on an Intel Xeon CPU at 3.10 GHz, reaches 270.72 MB/s;
an implementation of a Mersenne Twister, which is a typical PRNG, on an Intel Xeon 5160 at 3 GHz, reaches 113.4*32/8=453.6 MB/s;
there are even faster algorithms/implementations. For example, the rand() function in the GNU Scientific Library, according to the same paper, reaches 227.8*32/8=911.2 MB/s. Xorwow, which belongs to the Xorshift PRNG family, reaches 1388.4 MB/s.
Second, writing cryptographic software, including CSPRNGs, is much more complex than writing general-purpose software.
There are also historical reasons. At least until the 1990s, developers, including some developers working on standardizing new programming languages, were afraid to deal with cryptographic algorithms, because the export restrictions on cryptography were severe and not entirely understood by them. Quoting one such developer:
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 the world that was.
What about more recent programming languages, such as Python?
Some people argue that baking CSPRNGs into programming languages by default would lead to a false sense of security, especially as new flaws arise and when dealing with older software. Say that now, in 2018, random
is cryptographically secure. Do developers remember to check, when dealing with older versions, that the old random
was actually insecure?
An interesting quote on this matter:
Anyone writing crypto code without reading the docs and understanding what they are doing are surely making more mistakes than just using the wrong PRNG. There may be a good argument for adding arc4random support to the stdlib, but making it the default (with the disadvantages discussed, breaking backwards compatibility, surprising non-crypto users, etc.) won't fix the broken crypto code. It will just give people a false sense of security and encourage them to ignore the docs and write broken crypto code.
See this for more insight on how the Python community was reasoning about implementing a CSPRNG by default.
TL;DR. They are faster and easier to implement. In the past, people were afraid of crypto, because of heavy restrictions. Now, people are afraid of giving a false sense of security.