← Back to Feed CACHED · 2026-08-08 17:47:34 · CACHE_KEY CVE-2026-71851
CVE-2026-71851 · CWE-331 · Disclosed 2026-08-07

crypto-js is a JavaScript library of crypto standards.

ASSESSED — NOISGATE V0.5
Vendor
Reassessed
Verdict:
Do you agree?
01 · The Real Story

A slot machine that only has 500 billion combinations pretending to have trillions — and someone already figured out the pattern

CVE-2026-71851 affects the CryptoJS.lib.WordArray.random() function in crypto-js versions ≥ 3.1.2-4 and < 4.0.0. These versions use a custom Multiply-With-Carry PRNG seeded by Math.random() instead of a cryptographically secure source. Requests for 128 or 256 bits of randomness yield effective search spaces of only ~2^39 and ~2^47 possibilities respectively — trivially enumerable on commodity hardware. The fix landed in version 4.0.0 in February 2020, over six years ago. The library is now discontinued; NodeJS and modern browsers ship native crypto modules that supersede it entirely.

The vendor's CRITICAL/9.0 rating reflects the *worst-case* outcome — complete private key recovery when the function is used for wallet seed generation, as proven by the Ill Bloom campaign that drained $5.7 million from five crypto wallet apps. However, the CVSS vector's own AC:H already signals that exploitation requires specific conditions. For enterprise defenders managing 10,000 hosts, the real question is whether any internal or customer-facing application calls WordArray.random() to generate session tokens, API keys, or HMAC secrets. Merely depending on crypto-js 3.x in package-lock.json is not sufficient to be exploitable — the application must actively invoke the vulnerable function for security-sensitive output. This condition significantly narrows the exploitable population, making the CRITICAL label overweight for most enterprise environments.

"Weak PRNG proven exploitable in the wild, but only apps using WordArray.random() for secrets are at risk."
02 · The Attack Path

4 steps from start to impact.

STEP 01

Identify target application using crypto-js < 4.0.0

The attacker identifies an application that uses crypto-js 3.x by examining client-side JavaScript bundles, open-source dependency manifests, or SBOM disclosures. For crypto wallet targets, the attacker checks public blockchain ledgers for addresses associated with known vulnerable wallet apps. For enterprise targets, the attacker looks for session tokens or API keys with entropy patterns consistent with MWC-generated output.
Conditions required:
  • Target application uses crypto-js ≥ 3.1.2-4 and < 4.0.0
  • Application calls WordArray.random() for security-sensitive value generation
Where this breaks in practice:
  • Most modern Node.js apps use native crypto.randomBytes() — crypto-js random is rarely the entropy source
  • The vulnerable function is one of dozens in the library; most consumers use AES/SHA functions with externally-supplied keys
  • The library has been abandoned since 2021; security-conscious teams have migrated
