CryptoJS.lib.WordArray.random(): Cryptanalytic Analysis of a Weak PRNG Vulnerability (Ill Bloom, CVE-2026-71851)

09.09.2026

CryptoJS.lib.WordArray.random(): Cryptanalytic Analysis of a Weak PRNG Vulnerability (Ill Bloom, CVE-2026-71851)

Source:  GitHub Security Advisory GHSA-rg76-677x-56q9 by Evan Vosberg, GitHub Advisory Database. Published: August 5, 2026. Additional sources for this investigation: Coinspect, “Ill Bloom Investigation,” and “Technical Disclosure: The CryptoJS Randomness Vulnerability.”
Identifiers:  CVE-2026-71851 · CVSS 3.1:9.0 (Critical), vector  AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H · CWE-331 (Insufficient Entropy), CWE-334 (Small Space of Random Values), CWE-338 (Use of a Cryptographically Weak PRNG).

Annotation

This paper presents a structured cryptanalytic analysis of the official security bulletin GHSA-rg76-677x-56q9, which describes a functional flaw  CryptoJS.lib.WordArray.random() in the crypto-js library (npm) versions < 4.0.0 [web:6][web:2]. The flaw is classified as exploiting a non-cryptographic pseudorandom number generator (PRNG) based on a modified George Marsaglia Multiply-With-Carry (MWC) algorithm initialized via  Math.random() [web:2][web:12]. This construction reduces the effective entropy space of nominally 128- and 256-bit queries to values ​​on the order of 239 And 247 [web:6][web:2], making brute-force enumeration computationally feasible on consumer hardware. The practical consequence was the recovery of private keys of BIP39 wallets and the theft of crypto assets worth at least $5–5.7 million in coordinated waves of withdrawals, documented by the research group Coinspect under the codename “Ill Bloom” [web:5][web:12].

1. Vulnerability Passport

ParameterMeaning
CVE identifierCVE-2026-71851 [web:6]
GHSA identifierGHSA-rg76-677x-56q9 [web:6]
Severity levelCritical, CVSS 3.1 = 9.0 [web:12]
CVSS vectorAV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H [web:12]
Class of Weakness (CWE)CWE-331, CWE-334, CWE-338 [web:12]
Affected versionscrypto-js < 4.0.0 (except 3.2.0 and 3.2.1) [web:6][web:3]
Corrected version4.0.0 (February 2020) [web:3]
The discoverer of the problemjuli (GitHub Advisory reporter), research — Coinspect [web:6]
Publication dateAugust 5, 2026 [web:6]

A historical parallel.  Assigning a CVE six years after the actual fix (4.0.0 was released in 2020) is reminiscent of the 2008 Debian OpenSSL vulnerability (CVE-2008-0166), where a defective patch that reduced the entropy of the random number generator remained undetected for over a year, and its effects on previously generated SSH keys persisted for years after the patch was released.

2. Technical nature of the defect

The standard (fixed) implementation  WordArray.random() in crypto-js delegates random byte generation to the platform’s native cryptographic source—  window.crypto.getRandomValues() in the browser or  crypto.randomBytes() Node.js [web:16]. A vulnerable implementation, introduced in June 2014 in a commit  ff1f003 as a response to issue #7 “randomBytes is not random enough,” replaced some of the calls  Math.random() with a custom implementation of the MWC generator [web:6][web:2].

2.1 Mathematical model of the MWC generator

Marsaglia’s classic Multiply-With-Carry generator is defined by the recurrence relation:xn=(a⋅xn−1+cn−1)againstb,cn=⌊a⋅xn−1+cn−1b⌋

Where a

 — multiplier, b

 — module (usually 232

), xn

 – another pseudo-random word, and cn

 — “carry” passed to the next iteration.

The cryptographic weakness of this design is that given a known or predictable seed, the internal state of the generator (x0,c0) completely determines the entire subsequent sequence of outputs. Since the seed was formed using  Math.random() a generator whose specification (ECMAScript) does not require cryptographic strength and in most implementations relies on a PRNG like xorshift128+ with limited internal entropy, the resulting space of reachable states turned out to be significantly smaller than the nominal bit depth of the query [web:2].

2.2 Quantitative assessment of entropy loss

Let Hnthem

 — the nominally requested entropy (128 or 256 bits), and Handff

 — the effective entropy achievable by the generator. According to an investigation by Coinspect:bitbitHandff(128)≈39 page,Handff(256)≈47 page

The search space reduction factor is:R=2Hnthem2Handff=2Hnthem−Handff

For 128-bit case: R=2128−39=289

 – that is, the actual number of options is reduced in 289

 times [web:6][web:2].

