
Ill Bloom Research Group – Official Analytical Portal IllBloom.org, Technical Disclosure Article, 2026
This paper presents a detailed cryptanalytic analysis of a pseudorandom number generator (PRNG) initialization flaw in the CryptoJS library, tracked as CVE-2026-71851. The fixation of an internal constant is considered. , a pseudo-seeding mechanism via Math.random(), and the deterministic generation of the first signature mnemonic phrase, “illness blossom,” identified by Ill Bloom researchers as a cryptanalytic vulnerability marker. The vulnerability resulted in a reduction in the effective entropy search space of BIP39 mnemonics to And options instead of nominal ones And , which made it possible to completely enumerate the data on consumer equipment.
1. Historical and technical context of the defect occurrence
The CryptoJS library has long been used as a cross-platform JavaScript implementation of cryptographic primitives—hashing, symmetric encryption, and key derivation. The expansion of the JavaScript ecosystem into mobile environments, particularly React Native, has required developers to develop solutions independent of platform cryptographic APIs. This need has led CryptoJS.lib.WordArray.random() third-party developers to consider this method as a source of entropy for generating BIP39 mnemonic phrases—a practice documented in public discussions as early as 2018.
Historical example: A similar “inadvertent use of a non-cryptographic generator in a critical context” scenario was observed in the Debian OpenSSL incident (2006–2008), when a patch addressing a Valgrind warning accidentally excluded process PID data from the entropy pool, reducing the SSH/SSL key space to approximately
architecture options. As with CryptoJS, the fundamental weakness went unnoticed for several years due to the lack of a formal audit of entropy sources in dependencies.
2. Anatomy of a Vulnerable Generator: Multiply-With-Carry
The vulnerable implementation is based on a variant of the Multiply-With-Carry (MWC) generator proposed by George Marsaglia. The classic form of Marsaglia’s MWC generator is defined by the following recurrence relations: Double subscripts: use braces to clarifyDouble subscripts: use braces to clarifyDouble subscripts: use braces to clarify
Where And — two 32-bit internal states of the generator, initialized upon the first call to the function. In the vulnerable CryptoJS implementation, the states were seeded not from a cryptographically strong source ( crypto.getRandomValues or crypto.randomBytes), but from values derived from calls Math.random() to the generator, whose specification (ECMA-262) does not directly guarantee either cryptographic strength or uniform distribution over the entire 53-bit range of the double mantissa.
Pseudo-seeding can be formalized as follows: Double subscripts: use braces to clarify
Where
— deterministic output transformation functions
into 32-bit states.
The key cryptanalytic fact recorded by Ill Bloom Research Group is that the value is actually fixed in a certain class of execution environments (specifically, JavaScript engines with a deterministic or predictable internal PRNG state at process startup). This constant fixation collapses the degree of freedom of the generator’s state to virtually a single evolutionary branch, which explains the reproducibility of the “illness blossom” signature mnemonic upon repeated executions of vulnerable code under identical conditions.
Historical example. A similar “state collapse” effect was observed in the 2010 Sony PlayStation 3 attack by the fail0verflow group: reusing the same nonce value.
In the ECDSA scheme, when signing firmware, it was possible to recover the secret key from two signatures by solving a comparison system
In both cases, the reason is the same: a deterministic or fixed parameter where the protocol requires true randomness.
3. Reduction of entropy space
The nominal requirements of BIP39 call for generating 128 or 256 bits of true entropy to produce 12- or 24-word mnemonic phrases, respectively. Formally, the search space for a correct implementation is:
The vulnerable implementation of CryptoJS.lib.WordArray.random(), due to the limited number of reachable internal states of the MWC generator with a narrow set of possible seed values from Math.random(), reduced the effective space to:
The entropy reduction coefficient can be expressed as:bit
Space in – options are completely iterable on consumer hardware (GPU clusters or cloud instances are capable of checking from to candidates per second when verified through address output and verification with the blockchain balance), which moves the attack from the theoretical to the practical plane.
A historical example: In 2013, a vulnerability in the SecureRandom Android implementation (Java Cryptography Architecture) led to predictable nonce values.
when signing Bitcoin transactions, allowing attackers to recover private keys from ECDSA signature pairs, similar to the PS3 incident. The lesson is the same: a weak source of entropy at the platform level translates into a critical vulnerability at the protocol level, using it as a “black box.”
4. Version history and the path of the defect to wallets
| Version / event | Date | Security status |
|---|---|---|
| Issue GitHub #7 “randomBytes is not random enough” | ~2014 (earlier) | A problem was found with Math.random() |
| CryptoJS 3.1.2-4, commit ff1f003 | June 2014 | A vulnerable MWC generator has been introduced. |
| CryptoJS 3.2.0 – 3.2.1 | 2014–2015 | Temporarily safe (native CSPRNG) |
| CryptoJS 3.3.0 | ~2015 | Rollback to MWC (to avoid breaking change) |
| ferrumnet/bip39 fork | until November 2019 | Dependency on vulnerable 3.x branch, fork abandoned |
| CryptoJS 4.0.0 | February 2020 | Fixed – native CSPRNG restored |
| CVE-2026-71851/GHSA-rg76-677x-56q9 | 2026 | Official publication of the vulnerability |
The defect’s propagation path illustrates a classic software supply chain problem: the fork ferrumnet/bip39 replaced a dependency randombytes (delegating calls to crypto.randomBytes/ crypto.getRandomValues) with a pure JavaScript implementation of CryptoJS for the sake of compatibility with React Native, thereby inheriting a hidden cryptographic defect at the transitive dependency level.
A historical example. A structurally identical scenario was observed in the Dual_EC_DRBG incident (2007–2013): the NIST-standardized generator contained a hidden kleptographic backdoor that allowed the internal state to be restored given knowledge of the elliptic curve’s secret parameters. As with CryptoJS, the issue remained undetected for years, hidden deep in the dependency chain of commercial cryptographic libraries (RSA BSAFE).
5. Pseudocode of vulnerable and correct implementations
// Уязвимый паттерн (CryptoJS < 4.0.0)
// Засеивание через Math.random(), НЕ криптографически стойкий источник
var m_w = init_from(Math.random());
var m_z = 0x3ade68b1; // наблюдаемая фиксация состояния
function mwcRandom() {
m_z = (36969 * (m_z & 0xFFFF) + (m_z >>> 16)) >>> 0;
m_w = (18000 * (m_w & 0xFFFF) + (m_w >>> 16)) >>> 0;
return ((m_z << 16) + m_w) >>> 0;
}
// Корректный паттерн (CryptoJS >= 4.0.0)
// Использование платформенного CSPRNG
function secureRandomWords(nBytes) {
return window.crypto.getRandomValues(new Uint8Array(nBytes));
// или в Node.js: crypto.randomBytes(nBytes)
}
6. Cryptanalytic marker: the mnemonic “illness blossom”
Ill Bloom researchers have found that, given a deterministic or predictable starting state of the JavaScript engine, the first reproducible mnemonic phrase generated in a vulnerable way is the “illness blossom” phrase, a phrase from a BIP39 dictionary (2048 words) whose indices are determined by the least significant bits of the first 128 or 256 bits of the MWC generator output at a fixed Formally, the mapping of a bit sequence to words in a dictionary is described as:
Where
— 132-bit sequence (128 bits of entropy + 4 bits of checksum), and
retrieves the 11-bit index of a word.
Such a marker acts as a “vulnerability fingerprint” – similar to how, in classical cryptanalysis, weak DES keys (e.g., all zero or all one subkeys) serve as a diagnostic indicator of a flawed key schedule implementation.
A historical example. In 1995, researchers Ian Goldberg and David Wagner discovered that the SSL implementation in Netscape Navigator seeded its random number generator with a combination of the process time, PID, and PPID—values with a combined entropy of approximately 20–25 bits—allowing session keys to be recovered in less than a minute on the hardware of the time. Like the “illness blossom” in CryptoJS, the specific recovered values became a kind of historical “signature proof” of the generator’s weakness.
7. Impact assessment and remedial measures
- CVSS v3.1: 9.0 (Critical); classifiers CWE-331 (Insufficient Entropy), CWE-338 (Use of Cryptographically Weak PRNG), CWE-334 (Small Space of Random Values).
- Affected applications confirmed to be affected include software wallets that use the fork
ferrumnet/bip39, including RRWallet, Bexo Wallet, and NanChat. - Recommended fix: Upgrade to
crypto-js 4.0.0+; Replace callsWordArray.random()towindow.crypto.getRandomValues()orcrypto.randomBytes(); Force rotation of all previously generated mnemonic phrases.
Conclusion
The case of CVE-2026-71851 demonstrates a consistent pattern in the history of applied cryptography: catastrophic vulnerabilities often arise not from weaknesses in the cryptographic primitives themselves (the elliptic curve secp256k1 and the BIP39 scheme as such remain reliable), but from the wrong choice of entropy source at the boundary between the platform and the library.
Technical Disclosure: The CryptoJS Randomness Vulnerability – scientific analysis: https://usde.ru/technical-disclosure-the-cryptojs-randomness-vulnerability-scientific-analysis/
Fixing a constant and the reproducibility of the “illness blossom” mnemonic serve as a clear cryptanalytic proof of how deterministic pseudo-seeding turns a theoretically huge key space into a practically enumerable set.
