CVE-2026-101910
ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
CVE-2026-101910 is a medium vulnerability (CVSS 6.9) in Beaugunderson Ip-address, published September 28, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.39%, the 32nd percentile. Fixed in ip-address 10.5.1.
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- None
- User interaction
- None
What an attacker can affect
- Confidentiality
- Low
- Integrity
- None
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
6.9
ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
CVE-2026-101910- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Weakness
- CWE-918
- Updated
- 2026-11-02
EUVDEUVD-2026-88394
6.9
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
EUVD-2026-88394- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-2vr4-cq9g-pvrc
6.9
ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
Summary
No classifier on Address6 recognizes the NAT64 local-use range 64:ff9b:1::/48 (RFC 8215). isPrivate(), isLoopback(), isLinkLocal() and their siblings all return false for every address in it, so an internal IPv4 destination written through a local-use NAT64 prefix (64:ff9b:1:7f00:0:100:: for 127.0.0.1, 64:ff9b:1:a9fe:a9:fe00:: for 169.254.169.254) reads as an ordinary global address. getType() names the range 'NAT64 (local-use)', so the library knows what the address is and classifies it as nothing.
An application that builds a network trust-boundary decision on these checks (for example a filter intended to block Server-Side Request Forgery, or SSRF) will classify an internal target as external and allow the request. SSRF is an attack in which a user-supplied address coaxes the server into making a request to an internal destination the user could not otherwise reach, such as a loopback service or a cloud metadata endpoint.
Details
The fix for GHSA-22jq-vg5j-6vgg (10.2.1) classifies IPv4-mapped (::ffff:0:0/96) and NAT64 well-known (64:ff9b::/96) addresses by their embedded IPv4 address: embeddedIPv4() in src/ipv6.ts decodes the trailing 32 bits and every special-use classifier delegates to the resulting Address4. Those are the only two ranges embeddedIPv4() handles.
The local-use range differs in kind from the well-known prefix, which is why extending the decoder does not fix it. RFC 8215 reserves 64:ff9b:1::/48 so an operator can carve their own NAT64 prefix out of it, of any length RFC 6052 allows (/48, /56, /64, or /96). Where the IPv4 address sits depends on that choice: 127.0.0.1 is 64:ff9b:1:7f00:0:100:: under a /48 prefix and 64:ff9b:1::7f00:1 under a /96 prefix, and each of those decodes to a different address under the other prefix length. There is no single embedded IPv4 address for the library to classify by.
What is well-defined is the range as a whole. The IANA IPv6 Special-Purpose Address Registry lists 64:ff9b:1::/48 as not globally reachable, and Python's ipaddress module reports is_private as True and is_global as False for every address in it. isPrivate() covered ULA (fc00::/7) plus the decoded mapped and well-known cases, and nothing in the local-use range.
Affected versions
>= 10.2.0, <= 10.5.0. The is* classification API was extended to Address6 in 10.2.0; releases before it do not expose the method and are not affected through this vector.
Impact
Every address in 64:ff9b:1::/48 parses successfully, isValid() is true, and no classifier catches it. Which internal target is reached depends on the NAT64 prefix deployed on the server's network; the well-known prefix column is the patched control from GHSA-22jq-vg5j-6vgg.
| Internal target | Well-known form | Classified | Local-use form (/48 prefix) | Classified |
|---|---|---|---|---|
| 127.0.0.1 | 64:ff9b::7f00:1 | loopback | 64:ff9b:1:7f00:0:100:: | nothing |
| 10.0.0.1 | 64:ff9b::a00:1 | private | 64:ff9b:1:a00:0:100:: | nothing |
| 169.254.169.254 | 64:ff9b::a9fe:a9fe | link-local | 64:ff9b:1:a9fe:a9:fe00:: | nothing |
| 192.168.1.1 | 64:ff9b::c0a8:101 | private | 64:ff9b:1:c0a8:1:100:: | nothing |
Reachability
Reaching an internal host through one of these addresses requires that the server's network run a NAT64 translator on a prefix inside 64:ff9b:1::/48 and that the attacker guess or know the prefix length. That is the same precondition the well-known prefix carries (a translator on 64:ff9b::/96), with the additional constraint that the prefix is operator-chosen rather than fixed. The severity reflects that precondition.
Proof of concept
npm i [email protected], then:
const { Address6 } = require('ip-address');
// A guard of the shape the library documents.
function isBlocked(host) {
const a = new Address6(host);
return a.isLoopback() || a.isLinkLocal() || a.isPrivate() ||…
- Record
GHSA-2vr4-cq9g-pvrc- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Weakness
- CWE-918
- Updated
- 2026-11-02
NVD
6.9
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
CVE-2026-101910- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-918
- Updated
- 2026-11-02
OSV
6.9
ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
CVE-2026-101910- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVDEBIAN-CVE-2026-101910
6.9
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
DEBIAN-CVE-2026-101910- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Updated
- 2026-11-02
OSVGHSA-2vr4-cq9g-pvrc
6.9
ip-address: no classifier recognizes the NAT64 local-use range 64:ff9b:1::/48, allowing SSRF and trust-boundary bypass
Summary
No classifier on Address6 recognizes the NAT64 local-use range 64:ff9b:1::/48 (RFC 8215). isPrivate(), isLoopback(), isLinkLocal() and their siblings all return false for every address in it, so an internal IPv4 destination written through a local-use NAT64 prefix (64:ff9b:1:7f00:0:100:: for 127.0.0.1, 64:ff9b:1:a9fe:a9:fe00:: for 169.254.169.254) reads as an ordinary global address. getType() names the range 'NAT64 (local-use)', so the library knows what the address is and classifies it as nothing.
An application that builds a network trust-boundary decision on these checks (for example a filter intended to block Server-Side Request Forgery, or SSRF) will classify an internal target as external and allow the request. SSRF is an attack in which a user-supplied address coaxes the server into making a request to an internal destination the user could not otherwise reach, such as a loopback service or a cloud metadata endpoint.
Details
The fix for GHSA-22jq-vg5j-6vgg (10.2.1) classifies IPv4-mapped (::ffff:0:0/96) and NAT64 well-known (64:ff9b::/96) addresses by their embedded IPv4 address: embeddedIPv4() in src/ipv6.ts decodes the trailing 32 bits and every special-use classifier delegates to the resulting Address4. Those are the only two ranges embeddedIPv4() handles.
The local-use range differs in kind from the well-known prefix, which is why extending the decoder does not fix it. RFC 8215 reserves 64:ff9b:1::/48 so an operator can carve their own NAT64 prefix out of it, of any length RFC 6052 allows (/48, /56, /64, or /96). Where the IPv4 address sits depends on that choice: 127.0.0.1 is 64:ff9b:1:7f00:0:100:: under a /48 prefix and 64:ff9b:1::7f00:1 under a /96 prefix, and each of those decodes to a different address under the other prefix length. There is no single embedded IPv4 address for the library to classify by.
What is well-defined is the range as a whole. The IANA IPv6 Special-Purpose Address Registry lists 64:ff9b:1::/48 as not globally reachable, and Python's ipaddress module reports is_private as True and is_global as False for every address in it. isPrivate() covered ULA (fc00::/7) plus the decoded mapped and well-known cases, and nothing in the local-use range.
Affected versions
>= 10.2.0, <= 10.5.0. The is* classification API was extended to Address6 in 10.2.0; releases before it do not expose the method and are not affected through this vector.
Impact
Every address in 64:ff9b:1::/48 parses successfully, isValid() is true, and no classifier catches it. Which internal target is reached depends on the NAT64 prefix deployed on the server's network; the well-known prefix column is the patched control from GHSA-22jq-vg5j-6vgg.
| Internal target | Well-known form | Classified | Local-use form (/48 prefix) | Classified |
|---|---|---|---|---|
| 127.0.0.1 | 64:ff9b::7f00:1 | loopback | 64:ff9b:1:7f00:0:100:: | nothing |
| 10.0.0.1 | 64:ff9b::a00:1 | private | 64:ff9b:1:a00:0:100:: | nothing |
| 169.254.169.254 | 64:ff9b::a9fe:a9fe | link-local | 64:ff9b:1:a9fe:a9:fe00:: | nothing |
| 192.168.1.1 | 64:ff9b::c0a8:101 | private | 64:ff9b:1:c0a8:1:100:: | nothing |
Reachability
Reaching an internal host through one of these addresses requires that the server's network run a NAT64 translator on a prefix inside 64:ff9b:1::/48 and that the attacker guess or know the prefix length. That is the same precondition the well-known prefix carries (a translator on 64:ff9b::/96), with the additional constraint that the prefix is operator-chosen rather than fixed. The severity reflects that precondition.
Proof of concept
npm i [email protected], then:
const { Address6 } = require('ip-address');
// A guard of the shape the library documents.
function isBlocked(host) {
const a = new Address6(host);
return a.isLoopback() || a.isLinkLocal() || a.isPrivate() ||…
- Record
GHSA-2vr4-cq9g-pvrc- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Weakness
- CWE-918
- Updated
- 2026-11-02
OSVUBUNTU-CVE-2026-101910
6.9
ip-address is a library for parsing and manipulating IPv4 and IPv6 addresses in JavaScript. From 10.2.0 until 10.5.1, the Address6 isPrivate classifier in src/ipv6.ts does not recognize the NAT64 local-use range 64:ff9b:1::/48. Applications that combine isPrivate, isLoopback, and isLinkLocal for a trust-boundary decision can treat an internal IPv4 destination encoded through that range as external. Exploitation depends on a server network using an operator-selected NAT64 prefix within the local-use range. A successful bypass can cross the intended network trust boundary. This issue is fixed in version 10.5.1.
- Record
UBUNTU-CVE-2026-101910- CVSS 4.0
- 6.9 Medium
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:N - Updated
- 2026-11-02
OSVCLSA-2026-1792369098 No score
TuxCare security update for ip-address (4 CVEs)
TuxCare rebuilt ip-address to address 4 CVEs. Fixed in 10.5.0-tuxcare.1.
- Record
CLSA-2026-1792369098- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
ip-addressnpm |
10.2.0 to 10.5.0 | 10.5.1 |
ip-addressTuxCare:npm |
10.5.0-tuxcare.0 up to 10.5.0-tuxcare.1, plus listed versions 10.5.0 |
10.5.0-tuxcare.1 |
node-ip-addressDebian:14 |
before 10.7.2-1, plus listed versions 10.2.0-110.2.0-210.3.1-110.4.0-18.1.0-28.1.0-3 |
10.7.2-1 |
ip-addressnpm |
10.2.0 up to 10.5.1 | 10.5.1 |
node-ip-addressUbuntu:20.04:LTS |
All versions, plus listed versions 6.3.0-1 |
None known |
node-ip-addressUbuntu:22.04:LTS |
All versions, plus listed versions 6.4.0-18.1.0-2 |
None known |
node-ip-addressUbuntu:24.04:LTS |
All versions, plus listed versions 8.1.0-2 |
None known |
node-ip-addressUbuntu:26.10 |
All versions, plus listed versions 8.1.0-310.2.0-210.3.1-110.4.0-1 |
None known |
node-ip-addressUbuntu:26.04:LTS |
All versions, plus listed versions 8.1.0-28.1.0-3 |
None known |
History
| When | Changed | Sources |
|---|---|---|
| 2026-11-02 | created | CVE List, EUVD, GitHub Advisories, NVD, OSV |
References
github.com/beaugunderson/ip-address/security/advisories/GHSA-2vr4-cq9g-pvrc
github.com/beaugunderson/ip-address/commit/ab3dc88bcf5374344168a2ba075ca7ac4ff257f8
github.com/beaugunderson/ip-address/releases/tag/v10.5.1
nvd.nist.gov/vuln/detail/CVE-2026-101910
github.com/advisories/GHSA-2vr4-cq9g-pvrc
github.com/CVEProject/cvelistV5/tree/main/cves/2026/101xxx/CVE-2026-101910.json
Left out here: the rest of 2 source descriptions. The JSON record has them.