The Bug: Math.random() Generating API Keys
A 44K-star open-source repository — react-native-elements — was found using Math.random() to generate integration API keys. This is a security vulnerability because Math.random() is a Pseudo-Random Number Generator (PRNG), not a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG).
Why Math.random() Is Not Secure
Math.random() in JavaScript uses an algorithm like XorShift128+ in V8. Once an attacker recovers the internal state by observing a few outputs, they can predict all future outputs. For API keys, which are used for authentication, this predictability means an attacker could forge valid keys.
The Attack: Recovering the Internal State
The article describes a class of attack: by collecting a sequence of Math.random() outputs, an attacker can reverse-engineer the PRNG state. Tools like v8-randomness-predictor exist to do this. With the state known, the attacker can generate the same "random" keys the application would produce.
The Fix: Use crypto.randomBytes
The one-line fix is to replace Math.random() with crypto.randomBytes() (Node.js) or crypto.getRandomValues() (browser). These are CSPRNGs that are seeded from system entropy and are not predictable.
Example of the vulnerable code:
function generateApiKey() {
return Math.random().toString(36).substr(2, 16);
}
Fixed version:
const crypto = require('crypto');
function generateApiKey() {
return crypto.randomBytes(16).toString('hex');
}
ESLint Rule to Catch This
To prevent this pattern, use the ESLint plugin eslint-plugin-security with rule detect-unsafe-random. Alternatively, a custom ESLint rule can flag any use of Math.random() in non-trivial contexts. The article provides an example rule that forbids Math.random() in functions that generate secrets.
Codebase Impact
React Native Elements is a UI library with 44K stars. The issue was found in a utility function generating integration API keys for third-party services. The fix was merged after the report.
Why This Matters
Many developers assume Math.random() is random enough for security. This case proves otherwise. The same pattern appears in countless projects: generating IDs, tokens, or keys with Math.random(). Each instance is a potential backdoor.
Next Steps for Developers
- Audit your codebase for
Math.random()usage, especially in functions that generate secrets, tokens, or IDs. - Install
eslint-plugin-securityand enabledetect-unsafe-random. - Replace
Math.random()withcrypto.randomBytes()(Node) orcrypto.getRandomValues()(browser) for any security-sensitive randomness. - For UUIDs, use
crypto.randomUUID()(Node 14.17+). - Consider using a dedicated library like
uuidwith crypto backend.
Conclusion
Math.random() is not secure for secrets. The react-native-elements case is a wake-up call. The fix is trivial; the risk is not. Run the audit today.


