Elias Virtanen
August 9, 2026
12 min read
A weak line of code sat inside one of the most widely used JavaScript cryptography libraries for roughly 12 years before it started stealing money. On August 5, 2026, GitHub published a Critical-severity security advisory for CryptoJS, the npm package that pulls in nearly 9.9 million downloads a week and has shipped inside browser apps and Node.js backends since the early 2010s. The bug, tracked as CVE-2026-71851, lives in a single function: CryptoJS.lib.WordArray.random(). Blockchain security firm Coinspect traced at least $5.7 million in stolen cryptocurrency to that function, spread across five wallet apps that used it to generate recovery phrases.
Coinspect named the campaign “Ill Bloom.” The name is new. The bug is not. WordArray.random() has produced predictable, brute-forceable output since the library shipped it more than a decade ago, and nobody flagged it as a security defect until this summer. That gap between old code and understood risk is the real story, and it says more about how crypto wallets get built in 2026 than it does about any single npm package.
Don’t miss new tech stories on Google
Add Tech Insider once in the Google app and our stories appear in your news suggestions.
What Is CryptoJS, and Why Does a 12-Year-Old Function Matter
CryptoJS implements standard cryptographic building blocks in JavaScript: AES encryption, SHA hashing, HMAC, and utility functions for generating random byte arrays. Developers reach for it because it runs the same way in a browser tab as it does on a server, without native bindings or a compiled dependency. That portability made it a default choice for teams that needed “some crypto” without auditing a full cryptography stack from scratch.
The function at the center of CVE-2026-71851 was never meant to be a wallet’s only line of defense. It was a general-purpose random-value generator, and general-purpose was the problem. Wallet apps used it to generate the entropy behind BIP39 recovery phrases, the twelve or twenty-four words that reconstruct a private key. When the random generator underneath those words is predictable, the phrase only looks random. It does not behave like one under a determined brute-force attack.
Coinspect’s disclosure adds an odd twist: CryptoJS shipped a genuinely secure fix once, in versions 3.2.0 and 3.2.1, then reverted it in version 3.3.0 because the change broke backward compatibility for existing users. That reversal is arguably the most consequential decision in this entire timeline. A maintainer chose not to break existing deployments over shipping a function that silently produced weak keys. GitHub’s advisory GHSA-rg76-677x-56q9 now rates the unpatched behavior Critical, with a CVSS base score of 9.0.
Inside CVE-2026-71851: How the Weak RNG Actually Works
The mechanics are simple once you see them laid out. WordArray.random() never calls a cryptographically secure source of entropy, the kind exposed by the Web Crypto API’s crypto.getRandomValues() or Node’s crypto.randomBytes(). Instead, according to the CVE-2026-71851 record on Feedly, it runs a custom Multiply-With-Carry pseudo-random number generator seeded with JavaScript’s Math.random(). That function was never built for security work. It is fast and statistically fine for shuffling a list or picking a random animation delay, and it is exactly the wrong tool for generating a private key.
The practical impact comes down to search space. A request for 128 bits of “entropy” through the vulnerable function produces an effective search space of roughly 2^39 possibilities. A 256-bit request narrows to about 2^47. Both numbers sound large in isolation. Compare them to the 2^128 or 2^256 possibilities a properly seeded generator produces, and the gap becomes obvious. A modern GPU rig can enumerate 2^39 or 2^47 combinations in hours or days. A real 128-bit key would take longer than the age of the universe to brute-force with the same hardware.
The Entropy Math Behind the Brute Force
Security researchers point to a one-line difference between the insecure pattern CryptoJS shipped for over a decade and the fix now recommended for any app still using it:
// Vulnerable pattern (CryptoJS < 4.0.0, WordArray.random())
// Seeded with Math.random(), NOT a cryptographically secure source
const weakEntropy = CryptoJS.lib.WordArray.random(16); // 128 bits requested, ~2^39 effective search space
// Recommended fix: pull entropy from a CSPRNG instead
const secureEntropy = crypto.getRandomValues(new Uint8Array(16)); // full 128 bits of real entropy
That single function call is the entire vulnerability. Any wallet, password manager, or key-generation tool that routed through the old function inherited the weakness automatically, without changing a line of its own code and often without anyone on the team realizing it.
The Ill Bloom Attacks: A Two-Sweep Timeline
Coinspect’s on-chain analysis traced the theft to two distinct sweeps. The first hit on May 27, 2026, when attackers drained approximately $3.14 million from 431 accounts in a single coordinated pass, evidence that whoever found the weakness had already mapped which addresses were reachable before striking. A second sweep followed later, pushing the confirmed total past $5.7 million (some outlets cite $5.69 million from the same on-chain data).
The gap between when the bug shipped and when it got exploited at scale is what makes this case worth watching closely. Wallet apps had been generating keys this way for years before May 2026. Someone eventually reverse-engineered the entropy weakness, built tooling to brute-force it, and ran a working attack in production more than a month before Coinspect published anything public. The Hacker News’ coverage frames the May sweep as the moment the theft grew large enough to draw forensic attention, not the moment the flaw was first exploited.
Which Wallet Apps Were Hit
Coinspect confirmed five applications used the vulnerable generator as an entropyremain unnamed in the disclosure available at publication time
The App With No Fix Coming
RRWallet’s line in Coinspect’s disclosure is the starkest: discontinued, no fix. Anyone who generated a recovery phrase inside RRWallet at any point cannot patch their way out of the exposure. The only real remedy is moving funds to a wallet built with a secure random the funds have not already been drained
CVSS Severity and a Confusing Patch Trail
GitHub’s own advisory scores CVE-2026-71851 at 9.0 out of 10, Critical. A separate bulletin from Cybersecurity Help, published August 7, 2026, scores the identical flaw at 9.2 under the newer CVSS v4 standard. The gap between 9.0 and 9.2 is small, but it illustrates how two legitimate scoring frameworks can land on slightly different numbers for the same root cause depending on which factors each version weighs.
The patch guidance is where things get genuinely confusing. GitHub’s advisory says every release before 4.0.0 counts as technically affected, including 3.3.0, the version that reintroduced the weak generator after 3.2.0 and 3.2.1 had briefly fixed it. The guidance from the advisory is blunt: only keep running a 3.x release if your application never uses WordArray.random() to generate anything security-sensitive. Otherwise, 4.0.0 is the only real fix. Maintainer Evan Vosberg published the advisory alongside that guidance, and the GitLab advisory database entry mirrors the same version boundaries. Security scanner Snyk’s package page for crypto-js now flags the issue for any project still pinned below 4.0.0.
None of that patch guidance helps users whose keys were already generated under the weak code. Upgrading a dependency does not retroactively fix a private key that a brute-force script can already guess. It only stops new keys from inheriting the same flaw.
How This Compares With Past Crypto RNG Disasters
CryptoJS is not the first widely used tool to leak money through weak randomness, and the pattern across incidents is consistent: a component built for convenience gets pressed into service generating private keys, nobody re-audits the randomness
The Wintermute case remains the largest by dollar amount. On September 20, 2022, the market maker lost roughly $160 million after its hot wallet, generated with the Profanity vanity-address tool, turned out to have a brute-forceable private key. Forklog’s reporting traced the root cause to the same category of flaw driving the CryptoJS incident: a weak seed feeding a process that was supposed to produce unguessable output. The Milk Sad disclosure site documents a closely related pattern in Libbitcoin Explorer’s seed command, and links its findings directly to the Trust Wallet weakness tracked as CVE-2023-31290.
What changes with CryptoJS is scale of exposure rather than size of any one theft. Profanity was a niche vanity-address tool. CryptoJS sits inside millions of projects, which means the discovery methodology here, auditing old, unglamorous utility functions for weak entropy, has a much larger attack surface left to search.
Why NPM Supply Chain Risk Keeps Compounding
CryptoJS’s flaw is a design defect that sat quietly for years, not an injected backdoor, which puts it in a different category from most 2025 and 2026 npm incidents. But it lands in an ecosystem already primed to worry about exactly this kind of exposure. In September 2025, attackers compromised a maintainer account through phishing and pushed malicious code into 18 widely used packages, including chalk, debug, and ansi-styles, which together pull more than 2 billion downloads a week, according to BleepingComputer’s reporting on the incident.
A separate compromise in March 2026 hit the axios HTTP client, which carries roughly 100 million weekly downloads and 174,000 downstream dependents, based on a supply chain tracking report from Shattered.io. The same report attributes to Sonatype’s 2026 State of the Software Supply Chain research a count of more than 454,600 newly discovered malicious npm packages in 2025, with a cumulative total exceeding 1.233 million blocked, a 75% year-over-year increase.
CryptoJS did not need to be compromised by an attacker to become dangerous. It only needed to be trusted for twelve years without anyone re-checking a design decision made early in the library’s history. That is arguably a harder problem to solve than a malicious package upload, because there is no phishing email to trace and no maintainer account to lock down. The fix requires developers to audit dependencies they have never questioned, not just watch for new ones behaving badly.
Market Impact: What $5.7 Million in Losses Really Costs
$5.7 million is a modest sum next to Wintermute’s $160 million or the billions tied to major exchange hacks in past years. The more expensive cost is trust, and it lands on parties who did nothing wrong. Bexo Wallet and NanChat both shipped fixes, yet both now have to explain to users why a dependency they never wrote put recovery phrases at risk. RRWallet, already discontinued, offers a preview of the worst outcome: a dead app with live, exposed keys and no one left to patch them.
There is a second, quieter cost for the broader npm ecosystem. Every widely used crypto-adjacent package now faces a reasonable question from security teams: has anyone actually audited your randomness? That question was rarely asked before Ill Bloom. It will likely get asked constantly through the rest of 2026, and answering it properly takes real engineering time that most open-
The Security Tooling Response: Who Catches Bugs Like This
Vulnerability databases moved fast once Coinspect went public. Miggo’s vulnerability database and Kodem Security’s CVE archive both indexed CVE-2026-71851 within days, and Snyk’s package advisory now surfaces automatically for any project running npm audit against an affected version. That tooling response is the system working as intended: a researcher finds a flaw, a CVE gets assigned, and dependency scanners propagate the warning to every downstream project within a normal release cycle.
The harder gap is enterprise vulnerability management at scale, where security teams triage thousands of findings across sprawling dependency trees and have to decide which ones justify an emergency patch cycle versus routine maintenance. Platforms built for that kind of prioritization, the category covered in our comparison of Tenable, Qualys, and Rapid7, exist precisely because “a CVE was published” and “this needs to ship today” are not the same signal. A weak RNG in a crypto library used for financial key generation is exactly the kind of finding that should jump the queue, but only if the scanning tooling correctly flags the downstream blast radius rather than treating it as a routine dependency bump.
What Wallet Users Should Do Right Now
- Check whether your wallet app is one of the five confirmed to use the vulnerable generator, starting with RRWallet, Bexo Wallet, and NanChat.
- If you use RRWallet, move funds to a new wallet immediately. No patch is coming.
- If you use Bexo Wallet or NanChat, update to the fixed version as soon as it is available, then generate a fresh recovery phrase rather than trusting the old one.
- Treat any recovery phrase generated before your app’s patch date as potentially compromised, even if your funds have not moved yet.
- Avoid reusing an old, potentially weak seed phrase across multiple wallets or chains, since a compromised seed exposes every address derived from it.
What Developers Should Do Right Now
- Search your dependency tree for crypto-js versions below 4.0.0, including transitive dependencies pulled in by other packages.
- Never use general-purpose libraries for key generation without confirming they call a CSPRNG such as
crypto.getRandomValues()orcrypto.randomBytes(). - Run
npm auditand cross-check results against Snyk’s or GitHub’s advisory databases, since scanner coverage can lag a fresh CVE by days. - If your app ever used the vulnerable function for anything security-sensitive, plan a forced key-rotation path for existing users, not just a version bump for new ones.
- Budget time for periodic entropy audits of long-standing dependencies, not only new ones flagged by automated scanners.
Five Predictions for the Next Six Months
- More legacy JS crypto libraries get audited. Coinspect’s methodology, treating old utility functions as suspects rather than assuming age equals trust, is cheap to repeat against other widely used packages, and researchers will likely repeat it.
- Wallet app stores face pressure over RNG disclosure. Repeated real-money losses traced to client-side crypto libraries make a reasonable case for app marketplaces to ask finance apps what they use for key generation.
- CryptoJS usage keeps declining. Expect a continued shift toward the native Web Crypto API and independently audited libraries as maintainers and downstream teams route around code with a documented history of reverted fixes.
- A race continues between attackers and defenders. Every wallet seed generated under the old CryptoJS code remains exposed until it is rotated, so expect continued scanning activity against old addresses through the rest of 2026.
- Entropy audits become a standard service line. Smart contract audits turned into a routine budget item after the DeFi hacks of 2021 and 2022. Expect security firms to package “randomness audits” the same way.
Related Coverage
Frequently Asked Questions
What is CVE-2026-71851?
CVE-2026-71851 is a Critical-severity vulnerability in CryptoJS, an npm JavaScript cryptography library. It affects the WordArray.random() function, which used a weak, Math.random()-seeded pseudo-random number generator instead of a cryptographically secure one. GitHub’s security advisory GHSA-rg76-677x-56q9 rates it 9.0 on the CVSS scale.
Is CryptoJS still safe to use?
Version 4.0.0 fixes the flaw. Versions below 3.3.0 and the reverted 3.3.0 release itself remain exposed for any use case involving security-sensitive random values, including wallet seed generation, session tokens, or key material. The library remains safe for non-security uses such as hashing or formatting.
How do I know if my wallet was affected by the Ill Bloom attacks?
Coinspect has publicly named three affected apps so far: RRWallet, Bexo Wallet, and NanChat. Two more affected apps have not been named publicly as of this reporting. If you use any wallet app and are unsure whether it depends on crypto-js, check with the app’s developer or watch Coinspect’s disclosure for updates.
What should developers do if their app depends on crypto-js?
Upgrade to version 4.0.0 if the dependency is used for anything security-sensitive. Run a dependency audit to check for transitive uses pulled in through other packages, since many projects use crypto-js indirectly without realizing it.
Does upgrading to CryptoJS 4.0.0 protect funds that were already generated with the weak version?
No. Upgrading only prevents new keys from inheriting the weakness. Any recovery phrase or private key generated before the upgrade remains guessable through the same brute-force approach attackers already used, so existing keys need to be rotated, not just the library version.
How is this different from a typical npm supply chain attack?
Most recent npm incidents, including the September 2025 attack that hit packages with more than 2 billion combined weekly downloads, involved attackers injecting malicious code after compromising a maintainer’s account. CVE-2026-71851 is different. It is a design flaw that shipped legitimately and sat unnoticed for years, which means there was no phishing email or account takeover to trace, only a weak function nobody re-audited.
Who discovered the CryptoJS RNG flaw?
Blockchain security firm Coinspect identified CryptoJS.lib.WordArray.random() as thelting wallet-draining campaign. CryptoJS maintainer Evan Vosberg published the corresponding GitHub Security Advisory on August 5, 2026
![CVSS 9.0, $5.7M Wallets Drained [2026] CVSS 9.0, $5.7M Wallets Drained [2026]](https://tech-insider.org/wp-content/uploads/2026/08/cryptojs-weak-rng-vulnerability-2026-1.webp)