Debian Security Tracker: CVE-2026-71851 (crypto-js) Tracking the node-crypto-js vulnerability in the Debian/Ubuntu package base and the cryptanalytic implications of insufficient entropy

09.09.2026

Debian Security Tracker: CVE-2026-71851 (crypto-js) Tracking the node-crypto-js vulnerability in the Debian/Ubuntu package base and the cryptanalytic implications of insufficient entropy

This paper examines CVE-2026-71851, a vulnerability in the JavaScript library  crypto-js, tracked by the Debian Security Tracker for the source package  cryptojs. The vulnerability is related to the method  CryptoJS.lib.WordArray.random(), which in versions prior to ,  4.0.0 used a custom variation of the Multiply-With-Carry generator, initialized via  Math.random(), instead of a cryptographically strong random source.

A key cryptanalytic fact is that a nominal query of 128 or 256 bits of randomness does not provide the corresponding actual entropy: the effective search space is estimated to be approximately the same as  2^39 the  2^47 number of states. When using this function to generate BIP39 recovery phrases, private keys, recovery tokens, API keys, or other secrets, this creates the conditions for offline brute-force attacks and subsequent seizure of assets or accounts.

Particular attention is paid to the interpretation of Debian Security Tracker statuses, including  vulnerable,  unfixed and  <postponed>, as well as the distinction between the presence of a vulnerable dependency and the actual exploitability of a defect.

Keywords:  CVE-2026-71851, crypto-js, node-crypto-js, Debian Security Tracker, CSPRNG, entropy, Math.random(), MWC, BIP39, cryptanalysis, offline brute-force, vulnerability management.

Introduction

Modern cryptographic systems typically rely on strong primitives: AES for symmetric encryption, SHA-256 for hashing, HMAC for integrity checking, and ECDSA or Schnorr signatures for authentication. However, the strength of these algorithms does not guarantee system security if the initial key material was generated by a predictable random number generator.

CVE-2026-71851 demonstrates a fundamental principle of applied cryptography: the length of the requested secret is not equal to the actual cryptographic entropy. An application may request a 256-bit value, but if its origin is limited to a small set of internal states of the generator, the attacker analyzes not a space of size  2^256, but a significantly smaller space of initial states.

This issue is particularly significant for the JavaScript ecosystem, where the library  crypto-js could be used in browsers, Node.js applications, wallet interfaces, web administration panels, authorization services, and cryptocurrency tools.

Vulnerability identification

CategoryContentCryptographic value
IdentifierCVE-2026-71851Unique identifier for correlating information in Debian Security Tracker, SBOM, SCA scanners, and internal risk registries.
Componentcrypto-js; Debian source package: cryptojsIn Node.js environments, the package may appear as  node-crypto-js; for audit purposes, it is more important to establish the actual version and delivery path of the dependency.
Vulnerable functionCryptoJS.lib.WordArray.random()The risk arises when using the function to create security-sensitive values, not when importing any library.
CauseCustom Multiply-With-Carry PRNG, seed from Math.random()The generator is not a CSPRNG and does not provide the required unpredictability.
Affected versionsAlmost a 3.x branch; the generator was present since 3.1.2-4The vulnerability affects older releases if they generated secrets through the specified function.
Upstream fixcrypto-js 4.0.0The fix prevents insecure generation of new secrets, but does not make previously generated values ​​secure.
Weakness classesCWE-331, CWE-334, CWE-338Insufficient entropy, small key space and the use of a cryptographically weak PRNG.

The practical meaning of CVE

Presence  crypto-js < 4.0.0 in dependencies does not automatically prove a compromise. A vulnerability becomes practically significant if the application calls  CryptoJS.lib.WordArray.random() values ​​that affect confidentiality, integrity, authentication, or control of cryptocurrency assets.

For example, using a function for decorative random interface identifiers is not equivalent to generating a BIP39 mnemonic. Conversely, using a vulnerable generator for a seed phrase, master key, private key, reset token, session token, or API secret makes the initial secrecy mathematically bounded by the state of the weak generator.

Debian Security Tracker Status

