Ill Bloom Research – “Technical Disclosure: The CryptoJS Randomness Vulnerability”

11.09.2026

Ill Bloom Research - “Technical Disclosure: The CryptoJS Randomness Vulnerability”

Research paper · cryptography, cryptanalysis, wallet security · September 2026

Abstract.  This paper analyzes vulnerability CVE-2026-71851, discovered by Ill Bloom Research  CryptoJS.lib.WordArray.random(). The key cryptanalytic fact is not a “cipher weakness” or a brute-force attack per se: the nominally 128- or 256-bit BIP39 input in the affected generation chain had an effective space cardinality of approximately 239 and  247 . Consequently, the computational strength of secrets was determined by the source entropy, not the output array size, SHA-256, PBKDF2, or secp256k1 strength. The origin of the flaw, the dependency path in React Native, the applicability limits, historical analogs, and a secure response procedure are discussed.

Keywords:  CSPRNG, entropy, CryptoJS, BIP39, MWC, CVE-2026-71851, cryptanalysis, dependency audit, JavaScript, React Native, key management.

1. Statement of the problem

Ill Bloom Research found that a number of recovery phrases were generated by wallets using CryptoJS’s weak randomness source. For the required 128 and 256 bits of entropy, the study indicates effective search spaces of approximately 239 and  247 states  ; this transforms the problem from cryptographically intractable to a finite offline brute-force search followed by verification of derived addresses and their state on the blockchain.

The vulnerability, identified as CVE-2026-71851, is specifically related to its use  WordArray.random() with sensitive values. The mere presence of a package  crypto-js version earlier than 4.0.0 in the dependency tree does not prove a compromise: data flow must be traced from the call to the vulnerable function to the generation of the mnemonic, private key, token, IV, or other secret.

2. Cryptanalytic fact

Entropy characterizes the uncertainty of a secret for an attacker. If the generator is capable of producing only N practically achievable candidates, the upper bound on the effective entropy is 7 times the logarithm of the set’s cardinality:

\[ H_{\mathrm{eff}} \leq \log_2 N. \]

For the case under study this gives:

\[ N_{128}\approx2^{39},\quad N_{256}\approx2^{47};\qquad H_{\mathrm{eff}}\approx39\ \text{and}\ 47\ \text{bit}. \]

With equiprobable search, the average work to find the correct candidate is approximately equal to half the space:

\[ W_{\mathrm{avg}}\approx\frac{N}{2}=2^{h-1}, \]

where h is the effective entropy. In other words, the BIP39 checksum does not create new secrecy: it is deterministically calculated from ENT; PBKDF2-HMAC-SHA512 deterministically transforms the mnemonic and passphrase into a seed; HD derivation then deterministically generates keys and addresses. All of these steps preserve the constraint introduced by the weak source of randomness.

BIP39 Transformation Chain

\[ \mathrm{ENT}\ \|\ \mathrm{CS}_{ENT/32} \rightarrow \mathrm{mnemonic} \xrightarrow{\mathrm{PBKDF2\text{-}HMAC\text{-}SHA512}} \mathrm{seed}_{512} \xrightarrow{\mathrm{BIP32/BIP44}} (k_i,\,P_i,\,A_i). \]

Here  ENT , is the initial entropy,  CS are the control bits,  k_i is the private key,  P_i is the public key,  A_i and is the address. The determinism of subsequent functions is useful for wallet recovery by the owner, but with weak ENT, it is equally useful for an attacker to verify candidates.

Practical interpretation:  “256-bit mnemonic” denotes the format and nominal length of the input. It does not guarantee 256 bits of unpredictability if the actual generator selected the input from a significantly smaller set.

3. Root Cause

The affected implementation  CryptoJS.lib.WordArray.random() used a custom variation of the Multiply-With-Carry (MWC) pseudorandom generator, associated with the work of George Marsaglia. This generator is not a cryptographically secure source of random numbers: its state and initialization do not provide the required unpredictability for the key material.

It’s important to distinguish between two design flaws.  Math.random() It also shouldn’t be used for cryptographic secrets, but replacing repeated challenges  Math.random() with MWC didn’t make the system a CSPRNG: it created a limited space of achievable outputs. Cryptanalytically, it’s not the appearance of the “random” 256-bit array that’s decisive, but the number of independent unknown bits defining that array.

Simplified MWC model

The general form of the MWC step can be written as:

\[ t_n=a\,x_n+c_n,\qquad x_{n+1}=t_n\bmod b,\qquad c_{n+1}=\left\lfloor\frac{t_n}{b}\right\rfloor. \]