Detection/coverage: SCA tools (Snyk, Socket.dev, npm audit) flag crypto-js < 4.0.0 with this CVE. Static analysis can grep for CryptoJS.lib.WordArray.random( calls.
STEP 02

Harvest security-sensitive output

The attacker collects the cryptographic artifacts generated by the weak PRNG. For blockchain targets, this means harvesting wallet addresses from public ledgers. For enterprise targets, this could mean intercepting session tokens from HTTP responses, capturing API keys from logs or network traffic, or obtaining HMAC-signed payloads where the signing key was generated via the vulnerable function.
Conditions required:
  • Access to the output derived from WordArray.random() — either public (blockchain) or obtainable via network position
Where this breaks in practice:
  • Enterprise session tokens are typically transmitted over TLS and expire quickly
  • API keys generated at provisioning time may have been rotated since the vulnerable version was in use
  • Attacker needs to know or guess that the target value was generated by the weak PRNG
Detection/coverage: Network monitoring for unusual token harvesting patterns; API gateway logs showing enumeration of endpoints returning tokens.
STEP 03

Offline brute-force enumeration of PRNG state

The attacker reconstructs the MWC generator state space. Since Math.random() seeds the generator, the attacker enumerates seed values from 0 to 2^32−1 and simulates the MWC output for each seed. For 128-bit requests this produces ~2^39 candidates; for 256-bit requests, ~2^47. On a modern GPU rig or cloud instance, 2^47 iterations complete in hours to days. Tools like crypto-bruteforce-seed-generator and custom MWC reconstruction scripts exist publicly on GitHub.
Conditions required:
  • Commodity compute resources (GPU or cloud — estimated cost < $500 for full enumeration)
  • Knowledge of how many bytes were requested in the original WordArray.random() call
Where this breaks in practice:
  • If the application applied additional entropy mixing (e.g., concatenating crypto.randomBytes() output), brute force becomes infeasible
  • Enumeration time increases if the attacker doesn't know exact parameters
STEP 04

Recover secret and exploit

The attacker matches a brute-forced candidate against the harvested target. For wallets, this means deriving BIP39 mnemonics, generating addresses, and checking against the blockchain. For enterprise apps, this means testing candidate session tokens or API keys against the target service, or forging HMAC signatures. Successful recovery gives the attacker the original secret — session hijack, authentication bypass, or fund theft.
Conditions required:
  • Successful match from step 3
  • Target secret has not been rotated since generation
Where this breaks in practice:
  • Enterprise key rotation policies may have invalidated old keys
  • Session tokens with short TTLs (< 24h) are impractical targets
  • MFA or IP-binding on sessions blocks replay even with a valid token
Detection/coverage: Authentication anomaly detection (impossible travel, new device); blockchain monitoring for unauthorized transfers.
03 · Intelligence Metadata

The supporting signals.

In-the-Wild ExploitationConfirmed. Coinspect's *Ill Bloom* investigation documented two drain waves (May 27 and May 30–Jul 13, 2026) totaling $5.7M from 953 compromised accounts across five crypto wallet apps.
Proof-of-ConceptMultiple brute-force seed enumeration tools exist on GitHub (e.g., DjamaGuelleh/crypto-bruteforce-seed-generator). Coinspect demonstrated the full chain: enumerate MWC outputs → derive BIP39 phrases → check addresses against blockchain.
EPSS Score0.00317 (low percentile) — reflects the narrow exploitability condition requiring specific function usage, not just dependency presence.
KEV StatusNot listed as of 2026-08-09.
CVSS VectorCVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:C/C:H/I:H/A:H — 9.0. The AC:H is justified: exploitation requires the target to use the specific vulnerable function. The S:C (Changed scope) reflects cross-boundary impact (e.g., wallet funds on a different trust boundary).
Affected Versionscrypto-js ≥ 3.1.2-4, < 4.0.0. Versions 3.2.0 and 3.2.1 briefly used native crypto but 3.3.0 reverted to the weak MWC generator.
Fixed Version4.0.0 (released February 2020). The library is now discontinued — no further releases expected.
Scanning / Exposurenpm reports ~10M weekly downloads and 15,583 dependents for crypto-js. However, most dependents use AES/SHA functions, not WordArray.random(). Socket.dev and Snyk flag all < 4.0.0 installs.
Disclosure TimelineWeak PRNG introduced June 2014. Fixed in v4.0.0 Feb 2020. Ill Bloom exploitation discovered May 2026. Coinspect public disclosure Aug 5, 2026. CVE published Aug 7, 2026.
Researcher / OrgCoinspect (CEO Juliano Rizzo) discovered and coordinated disclosure. GHSA-rg76-677x-56q9 published by maintainer Evan Vosberg.
04 · The Call

noisgate verdict.

Final Verdict
DOWNGRADED to HIGH (7.0/10)

The single most decisive factor is the narrow exploitability condition: only applications that actively call WordArray.random() for security-sensitive generation are vulnerable — merely depending on crypto-js 3.x is not sufficient, and the vast majority of the 15,583 dependents use it for AES/SHA operations with externally-supplied keys. Active in-the-wild exploitation of crypto wallets prevents further downgrade below HIGH.

HIGH Vulnerability mechanics and affected version range
HIGH Active exploitation evidence (Ill Bloom campaign)
MEDIUM Enterprise exposure estimate (fraction of installs using WordArray.random() for secrets)

Why this verdict

  • Narrow trigger condition: The vulnerability requires the application to call CryptoJS.lib.WordArray.random() for security-sensitive values. Most crypto-js consumers use it for AES encryption or SHA hashing with externally-provided keys — the vulnerable function is not in the hot path for typical usage.
  • Six-year-old fix: Version 4.0.0 shipped in February 2020. Any application still on 3.x has had over six years of remediation runway. This narrows the exploitable population to unmaintained or legacy codebases.
  • Offline attack, not RCE: This is not a remotely-triggerable code execution flaw. The attacker must first obtain or observe the output of the weak PRNG, then perform offline brute-force enumeration. There is no shell, no lateral movement, no privilege escalation inherent to the vulnerability itself.
  • Role multiplier: crypto-js is an npm library embedded in application code. It does not run on domain controllers, hypervisors, or network edge appliances. In *typical enterprise roles* (Node.js API servers, frontend builds), the blast radius is confined to the secrets generated by that single application — session tokens, API keys, or HMAC signing keys. The worst plausible high-value role is a backend service that generates authentication tokens for a customer-facing SaaS platform; compromise of those tokens could enable account takeover across the tenant. This outcome is serious but bounded to one application's trust boundary, not fleet-scale. For crypto wallet applications (a narrow but real deployment role), the blast radius is total fund loss — proven by $5.7M in Ill Bloom drains — but wallet apps represent a tiny fraction of enterprise crypto-js deployments.
  • Active exploitation prevents MEDIUM: Despite all friction, Coinspect documented $5.7M in real losses. The attack tooling is public. If an enterprise app does use the vulnerable function, the exploitation cost is < $500 in cloud compute.

Why not higher?

The CRITICAL rating assumes every crypto-js 3.x installation is exploitable, but the advisory itself states that merely depending on the library is insufficient — the application must actively use WordArray.random() for secret generation. This is a narrow subset of the installed base. The vulnerability provides no RCE, no lateral movement, and no privilege escalation; it is a cryptographic weakness whose blast radius is bounded to the secrets generated by one application. The fix has been available for six years.

Why not lower?

Active in-the-wild exploitation is confirmed with $5.7M in documented losses. Public brute-force tooling makes exploitation accessible to low-skill attackers for < $500. The EPSS score of 0.00317 is low but does not account for the proven Ill Bloom campaign. With ~10M weekly downloads and 15,583 dependents, the probability that at least one application in a 10,000-host enterprise uses the vulnerable function for token or key generation is non-trivial. Already-generated weak secrets cannot be retroactively strengthened by upgrading — they must be identified and rotated.

05 · Compensating Control

What to do — in priority order.

  1. Audit all applications for WordArray.random() calls — Run grep -r 'WordArray.random\|CryptoJS.lib.WordArray.random' . across all Node.js codebases and bundled assets. Any hit in a security-sensitive context (token generation, key derivation, nonce creation) is a confirmed exposure. Prioritize this audit within the noisgate mitigation SLA of 30 days.
  2. Rotate all secrets generated by vulnerable code paths — If audit confirms WordArray.random() was used for session secrets, API keys, HMAC keys, or any authentication material, rotate those secrets immediately — upgrading crypto-js alone does not fix already-generated weak values. This is the most critical compensating control.
  3. Pin or upgrade crypto-js to ≥ 4.0.0 or replace with native crypto — Since crypto-js is abandoned, the best path is replacing all usage with Node.js built-in crypto.randomBytes() or the Web Crypto API crypto.getRandomValues(). If immediate replacement is impractical, pin to 4.0.0. Deploy within the 30-day noisgate mitigation SLA.
  4. Add SCA policy to block crypto-js < 4.0.0 in CI/CD — Configure Snyk, Socket.dev, or npm audit to fail builds that include crypto-js < 4.0.0. This prevents reintroduction via transitive dependencies.
What doesn't work
  • WAF / network-level controls — this is an offline cryptographic weakness; there is no network payload to inspect or block.
  • Rate limiting on authentication endpoints — the brute-force happens offline against the PRNG state, not against the target service's login endpoint.
  • Upgrading crypto-js without rotating secrets — already-generated weak keys remain weak regardless of the library version. The entropy deficit is baked into the output at generation time.
06 · Verification

Crowdsourced verification payload.

Run this script on any host with Node.js installed to check whether a project's node_modules contains a vulnerable crypto-js version. Execute from the project root directory: bash check_cryptojs.sh /path/to/project. No elevated privileges required.

noisgate-verify.sh
BASHREAD-ONLYSAFE
#!/usr/bin/env bash
# check_cryptojs.sh — Detect vulnerable crypto-js versions (CVE-2026-71851)
# Usage: bash check_cryptojs.sh /path/to/project
# Requires: node (any version), or just grep/jq

set -euo pipefail

PROJECT_DIR="${1:-.}"
RESULT="UNKNOWN"

if [ ! -d "$PROJECT_DIR" ]; then
  echo "ERROR: Directory $PROJECT_DIR does not exist."
  exit 2
fi

# Check for crypto-js in node_modules
PKG_JSON="$PROJECT_DIR/node_modules/crypto-js/package.json"

if [ ! -f "$PKG_JSON" ]; then
  # Also check lock files for transitive deps
  if grep -q '"crypto-js"' "$PROJECT_DIR/package-lock.json" 2>/dev/null || \
     grep -q 'crypto-js@' "$PROJECT_DIR/yarn.lock" 2>/dev/null; then
    echo "INFO: crypto-js found in lock file but not installed. Run npm install first."
    RESULT="UNKNOWN"
  else
    echo "PATCHED — crypto-js is not a dependency of this project."
    exit 0
  fi
else
  VERSION=$(node -e "console.log(require('$PKG_JSON').version)" 2>/dev/null || echo "")
  if [ -z "$VERSION" ]; then
    VERSION=$(grep '"version"' "$PKG_JSON" | head -1 | sed 's/.*"version".*"\(.*\)".*/\1/')
  fi

  if [ -z "$VERSION" ]; then
    echo "UNKNOWN — could not parse crypto-js version."
    exit 2
  fi

  echo "INFO: Found crypto-js version $VERSION"

  # Parse major version
  MAJOR=$(echo "$VERSION" | cut -d. -f1)

  if [ "$MAJOR" -ge 4 ] 2>/dev/null; then
    echo "PATCHED — crypto-js $VERSION is >= 4.0.0 (not affected by CVE-2026-71851)."
    exit 0
  else
    echo "VULNERABLE — crypto-js $VERSION is < 4.0.0 (affected by CVE-2026-71851)."
    # Additional check: see if WordArray.random is actually called
    echo ""
    echo "=== Checking for WordArray.random() usage in source code ==="
    HITS=$(grep -r -l 'WordArray\.random\|CryptoJS\.lib\.WordArray\.random' "$PROJECT_DIR/src" "$PROJECT_DIR/lib" "$PROJECT_DIR/app" 2>/dev/null | head -20 || true)
    if [ -n "$HITS" ]; then
      echo "WARNING: WordArray.random() calls found in application code:"
      echo "$HITS"
      echo ""
      echo "VULNERABLE — confirmed usage of the weak PRNG function."
    else
      echo "NOTE: No WordArray.random() calls found in src/lib/app directories."
      echo "VULNERABLE — version is affected, but exploitability depends on whether"
      echo "            WordArray.random() is called for security-sensitive generation."
      echo "            Check all code paths including bundled/transpiled files."
    fi
    exit 1
  fi
fi

echo "$RESULT"
exit 2
07 · Bottom Line

If you remember one thing.

TL;DR
Monday morning: Run an SCA scan (npm audit, Snyk, or the verification script above) across all Node.js projects and container images to identify crypto-js < 4.0.0 installations. For any confirmed hit, immediately audit whether WordArray.random() is called for session tokens, API keys, HMAC secrets, or any cryptographic material. If it is, rotate those secrets now — upgrading the library does not fix already-generated weak values. Under the noisgate mitigation SLA for HIGH, deploy compensating controls (upgrade or replace crypto-js, add CI/CD block rule, rotate affected secrets) within 30 days. Complete full remediation (library replacement and secret rotation verified across all environments) within the 180-day noisgate remediation SLA. If you discover any application generating authentication tokens via the vulnerable function, treat that specific application as an emergency — the exploitation cost is under $500 in cloud compute and public tooling exists.

Sources

  1. CVE-2026-71851 — CVEReports
  2. GHSA-rg76-677x-56q9 — GitLab Advisory Database
  3. CryptoJS Weak RNG Behind $5.7M in Drains — The Hacker News
  4. crypto-js Weak Randomness in WordArray.random() — TheHackerWire
  5. crypto-js — npm
  6. crypto-js Security Analysis — Socket.dev
  7. OffSeq Threat Radar — CVE-2026-71851
Peer Review

What defenders are saying.

Submit a review attribution: handle + country only
0 flags selected · stored anonymously
Validation Results

Crowdsourced verification outputs.

Results submitted by users who ran the verification payload against their environment.