FieldFixed valueInterpretation
Source packagecryptojsDebian typically detects vulnerabilities at the source package level. Binary packages and Node.js modules must be matched against the source package and its version.
Debian bookworm3.1.2+dfsg-3, status vulnerableThe version contains a vulnerable implementation. It is necessary to identify the actual calls  WordArray.random() in the application code and dependencies.
Debian unstable(unfixed)The tracker does not have a specified uploaded patch for this branch at the time of review.
Bookworm and Bullseye<postponed>, “Minor issue, low popcon”The update has been postponed. This does not mean it’s fixed and does not eliminate the need for local risk management.

An important distinction:  the status  <postponed> reflects the Debian update delivery process, not the actual cryptographic strength of the application. For a service that issued private keys or seed phrases through a vulnerable function, the “Minor Issue” designation should not be used as grounds for refusing to rotate secrets.

Semantics of statuses

This status  vulnerable indicates that a specific version of a package in a given Debian release is considered vulnerable. This status  unfixed indicates that there is no registered fixed version in the corresponding channel. This status  <postponed> applies when a fix can be backported to a later update, including inclusion in a future security advisory.

For operational security, it’s necessary to distinguish between package maintenance processes and the threat model. Debian’s priority may take into account the mass installation of a package, the complexity of updating, and other factors. The owner of a cryptographic service must also consider the cost of compromising a single secret.

Technical root cause

In the affected versions,  crypto-js the method  CryptoJS.lib.WordArray.random() used an internal Multiply-With-Carry pseudorandom generator. Initialization was performed based on  Math.random(), which is not intended for cryptographic use.

General-purpose generators may be suitable for simulations, game mechanics, randomization of interface elements, and statistical experiments. However, they should not be used for keys, nonces, tokens, one-time recovery links, BIP39 entropy, or other secrets that must be unpredictable to an adversary.

Simplified MWC model

The Multiply-With-Carry family of generators can be schematically represented by a recurrence relation:

x_{i+1} = (a x_i + c_i) mod b

where  x_i is the internal state,  c_i is the carry,  a is the multiplier, and  b is the arithmetic base. The mere fact of using MWC does not always imply vulnerability; the critical point is that the specific construction, seed, and observed sequence do not ensure the properties of a CSPRNG.

A cryptographically secure generator must make it computationally infeasible to reconstruct previous and future outputs, even when observing a portion of the sequence. For secret values, it requires reliance on a system-provided CSPRNG: for example,  getrandom(),  /dev/urandom,  window.crypto.getRandomValues() or  crypto.randomBytes() in Node.js.

Actual entropy

The formal length of the result itself does not determine its strength. If an application receives a 128-bit string, but the generator can only produce about  2^39 128 practically distinguishable variants, then the actual uncertainty is closer to 39 bits than 128.

H_eff = log2(|S|)

where  S is the set of actually achievable secrets, and  H_eff is the effective entropy. With a uniform distribution and exhaustive search, the average difficulty of finding a specific value is approximately half the space:

W_avg ≈ 2^(H_eff - 1)
Nominal lengthEfficient spaceAverage complexity of enumerationCryptanalytic derivation
128 bitsNear 2^39About  2^38 checksThis is not comparable to the security of a 128-bit key space.
256 bitsNear 2^47About  2^46 checksExtending the result does not restore the lost entropy of the internal state.

In the ideal model, a 128-bit space requires about 128  2^128 variants, while a 256-bit space requires about 128 variants  2^256. Reducing the space to  2^39 or  2^47 changes the nature of the problem: instead of an astronomically impossible enumeration, a task emerges that is potentially feasible with specialized software on available computing hardware.

Relationship with BIP39 and Bitcoin

BIP39 describes the transformation of the initial entropy into a mnemonic phrase, typically consisting of 12, 18, or 24 words. In a correct implementation, the strength of the mnemonic phrase is determined by the randomness of the initial value, not just the number of words displayed.

If BIP39 entropy was generated through a vulnerable [keyword]  CryptoJS.lib.WordArray.random(), an attacker may not attempt to enumerate all valid mnemonics. Instead, they simulate or enumerate a significantly smaller set of weak generator states, reconstruct the entropy candidates, obtain the corresponding BIP39 phrases, derive the seed, and then verify the derived addresses.

entropy → BIP39 mnemonic → PBKDF2-HMAC-SHA512 → seed → BIP32/BIP44 derivation → private keys → addresses

