
Material type: research paper
Date: July 5, 2026 (Cointelegraph publication context)
Subject: BIP39 mnemonic cryptographic security compromised due to a flawed CryptoJS entropy source.
Abstract. Ill Bloom is not an attack on SHA-256, BIP39, secp256k1, or signature algorithms per se. It is a practical cryptanalytic example of breaking the assumption of uniform randomness in secret generation. In a number of software wallets, the challenge CryptoJS.lib.WordArray.random() was used to generate BIP39 entropy. A vulnerable implementation based on a variant of the Multiply-With-Carry (MWC) generator compressed the effective search space from the standard 128/256 bits to approximately 39/47 bits. As a result, a mnemonic phrase, formally consisting of 12 or 24 words, could become a brute-force secret; from it, the seed, keys, and addresses were deterministically recovered, after which public blockchain activity was used as an oracle to select wallets with balances.
1. Context and fact of the incident
According to a Cointelegraph report on July 5, 2026, Coinspect warned of thousands of potentially vulnerable software wallets across the Bitcoin, Ethereum, Polygon, Rootstock, Tron, and Solana networks. At the time of the initial report, researchers attributed at least $5 million in active exploitation to the breach, citing weak randomness in recovery phrase generation as the source of the risk.
Coinspect’s investigation began in May 2026 with a mass withdrawal event. A key feature of the case is the time lag between the introduction of the root cause and the discovery of the consequences: the defective code in CryptoJS was introduced in June 2014, and vulnerable wallets, according to the investigation, could have been generated since at least 2018.
Cryptanalytic fact: the length of a phrase, the number of words, and even a valid BIP39 checksum do not prove cryptographic strength. Strength is determined primarily by the min-entropy of the source that generated the initial secret.
2. Wallet security model
A typical HD wallet builds a chain of “random entropy → BIP39 mnemonic → seed → BIP32/BIP44 derivation → private keys → public addresses.” BIP39 encodes entropy with a checksum and dictionary words, but does not add unpredictability to the already weak input.
LaTeX block 1 — BIP39 construction:
\[ CS = \operatorname{MSB}_{ENT/32}(\operatorname{SHA256}(ENT)) \]
\[ M = \operatorname{Encode}_{2048}(ENT \parallel CS) \]
where \(ENT\) is the original entropy of length 128 or 256 bits, \(CS\) is the checksum, \(M\) is the mnemonic.
When generated correctly, a 12-word mnemonic typically carries 128 bits of entropy, while a 24-word mnemonic carries 256 bits. The checksum reduces the number of valid word combinations to valid encodings, but its purpose is to detect input errors, not to enhance security.
LaTeX block 2 — transition from mnemonic to seed:
\[ seed = \operatorname{PBKDF2\!\text{-}\!HMAC\!\text{-}\!SHA512}(M,\; \texttt{«mnemonic»}\parallel P,\; 2048,\; 512) \]
where \(P\) is an optional BIP39 passphrase. In the absence of the optional passphrase, recovery of \(M\) completely reveals the seed.
3. The Essence of Ill Bloom
Coinspect’s technical disclosure attributes the issue to CryptoJS.lib.WordArray.random() and identifies it as CVE-2026-71851. In vulnerable versions, the function was not a CSPRNG: instead of the system’s cryptographic randomness source, a custom MWC pseudorandom generator was used.
| Property | Normal generation | Ill Bloom | Practical effect |
|---|---|---|---|
| The source of randomness | OS CSPRNG, for example crypto.getRandomValues , or crypto.randomBytes | CryptoJS MWC PRNG in a vulnerable path | The secret depends on the small internal state, not on the stated output length |
| Effective space of 128-bit ENT | About \(2^{128}\) | About \(2^{39}\) | Reduction by approximately \(2^{89}\) times |
| Effective space of 256-bit ENT | About \(2^{256}\) | About \(2^{47}\) | Reduction by approximately \(2^{209}\) times |
| Object of attack | A practically undisclosed secret | Candidate mnemonics with verifiable addresses | Mass offline generation and on-chain filtering are possible |
LaTeX block 3 — effective entropy:
\[ H_{\mathrm{eff}} \approx \log_2 |\mathcal{S}| \]
\[ H_{\mathrm{eff}}^{128} \approx 39, \qquad H_{\mathrm{eff}}^{256} \approx 47 \]
\[ \Delta H_{128}=128-39=89, \qquad \Delta H_{256}=256-47=209 \]
It is this compression of space, not cryptanalysis of the hash function or elliptic curve, that is the central mechanism. Just because the output appears to be 32 bytes long doesn’t mean it contains 256 bits of unpredictability: the output could be a long, deterministic unfolding of a much smaller state.
4. Why is this cryptanalysis
Strictly speaking, this is a cryptanalysis of the implementation and generation of the key material. The attacker doesn’t reverse the one-sidedness of PBKDF2, doesn’t find SHA-256 collisions, and doesn’t solve ECDLP for secp256k1; they shift the search from the astronomical key space to a small set of states of the faulty generator.
LaTeX block 4 — problem reduction:
\[ \text{Search for a private key in }[1,n-1] \quad \not\Rightarrow \quad \text{Ill Bloom attack} \]
\[ s \in \mathcal{S}_{\mathrm{MWC}} \Rightarrow ENT(s) \Rightarrow M \Rightarrow seed \Rightarrow \{A_i\} \]
\[ \text{Goal: find } s \text{ such that } \operatorname{Activity}(A_i)=1 \text{ or } \operatorname{Balance}(A_i)>0 \]
A public blockchain turns brute-force testing into a “generate-and-test” problem. For each valid state, an attacker can deterministically compute the mnemonic, obtain addresses via known derivation paths, and verify whether there is a transaction history or a non-zero balance. The address serves as a public marker of the correctness of the hypothesis; the private key does not need to be directly guessed.
Simplified analysis scheme
# Псевдокод для аудита/понимания, не инструкция по эксплуатации
for generator_state in candidate_state_space:
entropy = vulnerable_generator_model(generator_state)
mnemonic = bip39_encode(entropy, language, entropy_size)
seed = bip39_to_seed(mnemonic, optional_passphrase="")
for path in supported_derivation_paths:
addresses = derive_public_addresses(seed, path)
if has_public_onchain_activity(addresses):
record_for_responsible_disclosure(addresses, wallet_hypothesis)
A real-life example from cryptanalysis: attacks on weak keys in Debian OpenSSL (2006–2008) illustrate the same general principle: a flaw in the entropy source dramatically narrowed the set of possible keys, so the danger arose not from a breakdown of RSA/DSA as mathematical schemes, but from the predictable key generation process. Ill Bloom similarly undermines the secret generation step before standard cryptographic primitives are applied.
5. Historical supply chain
According to the technical disclosure, the MWC implementation appeared in CryptoJS 3.1.2-4 in June 2014 after discussions about its inadequacy Math.random(). Versions 3.2.0 and 3.2.1 temporarily used the system cryptographic source, but this change was reverted in 3.3.0 as potentially breaking compatibility; the native CSPRNG was restored in CryptoJS 4.0.0 in February 2020.
One of the documented downstream paths was a fork ferrumnet/bip39. In adapting to React Native, it replaced randombytes, which in the upstream project delegated the work of crypto.randomBytes either crypto.getRandomValues, with the pure JavaScript library CryptoJS. This is a clear example of supply-chain risk: a seemingly portable solution eliminates dependence on the platform API while simultaneously eliminating the platform’s cryptographic guarantee.
A critical audit rule: the presence of a vulnerable library version in the lockfile or APK does not, by itself, prove a wallet compromise. It is necessary to confirm the reachability of a specific call, the feed of its output into BIP39 entropy generation, the affected version timeframe, and the actual wallet parameters.
6. Investigation Methodology
Coinspect describes an iterative methodology: reproducing the faulty generation, generating candidate recovery phrases, deriving addresses, and comparing them with on-chain data. Detecting an active address doesn’t reveal which application created it, so the on-chain analysis was supplemented by open-source code review, dependency tracing, and reverse engineering of old APKs.
| Stage | Scientific task | Artifacts and evidence | An analogy from practice |
|---|---|---|---|
| RNG reproduction | Establish that the generator produces a small set of ENT | Source code, commit history, test vectors | Verifying Weak PRNGs in IoT/Embedded Devices |
| Listing configurations | Consider ENT size, BIP39 language, network and path | Parameter matrix, derivational patterns | Audit of HD wallets with multiple BIP44/BIP49/BIP84 paths |
| On-chain filtering | Separate used wallets from empty candidates | Transaction history, UTXO, tokens, clusters | Using a public key/address as a brute force verifier |
| App attribution | Link address sets to the wallet generator | Code, dependencies, historical APKs, ecosystem connections | Software provenance and forensic dependency analysis |
| Response | Reduce damage without publishing operating procedures | Address checker, developer contacts, staged disclosure | Coordinated vulnerability disclosure during active operation |
A real-life example from archival analysis: when investigating closed-loop or discontinued software, the current version is almost always insufficient. Coinspect explicitly emphasizes the need to analyze historical packages: Bitcoin Libre was confirmed using on-chain traces and a historical APK, and Milo Wallet was confirmed by reconstructing the generation process from an archived application. A similar forensic approach is used when investigating compromises where malicious or vulnerable logic has disappeared from the current repository.
7. Configurational combinatorics
The study isn’t limited to a single mnemonic for the PRNG state. Different applications could have used 128- or 256-bit entropy, English or Chinese BIP39 lists, different networks, and different derivation paths. The same seed generates multiple keys and addresses, and an incorrect path makes the correct seed invisible to simple scanning.
LaTeX block 5 — estimation of the number of checks:
\[ N_{\mathrm{checks}} \approx |\mathcal{S}| \cdot L \cdot P \cdot C \cdot A \]
where \( |\mathcal{S}| \) is the number of generator states, \(L\) is the number of wordlist languages, \(P\) is the number of derivation paths, \(C\) is the number of networks/configurations, \(A\) is the number of addresses per path.
The practical value of this formula lies in explaining why the study required significant computational resources even after entropy dropped to 39–47 bits. The problem becomes feasible, but remains multidimensional: the researcher must avoid the false conclusion “addresses not found” if a specific language, path, account index, or address format is not covered.
8. Verified applications
The list below reflects only the applications Coinspect was able to confirm, not a complete list of potentially affected software. Discontinued products are particularly important: users cannot obtain a patch, and a compromised seed phrase remains compromised regardless of other application updates.
| Wallet/software | Status | Elimination | Confirmation type | Cryptanalytic meaning |
|---|---|---|---|---|
| RRWallet (RenrenBit) | Discontinued | No fix | Public source code | Direct testing of a vulnerable generation process |
| Bexo Wallet | Active | Fixed in 20.1.0 | Dependency analysis; controlled validation with affected mnemonics | First confirmed bridge from incident to cause |
| NanChat | Active | Fixed in 1.3.0 | Source code and dependency tracing | Confirming the reachability of defective code in wallet flow |
| Bitcoin Libre | Active | Fixed in version 4 | On-chain analysis and historical APK | An example of the importance of archives of old builds |
| Milo | Discontinued | No fix | On-chain pattern and historical APK | Clustering token activity as an attribution trace |
A telling example of on-chain attribution: when analyzing a 256-bit subset, Coinspect noticed that 96% of wallets received the same Milo token on Polygon. This cluster isn’t a mathematical proof in itself, but it formed a testable hypothesis about the app; subsequent analysis of the APK confirmed the compatibility of its wallet-generation flow with the identified vulnerable wallets.
9. Limitations and evidence
The public address contains no metadata about the program that created the wallet. Therefore, the proof chain must be multi-source: matching addresses and transactions is useful for search, but final technical confirmation requires call graph analysis and evidence that the weak function was actually used to generate the BIP39 entropy.
The loss data should be interpreted as a lower estimate: Coinspect and the media have recorded the amounts and addresses already withdrawn, but it is impossible to reliably prove complete coverage of all applications, versions, languages, and network configurations. The absence of a match in a known set does not constitute a cryptographic security certificate, but merely a result of the coverage available to the researchers at the time of the audit.
10. Disclosure during an active attack
Ill Bloom reveals the conflicting goals of responsible disclosure. Full publication of brute-force optimizations and comprehensive operating parameters could make it easier for attackers to scale their attacks, while too late disclosure leaves owners of already predictable wallets unable to transfer funds.
Coinspect chose a staged disclosure: first, an address checker, on-chain analysis, and coordination with affected parties; then, a technical explanation of the root cause and verified applications. For the scientific community, this demonstrates that research reproducibility and operational security don’t always align.
11. Practical measures
For the wallet owner
- Check public addresses using the official Ill Bloom checker; the address verification service should not require a seed phrase, private key, signature, or approval.
- If a match is confirmed, consider the entire original recovery phrase compromised, even if the specific address is still empty or has not been touched.
- Create a new wallet with a new phrase on a trusted device, preferably a hardware one, and transfer assets to the new addresses.
- Do not import the old phrase into the “updated” application as a fix: such an import does not increase the entropy of the already created secret.
For the developer
// Безопасный принцип для web/JS: источник — системный CSPRNG.
const entropy = new Uint8Array(32);
crypto.getRandomValues(entropy); // браузерный Web Crypto API
// В Node.js используйте crypto.randomBytes(32).
// Не используйте Math.random(), пользовательские PRNG или CryptoJS WordArray.random()
// для ключей, nonce, salt с секретным назначением и BIP39-энтропии.
A real-life example of an engineering error: replacing a system API with a pure JavaScript implementation for the sake of cross-platform compatibility may seem like a neutral refactoring, but in key generation, it changes the trust boundary. Upstream bip39 used randombytes delegation to system sources, while the described downstream fork for React Native replaced this line with CryptoJS—thus changing the cryptographic properties of the entire system.
For the auditor
- Conduct data-flow analysis from the ENT generation point to BIP39 encode, rather than limiting yourself to SBOM scanning of vulnerable packets.
- Inventory versions, lockfile, transitive dependencies, historical releases, APKs/IPAs, and branches that previous users may have used.
- Test platform fallbacks: Browser, Node.js, React Native, WebView, and polyfill layers often use different sources of randomness.
- Test min-entropy and generator independence on reproducible test vectors without placing real user phrases in the test infrastructure.
- Plan user migration as a root secret rotation, not as an in-place library upgrade.
12. Conclusions
Ill Bloom demonstrates a fundamental property of applied cryptography: strong standards don’t compensate for predictable key material. BIP39 correctly encodes ENT, PBKDF2 correctly derives the seed, and secp256k1 correctly constructs keys—but the entire chain becomes weak if the ENT has not 128/256 bits, but around 39/47 bits of effective entropy.
For a cryptanalyst, this is a case study in search space reduction; for a developer, it’s about rigorous CSPRNG selection and dependency chain control; for response specialists, it’s about a combination of on-chain forensics, analysis of archived builds, and careful disclosure during an ongoing theft. The main object of migration here is not the application, but the secret: funds must be transferred to a wallet recreated from cryptographically secure entropy.
Sources
Cointelegraph – “Coinspect Warns Thousands of Wallets Vulnerable to Ill Bloom” (05/07/2026): cryptanalytic analysis: https://alpinvest.ru/cointelegraph-coinspect-warns-thousands-of-wallets-vulnerable-to-ill-bloom-07-05-2026-cryptanalytic-analysis/
- Cointelegraph. Coinspect Warns Thousands of Wallets Vulnerable to Ill Bloom , 07/05/2026.
- Coinspect. Ill Bloom: Investigating a Wallet Generation Vulnerability During Active Exploitation .
- Ill Bloom Research. Technical Disclosure: The CryptoJS Randomness Vulnerability .
- Ill Bloom Research. Identifying the Wallets Behind Vulnerable Recovery Phrases .
- GitHub Security Advisory: GHSA-rg76-677x-56q9; CVE-2026-71851 (listed in Ill Bloom’s technical disclosure).