Here  a is the multiplier,  b is the base,  x_n is the state word,  c_n and is the carry. The formula illustrates the final internal state and deterministic evolution, but is not a reconstruction of a specific vulnerable implementation and is not intended for exploitation.

// Небезопасный антипример: не применять для ключей, seed-фраз, токенов и IV.
const entropy = CryptoJS.lib.WordArray.random(16);
const mnemonic = entropyToMnemonic(entropy);

// Безопасный принцип в браузере: ОС предоставляет криптографическую случайность.
const entropyBytes = new Uint8Array(16);
crypto.getRandomValues(entropyBytes);
// Затем передайте entropyBytes в проверенную BIP39-библиотеку.

This example illustrates an architectural boundary: secret generation should rely on the platform’s cryptographic API, not on a generic JS pseudo-generator.

4. Version history

Period / VersionThe state of the source of randomnessSignificance for audit
June 2014, 3.1.2-4The MWC approach was introduced in  WordArray.random() (commit  ff1f003)The beginning of the historical risk window for challenges that generated secrets
3.2.0 and 3.2.1Temporary transition to native cryptographic sourceExceptions within the 3.x line; the version must be confirmed using the lockfile and build artifacts
3.3.0 and later 3.xThe change was rolled back, MWC was present againYou can’t rely on the “newer means safer” rule
February 2020, 4.0.0Platform CSPRNG restoredFixed version; advisory considers versions below 4.0.0 to be affected

This retrospective highlights a typical danger of update semantics: a fix perceived as a breaking change can be reverted. Therefore, the analysis should include not only the  package.json, but also  package-lock.jsonthe  yarn.lockpackage manager lockfile, SBOM, release archives, mobile bundles, and wallet generation date.

5. The path to wallets

Ill Bloom describes a documented path through the fork  ferrumnet/bip39. In the BIP39 upstream project, entropy came from  randombytes, which delegates work  crypto.randomBytes to Node.js and  crypto.getRandomValues the browser; when adapting the fork for React Native, this path was replaced with pure-JavaScript CryptoJS.

\[ \text{Wallet UI} \rightarrow \text{BIP39 fork} \rightarrow \texttt{CryptoJS.WordArray.random()} \rightarrow \text{weak ENT} \rightarrow \text{mnemonic} \rightarrow \text{addresses}. \]

It’s precisely this interpackage dependency that explains why static verification of a single top-level package is insufficient. The fork may have seemed functionally convenient and cross-platform, but removing the boundary with the native CSPRNG replaced the cryptographic property with execution compatibility.

Safe Dependency Checking

# Инвентаризация транзитивных зависимостей в Node.js-проекте.
npm ls crypto-js
npm explain crypto-js
npm audit --omit=dev

# Зафиксируйте доказательства для расследования.
sha256sum package-lock.json yarn.lock 2>/dev/null

The output of these commands is a starting point, not a final verdict. Next, you should look for calls  WordArray.random, their wrappers, versions embedded in already published application bundles, and the actual purpose of the output.

6. Attack model

Given the known characteristics of the weak space, the attack is essentially offline: the entropy candidate is converted into mnemonics, then into deterministic keys/addresses; matching publicly observable addresses or the presence of funds serves as the verifiable criterion. The blockchain acts as a verification oracle: the publicity of addresses and balances does not directly reveal the correct secret, but allows for filtering out invalid candidates.

Below is the scientific diagram without operational parameters, optimizations and brute force code:

Для каждого кандидата e из допустимого пространства S:
    m = BIP39_Encode(e)
    s = PBKDF2_HMAC_SHA512(m, salt="mnemonic" || passphrase)
    A = Derive_Addresses(s, predefined_paths)
    если A соответствует наблюдаемому целевому множеству:
        пометить e для легитимной проверки владельцем / реагирования

The search complexity is determined by approximately 7 logarithms of S, not by the 128/256-bit length of the serialized ENT. An additional BIP39 passphrase can only change the risk model if it was actually used and had independent high entropy; it cannot be considered a universal compensation for weak generation, especially when the user’s passphrase is unknown or weak.

7. Historical parallels

HappeningCryptanalytic mechanismA Lesson for the CryptoJS Incident
Debian OpenSSL, 2006–2008A significant reduction in the generator’s state space led to predictable keys; the researchers showed that public keys could be generated from a small set of candidates.The strength of RSA/DSA/SSH keys can be broken without RSA factorization: a flaw in secret generation is sufficient.
Dual_EC_DRBGHistorical concerns centered on the ability to predict the state/output under specific parameters; NIST later withdrew the algorithm from its recommendation.Validating the provenance of the generator’s parameters, state, and API is as important as choosing a cryptographic primitive.
Android SecureRandom, early Bitcoin wallets from 2013Insufficient randomness in ECDSA signatures can reuse or predictably generate nonces; knowledge of the nonce reveals the private key.For ECC, both a weak wallet seed and a weak signature nonce are dangerous: the former narrows the search for the key, while the latter can reveal it algebraically.

