Ill Bloom: A Cryptanalytic Analysis of Crypto Wallet Compromises Due to a Weak Random Number Generator in CryptoJS

09.09.2026

Ill Bloom: A Cryptanalytic Analysis of Crypto Wallet Compromises Due to a Weak Random Number Generator in CryptoJS

Research paper.  Topic:  CryptoJS Weak RNG Behind $5.7 Million in Drains Affects Five Crypto Wallet Apps . Based on The Hacker News publication of August 6, 2026, and primary materials from Coinspect/GitHub Security Advisory.

This article examines the Ill Bloom incident—an exploitation of insufficient entropy in the function  CryptoJS.lib.WordArray.random()used by certain crypto wallets to generate BIP39 recovery phrases. According to on-chain analysis by Coinspect, the confirmed lower bound on damage as of July 13, 2026, was $5,690,922. The attack did not break ECDSA, secp256k1, SHA-256, PBKDF2, or blockchain consensus: it reduced the initial secret space to a brute-forceable size before running the standard cryptographic transformations.

The paper examines a mathematical model of entropy loss, the lifecycle of vulnerable code, a methodology for offline mnemonic brute-force and subsequent on-chain correlation, the status of five applications, and migration measures. The central cryptanalytic conclusion is that the strength of a hierarchical wallet is limited by the minimum input entropy, and deterministic KDFs and hash functions are unable to recover the lost randomness.

Keywords:  CryptoJS, Ill Bloom, CSPRNG, BIP39, PBKDF2, HD wallet, entropy, cryptanalysis, Math.random(), MWC, keyspace enumeration, vulnerability management.

Statement of the problem

The BIP39 mnemonic phrase is perceived by users as “24 random words,” but its cryptographic strength is determined not by its dictionary or mapping length, but by the entropy  ENTwith which it was generated. If the source of randomness is predictable or has little internal state, the BIP39 format merely encodes a weak secret in a readable form.

The affected CryptoJS branch used a Multiply-With-Carry (MWC) generator initialized with a JavaScript value  Math.random(), rather than the system CSPRNG. As a result, the requested 128 or 256 bits did not actually mean 128 or 256 independent bits: the researchers estimated the effective space to be approximately 128  2^39 and 256  2^47 variants, respectively.

Facts of the incident

ParameterEstablished factCryptanalytic meaning
First sweepMay 27, 2026; approximately $3.14 million; 431 accounts.The observed batch purge is consistent with the pre-computed weak seed dictionary and automated balance checking.
Second sweepMay 30 – July 13, 2026; approximately $2.55 million; addresses associated with 522 seeds.The repeatability of the operation shows that the compromise is not a one-off, but rather a reproducible algorithmic one.
A major episodeAround 2.18 million USDT from one Tron account on July 4, 2026.A single weak seed can control assets and addresses across multiple networks.
Lower damage estimateUS$5,690,922 as of July 13, 2026.This is not an estimate of all vulnerable wallets, but a measurable minimum of identified transactions.
Scope of the study2,114 identified seeds and associated addresses across Bitcoin, Ethereum, Tron, Rootstock, and Polygon.Deterministic derivation allows one candidate secret to be associated with multiple public addresses.

Interpretation limitations.  The amounts listed are lower bounds, not the full extent of the losses. A negative public verification result for an address only indicates the address’s absence from the published dataset; it does not prove the cryptographic security of the phrase.

Affected applications

ApplicationDisclosure statusPractical consequence
RRWalletDiscontinued; no fix available.Phrases created through a vulnerable path must be considered compromised and migrated.
Bexo WalletA fix was reported in 20.1.0; at the time of The Hacker News’ review, the corresponding build had not yet been confirmed in stores.You can’t rely solely on the version number from an unofficial source; you should check the official changelog and the available build.
NanChatVersions prior to 1.3.0 are considered affected; fixed in 1.3.0, migration tool added.The patch prevents the generation of new weak seeds, but does not change those already created.
Bitcoin LibreThe fix was announced in version 4, released in July 2024.It is necessary to evaluate the date and path of creation of a specific wallet, and not just the currently installed version.
MiloDiscontinued; no fix available.It requires generating a completely new seed in a trusted environment and transferring all assets.

For RRWallet, Bexo, Bitcoin Libre, and Milo, the full ranges of affected versions are not publicly disclosed. Therefore, the correct risk model is conservative: if a phrase could have been created via a vulnerable route, it should be revoked regardless of where it was later imported.