A historical parallel.  Similar arithmetic was applied in 2013 to an Android vulnerability  SecureRandomwhere insufficient OpenSSL PRNG initialization on Android led to nonce collisions. k

 in ECDSA Bitcoin wallet signatures: two signed messages with the same k

 allowed to restore the private key using the formulad=s1With2−s2With1r(s1−s2)againstn.

In the Ill Bloom case, the exploitation is different (seed guessing, not nonce guessing), but the result is the same: compromise of the private key due to a lack of true entropy.

3. Version timeline

VersionDateStatus GPS
< 3.1.2-4until June 2014Direct calls  Math.random() are also unsafe, but were not the subject of this bulletin [web:2]
3.1.2-4June 2014Introduced vulnerable MWC generator (commit  ff1f003) [web:6]
3.2.0 – 3.2.1—The platform’s native cryptographic source was temporarily used [web:3]
3.3.0—Rollback to a vulnerable MWC generator (change considered “breaking change”) [web:6][web:3]
3.3.0 – 3.x (all subsequent)until 2020Vulnerable generator persists [web:6]
4.0.0February 2020Complete replacement for the native Web Crypto API / Node.js  crypto [web:3][web:12]
GHSA-rg76-677x-56q9August 5, 2026Official CVE publication over 6 years after actual fix [web:6]

Historical parallel.  The situation in which secure behavior was temporarily introduced (3.2.0–3.2.1) and then reverted as a “breaking change” is structurally reminiscent of the history of rolling back TLS/SSL protocol downgrades (POODLE, 2014) and the re-enablement of weak cipher suites for the sake of backward compatibility—the tradeoff between migration ease and security systematically led to the long-term persistence of vulnerable configurations in production.

4. Path of defect propagation into the wallet ecosystem

The key link in the chain was a fork of the bip39 library  ferrumnet/bip39, adapted for React Native [web:2]. The original bip39 library obtains entropy through the [web:2] package  randombytes, which delegates calls to  crypto.randomBytes (Node.js) or  crypto.getRandomValues (browser) [web:2]. To avoid dependence on platform-specific APIs, the fork replaced this source with a pure JavaScript implementation of CryptoJS, thereby inheriting the vulnerable [web:2] PRNG. This fork has not received any commits since November 2019, meaning it remained “frozen” on the vulnerable version even after the release of the 4.0.0 [web:2] fix.

Schematically, the dependency chain looks like this:Wallet App→ferrumnet/bip39 (fork)→crypto-js < 4.0.0→MWC PRNG←Math.random()

A historical parallel.  The transitive spread of weak cryptography through forks and dependencies follows the pattern of the 2008 Debian OpenSSL incident, where a patch in one package (openssl) caused a cascading flaw in all derived keys and certificates generated on affected systems over a period of nearly two years.

5. Proof-of-Concept Methodology Reproduced by Coinspect

The investigation included a full cycle of offensive analysis [web:6]:

  1. Reimplementation of the behavior of a vulnerable function  WordArray.random().
  2. Enumeration of the achievable outputs of the internal PRNG.
  3. Converting entropy candidates into valid BIP39 mnemonic phrases.
  4. Derivation of private keys and addresses via relevant derivation paths (BIP32/BIP44) and networks.
  5. Comparison of received addresses with public blockchain data.
  6. Recovering private keys controlling funded addresses.

Formally, the derivation of BIP39 translates the entropy AND

 into a mnemonic phrase via a checksum and a dictionary of 2048 words:CS=SHA-256(AND)[0:ENT/32],M=split11(AND‖CS)

Where ENT

 — is the entropy length in bits, and each 11-bit group indexes a BIP39 dictionary word. If AND

 is selected from the space by power 239

 instead of 2128

, the number of possible mnemonic phrases collapses accordingly, and the attacker, instead of trying 2128

 only checks options 239

 — a problem that can be solved by parallel enumeration on a GPU cluster or even on a single modern workstation.

A historical parallel.  A similar methodology (PRNG reimplementation → seed bruteforce → key derivation → blockchain verification) was used in 2023 in the “Milk Sad” incident involving the libbitcoin-explorer library, where a weak Mersenne Twister seed initialized with timestamps allowed BIP39 mnemonics to be recovered and funds to be stolen from wallets created using a vulnerable utility  bx seed.

6. Economic and criminal damage

