CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2026-2739

The Ghost in the Machine: How an Empty Number Killed the Node.js Event Loop

Alon Barad
Alon Barad
Software Engineer

Feb 20, 2026·6 min read·41 visits

Executive Summary (TL;DR)

Invoking `maskn(0)` on a BigNumber instance corrupts its internal state by setting its length to 0. This causes critical methods like `toString()` to enter an infinite loop, crashing Node.js applications.

A logic error in the widely used 'bn.js' BigNumber library allows for a Denial of Service via state corruption. By invoking the bitwise masking function with a zero length, an attacker can violate internal object invariants, creating a 'ghost' number with a length of zero. This corrupted state forces subsequent operations like serialization or division into infinite loops, freezing the single-threaded Node.js process instantly.

The Hook: Big Integers, Big Problems

JavaScript has a complicated relationship with numbers. For years, we were stuck with IEEE 754 doubles, meaning anything integer-like above $2^{53}$ was a gamble. Enter bn.js, the unsung hero of the ecosystem. It is the bedrock for elliptic curve cryptography, blockchain implementations, and basically anything in Node.js that needs to count higher than a standard database ID.

But here's the thing about foundational libraries: when they crack, the tremors are felt everywhere. CVE-2026-2739 isn't a buffer overflow or a remote code execution via some complex gadget chain. It's a logic bug. A simple, stupid logic bug that turns a mathematical operation into a weapon of mass thread-destruction.

This vulnerability exploits the internal representation of these big numbers. By asking the library to perform a specific bitwise operation—masking a number with zero bits—we can trick the object into an invalid state. It creates a number that technically exists but has no data. When the library tries to read this 'ghost' number, it panics, loops, and takes your server down with it.

The Flaw: The Impossible Zero

To understand the bug, you have to look under the hood of bn.js. Since JavaScript didn't support 64-bit integers natively for a long time, bn.js implements numbers as an array of 'words' (usually 26-bit chunks) and a length property tracking how many words are in use.

The Invariant: The library relies on a strict invariant: length must always be at least 1. Even the number 0 is represented as words: [0], length: 1. There is no such thing as a number with no words.

The Glitch: The vulnerability lies in maskn(bits) (and imaskn). This function is supposed to keep only the lowest n bits of the number. The logic calculates how many words are needed to hold those bits and truncates the rest.

However, the developers forgot a critical edge case: maskn(0). When you ask for the lowest 0 bits, the calculation effectively wipes the array. Prior to version 5.2.3, this operation would set this.length = 0.

Congratulations. You have created a zombie object. It is a BN instance that violates the fundamental laws of its own universe. It has no length. It is a void.

The Code: Anatomy of a Fix

The fix is almost insultingly simple, which is characteristic of the most dangerous bugs. The developers just needed to ensure that if the masking operation wipes the number clean, it resets to the canonical 'zero' state rather than the 'void' state.

Here is the diff from the patch. Note the explicit check for the zero-length condition:

// lib/bn.js
 
   BN.prototype.imaskn = function imaskn(bits) {
     // ... existing logic truncating words ...
 
     // The Vulnerable State: words might be empty now.
+    // The Fix: Force it back to a valid Zero.
+    if (this.length === 0) {
+      this.words[0] = 0;
+      this.length = 1;
+    }
 
     return this._strip();
   };

Without this guard clause, this.length remains 0. The _strip() method, which is supposed to remove leading zero words, assumes there is at least one word to check. When length is 0, the internal logic of downstream functions collapses.

The Exploit: One Line to Kill

You don't need Metasploit for this. You don't need heap spraying. You just need a Node.js console. The exploitation is trivial because the corruption happens silently. The crash doesn't occur when you create the bad number; it happens when you try to look at it.

The PoC:

const BN = require('bn.js');
 
// Step 1: Create a perfectly normal number
const target = new BN('123456');
 
// Step 2: Corrupt it. 
// We ask for the lowest 0 bits. Theoretically, this is 0.
// Practically, it creates an invalid object.
target.maskn(0);
 