Compromise chain

The attack consists of deterministic computations on public data and does not require victim interaction, phishing, backup theft, or key extraction from the device. The critical error occurs at the moment of initial entropy generation.

  1. The vulnerable application calls  WordArray.random() to obtain the material  ENT.
  2. A weak MWC generator produces a sequence whose effective uncertainty is significantly smaller than the nominal size of the requested array.
  3. The entropy is converted into a BIP39 mnemonic, then through PBKDF2-HMAC-SHA512 to a seed, from which the HD algorithm derives keys and addresses.
  4. The attacker enumerates weak space candidates, performs the same public transformations, and checks the derived addresses against the public blockchain.
  5. Once the balance is detected, the attacker signs the transaction with the same legitimate private key and transfers the funds.

Illustrative audit code

Below is secure pseudocode demonstrating the anti-pattern. It’s intended to detect flawed architecture, not to generate secrets or brute-force wallets.

// АНТИ-ПАТТЕРН: не использовать для ключей, сидов, nonce, токенов.
const entropy = CryptoJS.lib.WordArray.random(32);
const mnemonic = entropyToBip39(entropy);

// ПРАВИЛЬНЫЙ ПРИНЦИП: источник ОС / Web Crypto CSPRNG.
const bytes = new Uint8Array(32);
crypto.getRandomValues(bytes);
const mnemonicSafe = entropyToBip39(bytes);

A real-life historical analog.  In 2008, a buggy patch in Debian OpenSSL dramatically reduced the key space; the practical consequence was the ability to enumerate predictably generated keys. The general principle with Ill Bloom is the same: a cryptographic algorithm can be standard and correct, but its security is compromised by a flaw in random initialization.

Mathematical model

Nominal and effective entropy

Let  S be the set of all possible values, and let the probabilities of their occurrence be  p_i. The minimum entropy, conservatively characterizing the probability of the best guess, is defined as follows:

H_min(S) = -log_2(max_i p_i)

For a uniform 128-bit source, the number of variants is  2^128. For a 256-bit source, it is  2^256. In the case under study, the effective space estimates were approximately  2^39 and  2^47.

N_nominal(128) = 2^128; N_eff(128) ≈ 2^39
N_nominal(256) = 2^256; N_eff(256) ≈ 2^47

Therefore, the losses in the margin of safety are estimated as:

ΔH_128 ≈ 128 – 39 = 89 bits
ΔH_256 ≈ 256 – 47 = 209 bits

This isn’t a “strength reduction of a few percent,” but an exponential reduction in space. The candidate number ratio for the 128-bit case is:

2^128 / 2^39 = 2^89

That is, the attacker moves from a practically inaccessible space to a problem suitable for parallel offline enumeration.

BIP39 does not add entropy

In BIP39, the checksum is calculated by hashing the original entropy, rather than adding independent randomness. For  ENT entropy bits, the checksum length is  CS = ENT / 32, and the mnemonic stream length is  ENT + CS; the number of words is:

CS = ENT / 32
MS = ENT + CS
Words = MS / 11

For example,  ENT = 128 yields  CS = 4,  MS = 132 and 12 words. However, this does not imply 132 bits of secrecy: the checksum depends deterministically on the original  ENT, so the cryptographic strength remains limited by the properties of the random source.

PBKDF2 does not fix weak secrets

The BIP39 seed is a deterministic function of the mnemonic and passphrase:

seed = PBKDF2-HMAC-SHA512(password = mnemonic, salt = “mnemonic” || passphrase, c = 2048, dkLen = 64)

If the set of admissible mnemonics has a cardinality no greater than  2^k, then the set of deterministically obtained seeds does not become larger  2^k in terms of guessability of the input secret. Generally, for a deterministic transformation  f:

|f(X)| ≤ |X|, H_min(f(X)) ≤ H_min(X)

Hashing and PBKDF2 may slow down one candidate verification, but they don’t introduce new unpredictability. This is a fundamental fact of cryptanalysis of randomness sources: “random-looking output” is not the same as “high-entropy output.”

Estimating the cost of enumeration

At a candidate processing rate  R of 10 …

T_expected ≈ 2^(k-1) / R

For ,  k = 39 the average number of attempts is about  2^38; for  k = 47 , it’s about  2^46. Actual performance depends on the number of derivation paths, networks, addresses being checked, BIP39/PBKDF2 implementation, and hardware, but it’s the exponential value of , not the length of the mnemonic string, that’s crucial  k.