For ECDSA, the relationship between nonce and key is evident from the signature equation:

\[ s \equiv k^{-1}(z+rd)\pmod n,\qquad d\equiv r^{-1}(s kz)\pmod n. \]

If the one-time nonce  k is known or recoverable, the private key  d is calculated directly. In the CryptoJS case under consideration, the emphasis is different: it’s not the signature nonce that is compromised, but the original entropy from which the wallet is derived; both scenarios emphasize that “post-RNG cryptography” does not correct for entropy loss.

8. Limits of applicability

It cannot be automatically concluded that all data processed by CryptoJS 3.x is compromised. The vulnerability is of practical significance when a specific call  WordArray.random() produced a security-sensitive value; using the library for hashing or other deterministic operations does not pose the same risk.

ScenarioGradeAction
crypto-js < 4.0.0 is in the lockfile, but  WordArray.random() is not called for secretsThe presence of addiction does not in itself prove exploitation.Confirm data flow, update dependency on risk management policy
BIP39 phrase created via vulnerable chainCritical Historical Risk: An Old Secret Can’t Be “Fixed” by Installing a PatchCreate a new wallet with a new phrase from a trusted CSPRNG and transfer assets
Tokens, encryption keys, or IVs have been generatedThe risk depends on the purpose, lifespan, and the attacker’s ability to test candidates.Rotate secrets, revoke tokens, reissue keys, investigate logs

9. Response and audit

  1. Record artifacts: application versions, lockfile, bundle hashes, installation dates, and wallet creation dates.
  2. Build a dependency graph and verify actual calls  CryptoJS.lib.WordArray.random().
  3. Classify each call by the intended purpose of the result: secret, public value, test data, or non-critical randomness.
  4. For affected seeds, immediately create a new wallet in a trusted environment and transfer funds; updating the library does not change an already created seed.
  5. Update  crypto-js to 4.0.0 or higher and prefer  crypto.getRandomValues() /  crypto.randomBytes() for generating secrets.
  6. Add regression tests, SCA/SBOM control, and a ban on weak APIs to code review and CI.

Regulatory template

// Browser / WebView: получение байтов от CSPRNG платформы.
function secureEntropy(byteLength = 32) {
  if (!globalThis.crypto?.getRandomValues) {
    throw new Error('CSPRNG платформы недоступен: генерация секрета запрещена');
  }
  const out = new Uint8Array(byteLength);
  globalThis.crypto.getRandomValues(out);
  return out;
}

// В Node.js используйте crypto.randomBytes(byteLength), а не Math.random().

Production code also requires environment handling, API restrictions, BIP39 library auditing, and integration tests. It’s critical not to write your own “fallback PRNG”: if a secure source is unavailable, the correct behavior is to fail to generate a secret.

10. Conclusions

Ill Bloom Research’s disclosure demonstrates a fundamental principle of applied cryptography: the length of a key, mnemonic , or hash output is not equal to the entropy if the input is generated by a predictable generator. In this case, the claimed narrowing to order 239–247 transforms  the security of BIP39 material from a 128/256-bit strength model to a brute-force bounded set model.

The most important practical conclusion is to separate code fixes from sanitizing existing secrets. Updating to CryptoJS 4.0.0 eliminates the vulnerable path for future generation, but does not add entropy to previously generated phrases, keys, and tokens; these require rotation or migration.

Sources

Coinspect “Ill Bloom”: cryptanalytical analysis of wallet generation vulnerability: https://bitvuln.ru/coinspect-ill-bloom-cryptanalytical-analysis-of-wallet-generation-vulnerability/

  1. Ill Bloom Research.  Technical Disclosure: The CryptoJS Randomness Vulnerability .
  2. GitHub Advisory Database.  GHSA-rg76-677x-56q9: crypto-js – Insufficient Entropy in Cryptographic Secret Generation .
  3. CVE Program.  CVE-2026-71851 .
  4. NIST.  SP 800-90 Historical Information: Random Bit Generation .
  5. YY et al.  When private keys are public: results from the 2008 Debian OpenSSL vulnerability .

Ethics Notice.  Research paper · cryptography, cryptanalysis, wallet security · September 2026. This article is intended for auditing, response, scientific analysis, and user protection. It intentionally does not contain brute-force implementations, specific generator parameters, target lists, or attack optimization methods. Research should only be conducted on proprietary systems or with explicit permission.