Thus, the strong components of BIP39, PBKDF2, and BIP32 are not an immediate weakness. They deterministically process already compromised initial data. A cryptanalytic attack is aimed at the generator space, not at reversing SHA-512, cracking secp256k1, or brute-forcing a Bitcoin private key.

Historical cryptanalytic context

The closest historical example is a Debian OpenSSL bug from 2006–2008. A bug in a Debian patch disrupted entropy collection, dramatically narrowing the key generation space. As a result, vulnerable SSH and TLS keys could be identified by precomputed sets. The attack principle is identical to CVE-2026-71851: a strong cryptographic primitive fails if its key is chosen from a small, predictable set.

Another classic example is the use of weak time-based, PID-based, or predictable state-based generators for session IDs and reset tokens. In such incidents, the attacker doesn’t have to break the encryption: they can reproduce the generator’s sequence, predict the next token, or try a limited set of candidates.

Attack scenario

A typical exploitation scenario for CVE-2026-71851 can be represented by the following sequence:

  1. The attacker determines that the target application was using  crypto-js < 4.0.0.
  2. It confirms the reachability of the call  CryptoJS.lib.WordArray.random() when generating the secret.
  3. It reproduces or enumerates a reduced space of internal states of a vulnerable generator.
  4. For each candidate, a candidate key, token, or BIP39 mnemonic is constructed.
  5. Candidates are verified using a known address, public key, token hash, checksum, server response, or blockchain data.
  6. Once a match is found, the attacker receives the corresponding secret material.

An important feature is the offline nature of a significant portion of the attack. If the adversary has a verifiable identifier—for example, a Bitcoin address, a public key, a token hash, or a known ciphertext/known plaintext—most candidates can be eliminated without limiting the server’s request rate.

Simplified audit pseudocode

for candidate_state in vulnerable_prng_state_space:
    entropy = generate_like_vulnerable_cryptojs(candidate_state)
    mnemonic = bip39_encode(entropy)
    seed = pbkdf2_hmac_sha512(mnemonic, passphrase)
    keys = derive_bip32_paths(seed)

    if target_address in addresses(keys):
        report_compromise(candidate_state, mnemonic)

This fragment is a conceptual cryptanalysis diagram, not a ready-made attack tool. Its purpose is to demonstrate why candidate verification can be deterministic and why difficulty is determined by the effective entropy of the generator, not the nominal length of the seed phrase.

Affected data

Value typeConsequence of weak randomnessRequired response
BIP39 mnemonic / wallet seedPossible recovery of private keys and asset control.Generate a new mnemonic using CSPRNG, transfer funds, stop using the old seed phrase.
Private keyComplete compromise of signature, identity or cryptocurrency wallet.Revoke and replace keys, reissue certificates, update trusted keys and signatures.
Session tokenHijacking a user’s session and bypassing authentication.Invalidate all tokens, switch to CSPRNG, implement rotation and expiration limits.
Password reset tokenUnauthorized password reset.Revoke existing links and issue new tokens only from the system CSPRNG.
API key / invite codeKey guessing, API access, or quota abuse.Reissue keys, check logs, enable permission restrictions and secret rotation.
Salt or IVDepends on the protocol: repetitions, predictability, or violation of the scheme’s assumptions are possible.Evaluate a specific cryptographic scheme; use a CSPRNG and correct sizes for new values.

Server environment audit

For Debian/Ubuntu servers, an audit should begin not only with checking the installed system package but also with an analysis of application dependencies. In the Node.js ecosystem, a vulnerable package  crypto-js can be present via  a  npmDocker  image, vendor directory, or transitive dependency.yarnpnpm

Checking a Debian package

apt-cache policy cryptojs
dpkg-query -W -f='${Package} ${Version}\n' cryptojs
apt list --installed 2>/dev/null | grep -Ei 'cryptojs|node-crypto-js'

These commands allow you to determine whether a system package is present and what version is actually installed. However, the absence of a package  cryptojs does  dpkg not rule out the presence of the library within a Node.js project.

Checking Node.js projects

npm ls crypto-js
npm explain crypto-js
grep -RIn --include='package.json' '"crypto-js"' /path/to/projects
find /path/to/projects -type f \( -name package-lock.json -o -name yarn.lock -o -name pnpm-lock.yaml \)

It is recommended to additionally analyze lock files, SBOM, and container images. The version of a dependency may differ from the version in the source  package.json due to transitive dependencies or an old lock file that pinned a historical build.