Cryptanalytic interpretation

Ill Bloom is a key generation attack, not an elliptic curve attack. The ECDLP problem for a correctly chosen secp256k1 private key was not simplified; instead, the attacker was able to reproduce the input secret itself and routinely derive valid keys.

LayerStatus in incidentConclusion
EntropyCompromised by a weak PRNG.Root cause.
BIP39Correctly encodes ENT and checksum into words.Is not a source of independent randomness.
PBKDF2-HMAC-SHA512Deterministically prints the seed.Does not increase the min-entropy of the mnemonic.
BIP32/HD derivationDeterministically outputs child keys and addresses.Allows you to test one candidate across multiple networks and paths.
ECDSA/secp256k1No signs of cryptanalytic attack are shown.The private key was reproduced via a weak seed.
BlockchainPublicly discloses addresses, balances and transactions.Provides a verifiable oracle for searching candidates.

A real-world historical analog.  ECDSA nonce generation flaws, including the Android Bitcoin RNG incident of 2013, led to the extraction of private keys without “breaking” the cryptocurrency itself. While the mechanism was different—the weakness affected the signature’s nonce, not the BIP39 seed—the overall lesson is the same: cryptography breaks down when one-time or root secrets are insufficiently unpredictable.

Origin of the defect

According to a public analysis, a vulnerable MWC generator initialized by  Math.random()was introduced in CryptoJS in June 2014. Versions 3.2.0 and 3.2.1 used native cryptographic randomness, but the weak implementation was reverted in 3.3.0 for backward compatibility reasons; version 4.0.0 finally returned native randomness in February 2020.

This demonstrates the danger of the simplistic “update dependencies within the major branch” policy. An upgrade within 3.x could have downgraded an application from a temporarily patched version to a vulnerable one. Advisory GHSA-rg76-677x-56q9 classifies versions below 4.0.0 as affected, but exploitation depends not on the package’s presence, but on calling a vulnerable function for security-sensitive values.

Dependency supply route

Coinspect identified the  ferrumnet/bip39 React Native fork as one of the paths where the standard cryptographic randomness source of the BIP39 upstream package was replaced with CryptoJS. This is more important than a simple  crypto-js lockfile search: the risk is determined by the specific data flow from a weak RNG to the generation of a phrase, key, nonce, token, or other security-critical value.

# Пример безопасной процедуры статического аудита (команды адаптируйте к проекту).
grep -RIn --include='*.js' --include='*.ts' \
  'CryptoJS\.lib\.WordArray\.random\|Math\.random' src/ packages/

npm ls crypto-js
npm audit --omit=dev

A real-world historical analog. The event-stream  dependency incident   in npm (2018) demonstrated that a transitive dependency can become a critical point of trust. In Ill Bloom, the analogous engineering problem is not the injection of malicious code, but the subtle substitution of a safe source of randomness for an unsafe one at the dependency or fork level.

Investigation methodology

A proper research methodology should reproduce the causal chain without accessing other people’s seed phrases and private keys. The goal of protection is to determine whether a specific generation process could have produced predictable values ​​and then organize a secure migration.

  1. Capture artifacts: application version, wallet creation date, platform, package-lock/yarn.lock, source code, or SBOM.
  2. Build a data flow: from RNG invocation to  entropyToMnemonicderivation  mnemonicToSeedand key import.
  3. Check the real source of entropy: Web Crypto  crypto.getRandomValues, Node.js  crypto.randomBytes, OS API or hardware RNG; don’t be limited by the dependency name.
  4. Compare the version with the defect timeline and official supplier bulletins.
  5. Use the published Coinspect checker only with the address, never sharing the recovery phrase, private key or keystore with a third party.
  6. If there is a reasonable risk, create a new independent seed on a trusted device and transfer the assets; then check the residual addresses, tokens, staking, and contract permissions.

Ethical boundary.  Listing candidates, scanning other people’s addresses for the purpose of withdrawing funds, or using discovered keys is illegal and does not constitute security research. A scientifically sound audit should work with consistent test data, proprietary keys, or an isolated lab environment.

