Sep 30, 2026·6 min read·6 visits
A logical error in the ip-address library allows cross-family IP comparisons (IPv4 vs. IPv6) to collide. This enables attackers to bypass IP-based filters and access controls by submitting crafted IPv6 addresses that mimic private IPv4 subnets.
The ip-address library is vulnerable to a logical bypass in its subnet containment methods. The functions isInSubnet() and isHostInSubnet() do not verify that compared addresses belong to the same IP family before performing masking checks. Under specific circumstances, an IPv6 address can share leading bit patterns with an IPv4 subnet, causing the containment check to evaluate as true. This allows attackers to bypass access control lists, firewalls, and server-side request forgery protection layers in applications relying on the library.
The ip-address library is a widely utilized package in the JavaScript and TypeScript ecosystems for parsing, manipulating, and validating IPv4 and IPv6 addresses. Security-sensitive systems frequently use this package to implement IP-based access control lists, firewalls, and server-side request forgery filtering mechanisms. When applications evaluate network boundaries, they rely on containment utilities to verify if a given IP address belongs to a specific range.
CVE-2026-101912 identifies a serious logical flaw within the subnet containment validation functions defined in src/common.ts. These functions, including isInSubnet() and isHostInSubnet(), perform comparisons on binary-masked strings. However, they fail to verify that both the subnet and the host belong to the same IP family before performing the evaluation. This incorrect comparison leads to a false-positive equivalence when checking disjoint network types.
The vulnerability is classified under CWE-697 (Incorrect Comparison) and CWE-843 (Access of Resource Using Incompatible Type, also known as Type Confusion). Because of the dynamic nature of JavaScript type matching, the library allows an Address6 object to be processed within an Address4 containment verification context. If the leading bits of an IPv6 address align with the prefix of an IPv4 subnet, the library incorrectly determines that the host is contained within that subnet.
The underlying security issue resides in the shared utility functions within src/common.ts of the ip-address codebase. The function isHostInSubnet() compares the masked binary representation of a target address against the masked binary representation of the host. Specifically, it retrieves the subnet mask of the network operand and applies that mask length to the binary representation of the host address.
When a mask is applied via the .mask(n) helper, the library computes the leading bits up to the length n and returns them as a zero-padded binary string. For an IPv4 address, the binary length is at most 32 bits, whereas for an IPv6 address, it is 128 bits. If a short subnet mask is applied to both, the library only evaluates the first n bits of each address representation.
Consider the comparison between the IPv4 subnet 10.0.0.0/8 and the IPv6 address a00::1. The first octet of the IPv4 address is 10, which yields the 8-bit binary string 00001010. The first 16-bit block of the IPv6 address a00::1 is 0a00, which converts to the binary sequence 0000101000000000. Masking this IPv6 address to 8 bits extracts the identical binary sequence 00001010. The comparison of these two strings evaluates to true despite the addresses belonging to disjoint network layers.
To understand the exact structural vulnerability, we must examine the implementation of the isHostInSubnet function prior to version 10.7.1. The vulnerable logic did not contain any validation checks to enforce type or bit-width consistency between the two compared entities.
// Vulnerable code in src/common.ts before v10.7.1
export function isHostInSubnet(this: Address4 | Address6, address: Address4 | Address6) {
// The function directly calls mask on the host and compares it to the address mask
// No validation is performed on 'this' versus 'address' classes or lengths
return this.mask(address.subnetMask) === address.mask();
}The patched version introduces a strict verification check that compares the padded binary string lengths before executing the masking comparison. Because IPv4 addresses pad to 32 characters and IPv6 addresses pad to 128 characters, any type mismatch is caught immediately before the string equivalence comparison.
// Patched code in src/common.ts in v10.7.1
export function isHostInSubnet(this: Address4 | Address6, address: Address4 | Address6) {
// Confirm that both address classes have matching binary zero-padded lengths
// This isolates 32-bit IPv4 addresses from 128-bit IPv6 addresses
if (this.binaryZeroPad().length !== address.binaryZeroPad().length) {
return false;
}
return this.mask(address.subnetMask) === address.mask();
}This remediation ensures that cross-family comparison attempts always return false, neutralizing the logical flaw.
Exploitation of CVE-2026-101912 requires a target application to accept arbitrary IP address inputs and validate them against a restricted subnet using the ip-address library. Common targets include administrative dashboards, forward proxies, or webhooks that employ IP-based access control lists (ACLs) to block internal connections.
An attacker can craft a specific IPv6 address designed to collide with a restricted internal IPv4 range. In a typical Server-Side Request Forgery (SSRF) bypass scenario, the application might block private IP ranges (such as 10.0.0.0/8). By supplying the IPv6 address a00::1, which evaluates to the same leading 8-bit sequence as 10.0.0.0/8, the containment check evaluates to true. If the application logic permits requests based on this containment check, the filter is bypassed.
This diagram displays the process by which different families produce matching binary patterns, resulting in the security bypass.
The security impact of CVE-2026-101912 depends heavily on the context in which the ip-address library is used. In applications utilizing the library to enforce network isolation, this vulnerability can lead to authorization bypasses, access control list evasion, or server-side request forgery. The CVSS v4.0 base score is calculated at 6.3, reflecting medium severity with partial integrity impact.
An attacker exploiting this flaw cannot execute arbitrary code directly through the library itself, but they can subvert routing or proxy constraints to query internal microservices. In cloud environments, this may expose sensitive internal metadata endpoints, such as the Instance Metadata Service (IMDS). Evasion of access controls on administrative interfaces can also lead to unauthorized data disclosure if backend APIs are exposed to external queries.
The Exploit Prediction Scoring System (EPSS) score is 0.0037, indicating a low probability of active exploitation in typical deployments. However, because the logical flaw is deterministic, security researchers can easily replicate the behavior to identify vulnerable ingress points.
The primary remediation strategy is upgrading the ip-address package to version 10.7.1 or later. This version enforces strict length comparisons, preventing type collisions between IPv4 and IPv6 addresses. Development teams must update their package manifests and rebuild their environments to apply the patch.
If upgrading is not immediately possible, applications should implement input sanitization to ensure that only a single IP family is processed within a given validation loop. Explicitly verifying that the input string does not contain colon characters before checking against an IPv4 subnet provides an immediate workaround. Normalizing all incoming IP representations prior to passing them to validation methods reduces the risk of type confusion.
// Temporary mitigation workaround
function safeSubnetCheck(userInput, allowedSubnet) {
const isUserV6 = userInput.includes(':');
const isSubnetV6 = allowedSubnet.includes(':');
if (isUserV6 !== isSubnetV6) {
return false; // Force fail if families mismatch
}
// Proceed to standard evaluation safely
}Additionally, implementing strict firewall rules at the network layer provides defense-in-depth, ensuring that logical bypasses within application code do not translate to successful network connections.
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N| Product | Affected Versions | Fixed Version |
|---|---|---|
ip-address Beau Gunderson | < 10.7.1 | 10.7.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-697 / CWE-843 |
| Attack Vector | Network (AV:N) |
| CVSS v4.0 Score | 6.3 (Medium) |
| EPSS Score | 0.0037 (Percentile: 28.38%) |
| Impact | Partial Integrity (ACL/SSRF Filter Bypass) |
| Exploit Status | Proof-of-Concept (PoC) Available |
| KEV Status | Not Listed |
The library compares two binary masked strings representing different IP families without ensuring that both operands are of the same type, resulting in a false-positive equivalence check.
A stack-based Denial of Service (DoS) vulnerability via uncontrolled recursion in the brace-expansion library prior to versions 1.1.20, 2.1.6, 3.0.8, and 5.0.11 allows unauthenticated remote attackers to trigger native stack exhaustion, terminating the Node.js process via a crafted payload containing deeply nested brace groups.
An uncontrolled resource consumption vulnerability exists in the brace-expansion JavaScript library. Due to an algorithmic flaw in parsing a legacy Bash-compatibility quirk involving {a},b}-shaped expansion structures, untrusted inputs containing many trailing closing braces trigger successive full-input rescans. This behavior yields quadratic CPU time complexity and high memory overhead, allowing remote, unauthenticated attackers to cause a Denial of Service (DoS) by blocking the single-threaded Node.js event loop.
Moment.js versions 2.29.2 through 2.30.1 are vulnerable to a Path Traversal flaw (CWE-27) on server-side Node.js environments when dynamic locales are configured. The vulnerability stems from an object-coercion bypass in the locale-name sanitization routine, which assumes incoming variables are string primitives. An attacker can pass a structured object with custom 'match' and 'toString' properties to bypass regex-based directory checks, leading to arbitrary file loading via Node's internal 'require()' call.
A denial-of-service vulnerability exists in the ip-address npm package prior to version 10.7.1. The library fails to limit the length of input strings parsed by the Address4 and Address6 constructors. When parsing highly malformed addresses, the diagnostic parser runs a synchronous regular expression search-and-replace that generates descriptive HTML error messages. Passing an excessively long string containing invalid characters causes severe memory amplification and CPU starvation, resulting in a thread hang or process crash in Node.js applications.
CVE-2026-101894 is a critical path traversal vulnerability in @xhmikosr/decompress before versions 10.2.2 and 11.1.4, stemming from an incomplete hardening bypass of CVE-2026-53486 where static lexical containment checks fail to detect kernel-level resolution of crafted symlink chains, allowing arbitrary local file modification and execution.
A security-critical desynchronization vulnerability exists in fast-uri versions 4.1.3 and 4.1.4. Due to incorrect order-of-operations, the mailto scheme parser validates raw percent-encoded parameter keys instead of normalized keys, but subsequently decodes and writes them into a generic headers object. When the parsed URI is serialized, these keys are re-emitted literally, allowing attackers to bypass validation boundaries and smuggle unauthorized recipients, subjects, or body parameters in downstream mailing applications.