// Step 3: Trigger the infinite loop.
// toString() relies on length to iterate. 
// With length 0, the loop condition is never met or underflows.
console.log("Goodbye, Event Loop...");
target.toString(); 

Why toString() hangs: The toString method usually performs repeated division and modulo operations to convert the number base (e.g., base 10). These algorithms loop while (number > 0). Because the internal state is corrupted (length: 0), the comparison logic fails to report '0', or the division step produces a result that doesn't reduce the problem size, resulting in an infinite while(true) scenario.

The Impact: Asymmetric Warfare

In a threaded environment like Java or C++, a CPU-spinning infinite loop is bad, but it usually only kills one worker thread. The rest of the application limps on.

Node.js is single-threaded. It runs on an event loop. If any operation blocks that loop—like a while(true) caused by a corrupt BigNumber—the entire process stops. It stops accepting HTTP requests. It stops processing database callbacks. It stops responding to health checks.

Attack Vectors:

  1. Smart Contracts/dApps: Many dApps use bn.js to handle token amounts. If a user can pass a parameter that results in a bit-mask of 0, they can freeze the processing node.
  2. Cryptography Handlers: If an implementation derives a mask length from user input (e.g., "give me the last N bits of this key"), sending N=0 triggers the DoS.
  3. Data Serialization: JSON endpoints that accept big integers and perform transformations before saving them are prime targets.

The Fix: Upgrade or Die

If you are running bn.js < 5.2.3, you are vulnerable. The dependency tree of the average Node project is deep and dark; you might not even know you are using it. elliptic, web3.js, and asn1.js all rely on it.

Remediation:

  1. Update Direct Dependencies: npm install bn.js@latest.
  2. Audit Transitive Dependencies: Use npm audit or yarn audit. You will likely need to regenerate lockfiles to force nested dependencies to grab the patched version.
  3. Defensive Coding: If you cannot update immediately, sanitize inputs. Never pass 0 to a bitwise mask function.
// The monkey-patch band-aid
const BN = require('bn.js');
const originalMaskn = BN.prototype.maskn;
BN.prototype.maskn = function(bits) {
  if (bits === 0) return new BN(0);
  return originalMaskn.apply(this, arguments);
};

This is a classic example of why input validation is hard—sometimes the invalid input (0) looks perfectly harmless.

Official Patches

indutny (GitHub)Official patch commit

Fix Analysis (1)

Technical Appendix

CVSS Score
6.9/ 10
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:P
EPSS Probability
0.01%
Top 97% most exploited

Affected Systems

Node.js applications using `bn.js`Cryptographic libraries (`elliptic`, `crypto-browserify`)Web3.js and Ethereum-related SDKsASN.1 parsers relying on BigNum arithmetic

Affected Versions Detail

Product
Affected Versions
Fixed Version
bn.js
indutny
< 5.2.35.2.3
AttributeDetail
CWE IDCWE-835
Attack VectorNetwork (AV:N)
CVSS v4.06.9 (Medium)
ImpactDenial of Service (Infinite Loop)
Affected Componentbn.js `maskn`/`imaskn` methods
Exploit StatusPoC Available

MITRE ATT&CK Mapping

T1499.003Endpoint Denial of Service: OS Exhaustion
Impact
CWE-835
Infinite Loop

Loop with Unreachable Exit Condition ('Infinite Loop')

Known Exploits & Detection

GitHub GistProof of Concept demonstrating the infinite loop in bn.js

Vulnerability Timeline

Vulnerability reported by Kr0emer
2026-02-08
Fix committed to main branch
2026-02-19
Release 5.2.3 published to NPM
2026-02-19
CVE-2026-2739 published
2026-02-20

References & Sources

  • [1]GitHub Issue #316: maskn(0) causes infinite loop
  • [2]Snyk Advisory for CVE-2026-2739

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.

More Reports

