
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 And [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
| Parameter | Meaning |
|---|---|
| CVE identifier | CVE-2026-71851 [web:6] |
| GHSA identifier | GHSA-rg76-677x-56q9 [web:6] |
| Severity level | Critical, CVSS 3.1 = 9.0 [web:12] |
| CVSS vector | AV: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 versions | crypto-js < 4.0.0 (except 3.2.0 and 3.2.1) [web:6][web:3] |
| Corrected version | 4.0.0 (February 2020) [web:3] |
| The discoverer of the problem | juli (GitHub Advisory reporter), research — Coinspect [web:6] |
| Publication date | August 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:
Where
— multiplier,
— module (usually
),
– another pseudo-random word, and
— “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 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
— the nominally requested entropy (128 or 256 bits), and
— the effective entropy achievable by the generator. According to an investigation by Coinspect:bitbit
The search space reduction factor is:
For 128-bit case:
– that is, the actual number of options is reduced in
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.
in ECDSA Bitcoin wallet signatures: two signed messages with the same
allowed to restore the private key using the formula
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
| Version | Date | Status GPS |
|---|---|---|
| < 3.1.2-4 | until June 2014 | Direct calls Math.random() are also unsafe, but were not the subject of this bulletin [web:2] |
| 3.1.2-4 | June 2014 | Introduced 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 2020 | Vulnerable generator persists [web:6] |
| 4.0.0 | February 2020 | Complete replacement for the native Web Crypto API / Node.js crypto [web:3][web:12] |
| GHSA-rg76-677x-56q9 | August 5, 2026 | Official 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:
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]:
- Reimplementation of the behavior of a vulnerable function
WordArray.random(). - Enumeration of the achievable outputs of the internal PRNG.
- Converting entropy candidates into valid BIP39 mnemonic phrases.
- Derivation of private keys and addresses via relevant derivation paths (BIP32/BIP44) and networks.
- Comparison of received addresses with public blockchain data.
- Recovering private keys controlling funded addresses.
Formally, the derivation of BIP39 translates the entropy
into a mnemonic phrase via a checksum and a dictionary of 2048 words:
Where
— is the entropy length in bits, and each 11-bit group indexes a BIP39 dictionary word. If
is selected from the space by power
instead of
, the number of possible mnemonic phrases collapses accordingly, and the attacker, instead of trying
only checks options
— 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].
| Application | Fix status |
|---|---|
| RRWallet | End of support, no fix released [web:5] |
| Bexo Wallet | Fixed in version 20.1.0 [web:5] |
| NanChat | Fixed in version 1.3.0 [web:5] |
| Bitcoin Libre | Fixed in version 4 (July 2024) [web:5] |
| Milo | End 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 cannot increase the entropy of the source.
Formally, for any measurable function
and a random variable
:
Therefore, if
bit, then
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-jsto version 4.0.0 or later; if possible, replace randomness generation with the native Web Crypto API or acryptoNode.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 (); 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]