According to Coinspect’s on-chain analysis, the recorded waves of theft affected addresses on the Bitcoin, Ethereum, Polygon, Rootstock, and Tron networks; as of July 13, 2026, the lower bound of stolen funds across the two waves was approximately $5 million, and by August 5, 2026, the aggregate estimate had grown to approximately $5.7 million [web:6][web:5]. The first confirmed on-chain signs of exploitation date back to May 27, 2026 [web:15][web:11]. At least five vulnerable wallet applications have been confirmed: RRWallet, Bexo Wallet, NanChat, Bitcoin Libre, and Milo [web:5].

ApplicationFix status
RRWalletEnd of support, no fix released [web:5]
Bexo WalletFixed in version 20.1.0 [web:5]
NanChatFixed in version 1.3.0 [web:5]
Bitcoin LibreFixed in version 4 (July 2024) [web:5]
MiloEnd of support, no fix released [web:5]

Historical parallel.  The scale and mechanics of the theft (massive compromise of mnemonic phrases generated by a single defective component) are comparable to the Trust Wallet Chrome extension incident (2022–2023), where weak PRNG initialization in a specific version of the extension led to the theft of funds from users who generated wallets during a vulnerable period. Furthermore, later wallet updates failed to protect the already compromised keys, exactly as described in the Impact section of this bulletin.

7. Critical property: irreversibility of compromise

The bulletin explicitly emphasizes that applying PBKDF2, another key derivation function (KDF), or a cryptographic hash function on top of the output of a vulnerable generator does not restore the lost entropy [web:6]. This is a fundamental property of entropy as a measure of uncertainty: a deterministic transformation f cannot increase the entropy of the source.

Formally, for any measurable function f

 and a random variable X

:H(f(X))≤H(X)

Therefore, if H(X)≈39

 bit, then H(PBKDF2(X))≤39

 bit, regardless of the number of KDF iterations or the length of the output key.

The practical implications listed in the bulletin follow from this: updating the library does not strengthen a previously generated secret; importing the same mnemonic phrase into updated software does not fix the problem; previously generated secrets may remain vulnerable indefinitely; future deposits to a compromised address are also at risk of theft [web:6].

8. Recommendations for troubleshooting

For developers

  • Upgrade  crypto-js to version 4.0.0 or later; if possible, replace randomness generation with the native Web Crypto API or a  crypto Node.js module [web:6][web:16].
  • Audit direct, transitive and downstream dependencies for  crypto-js < 4.0.0 [web:6] versions.
  • Determine if a function has been used  WordArray.random() to generate cryptographically significant secrets [web:6].
  • Determine the time intervals and application versions in which the vulnerable generation path was active [web:6].
  • Treat all long-lived secrets generated through the vulnerable path as compromised and rotate them [web:6].
  • Notify affected users that installing the update is not sufficient if the long-term secret was generated by vulnerable code [web:6].

For wallet users

The only reliable measure is to create a new wallet with a new mnemonic phrase from a trusted source and transfer assets to new addresses; importing an existing phrase into updated software does not eliminate the risk [web:6][web:15].

9. Conclusion and scientific significance

Case CVE-2026-71851 is a textbook example of how a local architectural decision (replacing a cryptographically strong source with a “universal” custom PRNG for the sake of cross-platform compatibility) can create a systemic risk that spans multiple independent products through transitive dependencies in the npm ecosystem [web:2][web:6]. From a cryptanalytic perspective, the incident confirms two fundamental truths: first, the strength of KDFs and hash functions does not compensate for the lack of input entropy (H(f(X))≤H(X)); secondly, the “temporary” weakening of the cryptographic component for the sake of backward compatibility (rollback 3.2.0→3.3.0) has historically proven to be one of the most persistent sources of long-lived vulnerabilities in cryptographic software [web:6][web:3].


Источники:

CryptoJS.lib.WordArray.random(): cryptanalytic analysis of the Ill Bloom vulnerability (CVE-2026-71851): https://bitcrack.ru/cryptojs-lib-wordarray-random-cryptanalytic-analysis-of-the-ill-bloom-vulnerability-cve-2026-71851/


GitHub Security Advisory GHSA-rg76-677x-56q9 / CVE-2026-71851 [web:6]
Coinspect, «Ill Bloom: Investigating a Wallet Generation Vulnerability» [web:2]
Coinspect, «Technical Disclosure: The CryptoJS Randomness Vulnerability», illbloom.org [web:2]
illbloom.org, публичный чекер адресов и FAQ [web:15]
The Hacker News, «CryptoJS Weak RNG Behind $5.7 Million in Drains» [web:5]
sigintzero.com, «Ill Bloom: CryptoJS Weak PRNG Drains $5.7M» [web:12]
securityonline.info, «CryptoJS Randomness Vulnerability Drains Crypto Wallets» [web:11]