•about 4 hours ago•CVE-2024-29203
4.3

CVE-2024-29203: Client-Side Cross-Site Scripting via Unsandboxed Iframes and Legacy Embed Elements in TinyMCE

CVE-2024-29203 identifies a cross-site scripting (XSS) vulnerability in the content ingestion and parsing mechanics of TinyMCE rich text editor. Due to a failure to enforce sandbox attributes on dynamic iframe elements and safely handle legacy embed objects, unauthenticated attackers can inject malicious elements that execute scripts within the context of the parent application session.

Amit Schendel
Amit Schendel
5 views•5 min read
•about 6 hours ago•CVE-2026-9277
8.1

CVE-2026-9277: OS Command Injection in shell-quote via Object-Token Line Terminator Parsing Defect

A technical breakdown of the OS command injection vulnerability in the shell-quote NPM package (CVE-2026-9277 / GHSA-w7jw-789q-3m8p). The bug resides in the character-by-character backslash-escaping logic applied to the .op field of object-tokens within the quote() function, which fails to match and escape line terminators due to a regex matching oversight in JavaScript. This allows unauthenticated remote attackers to execute arbitrary shell commands if they can control inputs processed by this library.

Alon Barad
Alon Barad
10 views•6 min read
•about 7 hours ago•CVE-2026-11645
8.8

CVE-2026-11645: Out-of-Bounds Memory Access in Google Chrome V8 Engine

A high-severity memory corruption vulnerability exists in the V8 JavaScript engine of Google Chrome before versions 149.0.7827.102/103. The flaw arises from an incorrect bounds-check elimination during JIT compilation by the TurboFan optimizer, allowing remote attackers to achieve out-of-bounds read and write access inside the sandboxed renderer process.

Amit Schendel
Amit Schendel
23 views•6 min read
•about 16 hours ago•CVE-2026-50751
9.3

CVE-2026-50751: Authentication Bypass in Check Point Security Gateway IKEv1 Legacy Validation

An improper authentication vulnerability (CWE-287) exists in the legacy, deprecated Internet Key Exchange version 1 (IKEv1) key exchange protocol implementation in Check Point Security Gateways. The vulnerability is caused by a logic flow weakness during the certificate validation process for Remote Access VPN and Mobile Access (SSL VPN) connections. An unauthenticated remote attacker can exploit this weakness to bypass user authentication entirely, establishing a fully functional Remote Access VPN connection without a valid password.

Alon Barad
Alon Barad
69 views•6 min read
•1 day ago•CVE-2026-39922
6.3

CVE-2026-39922: Server-Side Request Forgery in GeoNode Service Registration Endpoint

GeoNode versions prior to 4.4.5 and 5.0.2 are vulnerable to Server-Side Request Forgery (SSRF) in the service registration endpoint. Authenticated attackers with low privileges can exploit insufficient input validation in the Web Map Service (WMS) registration module to force the application server to make outbound network queries to loopback addresses, private RFC1918 subnets, link-local scopes, and cloud metadata endpoints. This technical report details the mechanics of the vulnerability, the underlying architectural flaw, and how to effectively remediate and mitigate the associated security risks.

Alon Barad
Alon Barad
4 views•7 min read
•1 day ago•CVE-2022-0492
7.8

CVE-2022-0492: Privilege Escalation and Container Escape via cgroups v1 release_agent

CVE-2022-0492 is a high-severity missing authorization vulnerability in the Linux kernel's Control Groups (cgroups) v1 implementation. The flaw resides within the cgroup_release_agent_write function in kernel/cgroup/cgroup-v1.c, where the kernel fails to validate if the process writing to the release_agent file possesses administrative capabilities in the initial user namespace. This allows a local attacker inside a container with root privileges (UID 0) to abuse user namespaces, mount a cgroups v1 directory, modify the release_agent parameter, and execute arbitrary commands on the host system as host root, effectively achieving a complete container escape.

Amit Schendel
Amit Schendel
12 views•7 min read