Root cause
CryptoJS.lib.WordArray.random(), the library's primary entropy source since 2012, calls Math.random() whenever window.crypto is absent — a non-cryptographic PRNG whose internal state can be approximated from a short sequence of observed outputs.
// CryptoJS v4.2.0 — affected path (simplified)
WordArray.random = function(nBytes) {
var words = [];
for (var i = 0; i < nBytes; i += 4) {
// ⚠️ Math.random() is NOT a CSPRNG
words.push((Math.random() * 0x100000000) | 0);
}
return new WordArray.init(words, nBytes);
};
Any wallet application that piped this output through BIP-39 mnemonic generation produced seed phrases whose effective entropy was bounded by Math.random() — in practice 32–64 bits rather than the 128 or 256 bits the BIP-39 wordlist implies. The vulnerable code path is exercised only when an application explicitly calls WordArray.random() for key or seed material; simply importing CryptoJS is insufficient.
Attack steps
| Step | Action |
|---|---|
| 1 | Enumerate candidate seeds by replaying plausible Math.random() sequences seeded with timestamp ranges and process-state approximations |
| 2 | Derive BIP-32 HD key trees for each candidate; generate the first 10 child addresses per seed |
| 3 | Monitor Ethereum and TRON UTXO/account sets for address matches |
| 4 | Wave 1 (May 27, 2026): automated sweep drains $3.14M from 431 accounts |
| 5 | Wave 2 (May 30 – July 13, 2026): $2.55M from 522 addresses; one TRON account yields $2.18M USDT alone |
Impact
~$5.69M across Ethereum and TRON from five affected wallet applications; NanChat was the only publicly named app at time of disclosure (August 5–6, 2026). CVSS 9.0 Critical. The vulnerability was disclosed by CryptoJS maintainer Evan Vosberg under GHSA-rg76-677x-56q9.
Lessons for auditors
- Never use
CryptoJS.lib.WordArray.random()for security-sensitive values. Usewindow.crypto.getRandomValues()(browser) orcrypto.randomBytes()(Node.js) directly. - Post-generation hashing cannot restore entropy. Once a seed phrase is derived from weak entropy, subsequent PBKDF2 or SHA-256 rounds do not reduce the candidate search space — the attacker already knows the low-entropy domain.
- Audit transitive dependencies for key generation. A protocol's Solidity may be flawless while its wallet UI bundles CryptoJS for mnemonic generation; smart-contract audits should include a frontend dependency review where key material is generated.
- Advisory scope precision matters. The GHSA advisory explicitly notes that merely bundling CryptoJS does not constitute vulnerability — only applications that invoke
WordArray.random()to generate key material are affected. Blanket upgrade alerts without this nuance cause unnecessary churn.