Recommendations for users

  1. If the phrase was generated by the affected app or its origin cannot be determined, consider it potentially compromised.
  2. Don’t just update your app: updating stops vulnerable generation in the future, but doesn’t change the mathematical predictability of the old seed.
  3. Generate a new phrase using updated trusted software with a CSPRNG or a hardware wallet that generates a seed inside the device.
  4. Transfer all assets to new addresses: native coins, tokens, NFTs, funds in linked accounts, and networks supported by the same seed.
  5. Save your new phrase offline and never enter it into websites, chatbots, “checkers,” or support forms.
  6. For NanChat, if your wallet was created before version 1.3.0, follow the official migration mechanism. For Bexo, please confirm that you have actually installed the build with the fix.

Recommendations for developers

ControlRequirementThe criterion being tested
The source of randomnessUse only CSPRNG OS or platforms.Web:  crypto.getRandomValues; Node.js:  crypto.randomBytes; mobile: protected OS API.
Banning weak APIsExclude  Math.random()homemade PRNGs and compatibility fallbacks from secret creation paths.Static lint/Semgrep rules and code review block such calls.
SBOM and lock filesTake into account transitive dependencies and forks.The build is reproducible, versions and hashes of artifacts are fixed.
TestingCheck the source of bytes and the absence of silent fallbacks.Negative tests simulate the unavailability of the CSPRNG and require fail-closed behavior.
Version controlAnalyze changelogs and security advisories, rather than relying solely on major/minor semantics.An update cannot revert a known defect without an explicit exception in CI.
Incident ResponseProvide migration and address checker without entering secrets.The user can generate a new seed and transfer assets without revealing the old one.
// Пример fail-closed обёртки для браузерной среды.
export function secureRandomBytes(length) {
  if (!globalThis.crypto?.getRandomValues) {
    throw new Error('CSPRNG unavailable: secret generation aborted');
  }
  const out = new Uint8Array(length);
  globalThis.crypto.getRandomValues(out);
  return out;
}

A real-world historical analog.  The ROCA vulnerability (2017) affected RSA keys generated by certain hardware modules: formally valid keys had a structure that reduced the search space. In both cases, secure migration requires issuing new key material; “reinstalling the application” or changing the interface does not fix the weakness of an already issued secret.

Discussion

The incident highlights the difference between a cryptographic primitive and a cryptographic system. Even robust SHA-512, HMAC, PBKDF2, BIP32, and secp256k1 cannot compensate for low entropy at the root of the chain. This type of error is particularly dangerous in HD wallets, as a single seed can deterministically control addresses and assets across multiple ecosystems.

From a risk management perspective, a vulnerability should be classified based on its actual use. The presence of a CryptoJS version below 4.0.0 in a project requires investigation, but does not in itself prove an exploitable vulnerability; the critical vulnerability is the  WordArray.random() generation of sensitive data. The converse is also true: a patched package does not retroactively “fix” mnemonics released before the update.

Conclusion

Ill Bloom is a prime example of cryptanalytic compromise through entropy reduction, rather than through the destruction of modern cryptographic algorithms. Confirmed losses of at least $5.69 million and two waves of withdrawals demonstrate that a flawed RNG selection can turn a theoretically unachievable brute-force attack into a practical offline operation.

For users, the only correct response to a suspiciously generated phrase is to generate a new independent seed and transfer funds. For developers, the main lesson is that key generation must have a minimum trusted basis: a platform-specific CSPRNG, fail-closed if unavailable, transitive dependency control, reproducible builds, and an audit of the actual entropy flow before wallet release.

Sources

Ill Bloom: Cryptanalytic Analysis of CryptoJS Weak RNG: https://dynet.ru/ill-bloom-cryptanalytic-analysis-of-cryptojs-weak-rng/

  1. Swati Khandelwal.  “CryptoJS Weak RNG Behind $5.7 Million in Drains Affects Five Crypto Wallet Apps .” The Hacker News, August 6, 2026. URL:  thehackernews.com  (accessed September 7, 2026).
  2. GitHub Security Advisory GHSA-rg76-677x-56q9.  crypto-js: Insufficient Entropy in Cryptographic Secret Generation . URL:  github.com .
  3. Coinspect.  Ill Bloom: Investigating a Wallet Generation Vulnerability . URL:  coinspect.com .
  4. BIP-0039.  Mnemonic code for generating deterministic keys . Bitcoin Improvement Proposals. URL:  github.com/bitcoin/bips .
  5. NIST SP 800-90B.  Recommendation for the Entropy Sources Used for Random Bit Generation . National Institute of Standards and Technology.