Technical Disclosure: The CryptoJS Randomness Vulnerability

09.09.2026

Technical Disclosure: The CryptoJS Randomness Vulnerability

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. mz=0x3ade68b1, 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 239 And 247 options instead of nominal ones 2128 And 2256, 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 215

 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 clarifyDouble subscripts: use braces to clarifyDouble subscripts: use braces to clarifyDouble subscripts: use braces to clarify

Where mz And mw — 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 clarifyDouble subscripts: use braces to clarify

Where f,g

 — deterministic output transformation functions Math.random()

 into 32-bit states.

The key cryptanalytic fact recorded by Ill Bloom Research Group is that the value is actually fixed mz=0x3ade68b1 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. k

 In the ECDSA scheme, when signing firmware, it was possible to recover the secret key from two signatures by solving a comparison system k≡(h1–h2)(s1–s2)–1(modn)

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:|S128|=2128≈3.4×1038,|S256|=2256≈1.16×1077

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:|S128′|≈239,|S256′|≈247

The entropy reduction coefficient can be expressed as:bitΔH=log2⁡|S128|–log2⁡|S128′|=128–39=89 bit

Space in 239–247 options are completely iterable on consumer hardware (GPU clusters or cloud instances are capable of checking from 109 to 1011 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. k

 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 / eventDateSecurity status
Issue GitHub #7 “randomBytes is not random enough”~2014 (earlier)A problem was found with Math.random()
CryptoJS 3.1.2-4, commit ff1f003June 2014A vulnerable MWC generator has been introduced.
CryptoJS 3.2.0 – 3.2.12014–2015Temporarily safe (native CSPRNG)
CryptoJS 3.3.0~2015Rollback to MWC (to avoid breaking change)
ferrumnet/bip39 forkuntil November 2019Dependency on vulnerable 3.x branch, fork abandoned
CryptoJS 4.0.0February 2020Fixed – native CSPRNG restored
CVE-2026-71851/GHSA-rg76-677x-56q92026Official 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 mz=0x3ade68b1Formally, the mapping of a bit sequence to words in a dictionary is described as:wi=BIP39[bits11(E,11i..11i+10)],i=0,…,11

Where E

 — 132-bit sequence (128 bits of entropy + 4 bits of checksum), and bits11

 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 calls  WordArray.random() to  window.crypto.getRandomValues() or  crypto.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 mz=0x3ade68b1 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.