Finding dangerous API usage

grep -RIn \
  --include='*.js' \
  --include='*.ts' \
  --include='*.mjs' \
  --include='*.cjs' \
  'WordArray\.random' \
  /path/to/project

After finding the call, the result’s destination must be determined. Contexts with names or logic such as   ,  mnemonic,  wallet,  privateKey,  seed,  token,  reset,  secretand  apiKeyare  especially dangerous .noncesession

Safe replacement of generation

In Node.js, the built-in module should be used to generate secret bytes  node:crypto. It accesses the operating system’s cryptographically strong randomness source.

import { randomBytes } from 'node:crypto';

const entropy128 = randomBytes(16);  // 128 бит
const entropy256 = randomBytes(32);  // 256 бит

console.log(entropy128.toString('hex'));
console.log(entropy256.toString('hex'));

In the browser, you should use the Web Crypto API:

const entropy = new Uint8Array(32);
window.crypto.getRandomValues(entropy);

const hex = Array.from(entropy)
  .map(byte => byte.toString(16).padStart(2, '0'))
  .join('');

console.log(hex);

It is critically important not to replace CSPRNGs with constructs based on  Math.random(), time, PID, request counter, UUIDs of older versions, or a home-made mixture of multiple insecure sources. Combining weak sources does not automatically create cryptographic unpredictability.

Incident response

The response to CVE-2026-71851 must distinguish between two classes of objects: software components and historically created secrets. The library update eliminates the possibility of generating new weak values, but does not increase the entropy of keys, mnemonics, and tokens created before the update.

  1. Inventory all dependencies  crypto-js in Debian packages, Node.js projects, and container images.
  2. Check the actual calls  CryptoJS.lib.WordArray.random() and the purpose of the generated values.
  3. Update the library to a fixed upstream release or replace the insecure API with a system CSPRNG.
  4. Consider previously generated cryptographic secrets potentially compromised if they are created by a vulnerable function.
  5. Rotate private keys, API keys, reset tokens, and session secrets; invalidate old values.
  6. For wallets, create a new seed phrase in a trusted environment and transfer assets to new addresses.
  7. Analyze event logs, transactions, unusual authorizations, withdrawals, and API calls.
  8. Record the results in the SBOM, CMDB, risk register, and secure key generation procedure documentation.

Limitations of Risk Assessment

It’s impossible to infer a compromise based solely on the package version. The actual risk depends on whether the function was used for sensitive data, what specific values ​​were created, whether the attacker has access to validation artifacts, and how easily they can validate the candidates.

However, the absence of confirmed exploitation does not prove the security of previously issued keys or mnemonics. A conservative principle applies to cryptographic secrets: if the origin of the entropy is untrusted, the secret should be replaced, not simply left in use after a library update.

Conclusion

CVE-2026-71851 is a demonstrable vulnerability in applied cryptography: it does not directly break SHA-256, PBKDF2, AES, BIP39, or secp256k1. Instead, it reduces the search space of the original secret material to a level that makes targeted offline brute-force attacks realistic.

The Debian Security Tracker entry is important as a source of information about the distribution package’s state  cryptojs, but the flags  vulnerableand  should be interpreted in conjunction with the threat model of the specific application. For server environments and cryptocurrency services unfixed ,  <postponed> the correct strategy includes updating, searching for vulnerable API usage, replacing with CSPRNGs, and mandatory rotation of historically generated secrets.

Sources

Debian Security Tracker: CVE-2026-71851 (crypto-js): https://alpinvest.ru/debian-security-tracker-cve-2026-71851-crypto-js/

  1. Debian Security Tracker. CVE-2026-71851: crypto-js. https://security-tracker.debian.org/tracker/CVE-2026-71851
  2. GitHub Security Advisory. GHSA-rg76-677x-56q9: Insufficient Entropy in Cryptographic Secret Generation via Vulnerable CryptoJS Dependency Chain.
  3. Debian Security Team. Documentation on Debian Security Tracker statuses and the triage process.
  4. NIST SP 800-90A. Recommendation for Random Number Generation Using Deterministic Random Bit Generators.
  5. BIP39. Mnemonic code for generating deterministic keys.
  6. BIP32. Hierarchical Deterministic Wallets.