Skip to content
RESEARCH INDEX BREACHROAD / INTELLIGENCE NOTE

CryptoJS and Ill Bloom: a 12-year-old weak RNG cost at least $5.7 million

WordArray.random() produced recoverable seeds in five wallet apps. We examine entropy, on-chain investigation and safe fund migration.

PUBLIC RESEARCH
AUTHOR
/ CEO of Breachroad · OSCP · PNPT
PUBLISHED
6 August 2026
READING TIME
12 min read
TOPIC
Threats and Incidents
CryptoJS and Ill Bloom: a 12-year-old weak RNG cost at least $5.7 million

A Coinspect investigation connected the Ill Bloom campaign to CryptoJS.lib.WordArray.random(), a function used for years to create cryptographic material in JavaScript applications. At least five wallets used it to generate recovery phrases with insufficient or predictable entropy. Analysis of two sweeping waves placed confirmed losses at a minimum of $5.7 million.

The attacker did not break encryption or a blockchain. Private keys can have the correct length and format yet remain weak when a generator chooses them from a small reproducible set. An attacker calculates candidates offline, checks the corresponding addresses and moves funds without interacting with the victim.

Where the weakness originated

Historical CryptoJS versions relied on JavaScript randomness mechanisms that did not guarantee cryptographic quality across every browser and mobile application container. WordArray.random() looked like an API for random bytes, so developers used it for seeds and mnemonic phrases without validating the underlying entropy source.

If an input has fewer unpredictable bits than its output claims, hashing does not create new information. A long seed may simply be a deterministic expansion of a short PRNG state. The attacker cares about the possible-state count and whether time, platform or call order can be reconstructed.

The Ill Bloom project material connects source analysis, reverse engineering of withdrawn releases and transaction tracing across several chains. Coinspect identified address families derived from weak phrases and then observed coordinated sweeps. That is stronger evidence than the presence of an old library alone: technical cause and asset movement align.

Who needs to act

The risk concerns wallets that generated a new phrase with vulnerable code. Updating the app does not strengthen an existing seed. Importing the old phrase into a safe release also leaves funds under a key derived from the same weak entropy.

A user needs a new wallet and a new phrase produced by a verified CSPRNG, followed by an asset-transfer transaction. The migration should use a clean device, and users must avoid fake “repair tools” asking them to enter the mnemonic.

Plan for vendors and users

  1. Identify every app version and code path that generated keys, nonces, tokens or recovery phrases.
  2. Replace generic randomness with an operating-system CSPRNG such as Web Crypto crypto.getRandomValues(), and fail closed when it is unavailable.
  3. Add tests for fallback to Math.random(), repeatability after restart and insufficient output diversity.
  4. Notify users in language that explains the need for a new phrase, not merely an application update.
  5. Do not build an online “scanner” that requests a seed; verification should use public addresses or run offline.
  6. Monitor known on-chain patterns and provide a safe, prioritised fund-migration path.
  7. Treat the random generator and runtime environment as part of cryptographic and supply-chain review.

Investigating a loss of funds

Incident responders should preserve more than the wallet address and transaction history. They need the application version, lockfile, JavaScript bundle, wallet-generation path, device clock and entropy sources available in that runtime. Those artefacts help distinguish theft of a sound key after creation from a key that was predictable from the beginning. Reinstalling the application before preservation may destroy the most useful evidence.

Developers need a test that fails a build when a secure CSPRNG is unavailable; a generator must never silently fall back to a weaker function. An SBOM should record the bundled library version because the number in package.json does not always match code delivered to users. New wallets should separate key generation from the UI and implement it in a small auditable component backed by the operating system’s cryptographic interface.

Facts versus conclusions

Coinspect connects the code, five applications and transactions, and provides a lower-bound loss estimate. This does not mean every project importing CryptoJS generated weak keys. The precise function, version and environment determine exposure.

Breachroad’s conclusion is that an update fixes future generation but not previously created secrets. Developer security training and web and API penetration testing should cover entropy provenance and safe cryptographic-data migration.

SHARE / COPY