chore(deps): update dependency ip-address to >=10.3.1 [security] - #1190
Closed
renovate[bot] wants to merge 1 commit into
Closed
chore(deps): update dependency ip-address to >=10.3.1 [security]#1190renovate[bot] wants to merge 1 commit into
renovate[bot] wants to merge 1 commit into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
2 times, most recently
from
August 9, 2026 09:30
3b39c53 to
10506e1
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 9, 2026 09:35
10506e1 to
3890f4a
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
2 times, most recently
from
August 9, 2026 13:22
50aa2d7 to
38869c9
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 9, 2026 18:04
38869c9 to
8734509
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 9, 2026 18:10
8734509 to
2aba518
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 9, 2026 20:34
2aba518 to
40afaeb
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 9, 2026 20:39
40afaeb to
f8f2d4d
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 02:03
f8f2d4d to
d3dd3c9
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 02:14
d3dd3c9 to
f02e23b
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 05:55
f02e23b to
d7313c0
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 05:59
d7313c0 to
fe189f6
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 08:45
fe189f6 to
5825a70
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 08:51
5825a70 to
8a60022
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 14:51
8a60022 to
99f7c0f
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 14:57
99f7c0f to
eede4d8
Compare
renovate
Bot
force-pushed
the
renovate/npm-ip-address-vulnerability
branch
from
August 10, 2026 19:06
eede4d8 to
a80e8a5
Compare
h4yfans
added a commit
that referenced
this pull request
Aug 12, 2026
…1356) Bundles five stale bot PRs into a single change against current main so one coherent lockfile lands instead of nine conflicting stale ones. - prettier ^3.8.3 -> ^3.9.6 (#1197) - ip-address override >=10.1.1 -> >=10.3.1, resolves 10.5.0 (#1190, security) - hono override >=4.12.27 -> >=4.12.34, resolves 4.13.1 (#1189, security) - nanoid@>=4.0.0 <5.0.9 override 5.0.9 -> 5.1.16 (#1194) - framer-motion -> motion ^12.24.7 in landing (#1196) The renovate PR for the motion swap replaced the package but left all 49 `from 'framer-motion'` imports untouched, which does not resolve once framer-motion is off the manifest. Repointed them at `motion/react` and updated the vite manualChunks entry that named the old package. Left out deliberately: #1193 (nanoid 6.0.0 major) and #1195 (forces a 3.x transitive to v5) — both advisories are already closed by the existing pins, so they add breakage risk without security value.
Collaborator
|
Superseded by #1356 (merged as Verified on main: hono 4.13.1, ip-address 10.5.0, nanoid 5.1.16, prettier 3.9.6, motion 12.34.0. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR contains the following updates:
>=10.1.1→>=10.3.1ip-address: misclassification of IPv4-mapped/NAT64 IPv6 addresses can bypass SSRF and trust-boundary checks
CVE-2026-54272 / GHSA-22jq-vg5j-6vgg
More information
Details
Summary
Address6's special-property checks misclassify IPv4-mapped (::ffff:0:0/96) and NAT64 well-known (64:ff9b::/96) IPv6 addresses. These checks classify an address by its IPv6 wrapper rather than by the IPv4 address it embeds, soisLoopback(),isLinkLocal(),isMulticast(), andisUnspecified()all returnfalsefor literals such as::ffff:127.0.0.1or::ffff:169.254.169.254that actually route to loopback, RFC 1918, or link-local (cloud-metadata) destinations.Address6also had noisPrivate()method, so a mapped RFC 1918 address could not be detected at all.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) may therefore treat 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
Address6.getType()classifies an address by matching it against a table of known IPv6 special-use prefixes, returningGlobal unicastwhen nothing matches. That table had no entry for the IPv4-mapped range (::ffff:0:0/96), so every mapped address fell through toGlobal unicast; NAT64 addresses matched their ownNAT64 …labels. The boolean checksisLoopback,isUnspecified, andisMulticastcomparedgetType()against a fixed label and so returnedfalse, whileisLinkLocalandisULAchecked only the native IPv6 ranges.The library already exposed
isMapped4()andto4(), but did not apply them inside these checks, so a mapped or NAT64 address was never normalized to its embedded IPv4 address before classification. The underlying CIDR matching is correct; the defect is that the special-use table omitted the IPv4-mapped range and the checks performed no embedded-IPv4 normalization.Affected versions
>= 10.1.1, <= 10.2.0. Theis*classification API was introduced forAddress4in 10.1.1 and extended toAddress6in 10.2.0. Releases before 10.1.1 do not expose this API and are not affected through this vector.Impact
The misclassification covers the entire
::ffff:0:0/96range, in both dotted and hex notation and case-insensitively, plus the64:ff9b::/96NAT64 well-known prefix:::ffff:127.0.0.1/::ffff:7f00:1127.0.0.0/8)::ffff:10.0.0.110/8::ffff:172.16.5.5172.16/12::ffff:192.168.1.1192.168/16::ffff:169.254.169.254/::ffff:a9fe:a9fe::ffff:100.64.0.1100.64/10::ffff:0.0.0.0/::ffff:255.255.255.25564:ff9b::7f00:1/64:ff9b::a9fe:a9feFor IPv4-mapped addresses the host OS routes to the IPv4 stack, so the misclassification is reachable on any dual-stack host. For NAT64, the classification bypass is unconditional but end-to-end reachability additionally requires a NAT64/DNS64 gateway in the deployment network.
Proof of concept
A guard assembled from these checks lets internal hosts through:
On affected versions this prints (note that every
::ffff:…and64:ff9b::…internal target is allowed):The first three lines (native loopback, native IPv6 loopback, and a literal RFC 1918 address) are blocked as expected; the IPv4-mapped and NAT64 forms of the same internal destinations are allowed through.
Remediation
Upgrade to the patched release. In the fix,
Address6normalizes IPv4-mapped and NAT64 well-known addresses to their embedded IPv4 address before classifying, via a newembeddedIPv4()helper thatisLoopback,isLinkLocal,isMulticast, andisUnspecifiedconsult first.Address6also gainsisPrivate(),isCGNAT(), andisBroadcast()for parity withAddress4, andgetType()now labels the::ffff:0:0/96range asIPv4-mapped. After upgrading,new Address6('::ffff:127.0.0.1').isLoopback()returnstrueandnew Address6('::ffff:10.0.0.1').isPrivate()returnstrue.If you cannot upgrade immediately, normalize embedded IPv4 addresses yourself before classifying: call
to4()on any address whereisMapped4()(or membership in64:ff9b::/96) is true, and run your IPv4 checks against the result.A note on SSRF defense
These methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the resolved IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.
Credit
Reported by @OV-0-VO.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
ip-address: a CIDR suffix on the parsed address suppresses special-use classification and can bypass SSRF and trust-boundary checks
CVE-2026-69198 / GHSA-4xrf-jv44-h6hh
More information
Details
Summary
Every special-use classification method is built on
isInSubnet, which short-circuits tofalsewhenever the address's own subnet mask is shorter than the reference range's mask. That mask comes verbatim from the CIDR suffix on the parsed input, so appending a suffix such as/0suppresses classification entirely:isLoopback(),isPrivate(),isLinkLocal(),isCGNAT(),isMulticast(),isUnspecified(),isBroadcast(),isULA(), andgetType()all report an internal address as unremarkable, whilecorrectForm()andaddressstill return the real internal target.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) may therefore treat 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
isInSubnetinsrc/common.tsopens with a guard that compares the two prefix lengths:That guard is correct for the question
isInSubnetis named for — whether one network is contained in another, where a/0network genuinely is not inside a/8. It is wrong for classification, which asks a question about the address itself and must not depend on the prefix the caller happened to write./0is shorter than every reference prefix in the special-use tables (loopback/8, link-local/16, CGNAT/10, ULA/7, multicast/4), so for a classification call the bit comparison is never reached and the method returnsfalse.The underlying bit comparison is correct, and
mask(n)already returns the firstnbits of the full parsed address independently ofsubnetMask— the defect is solely that the containment guard sits in the classification path. Host bits are retained through parsing, socorrectForm()still yields the real target and the address remains fully usable for connecting./0is the universal case because it is shorter than every reference prefix, but any suffix shorter than the specific range being tested has the same effect:10.0.0.5/7defeatsisPrivate()for10.0.0.0/8.Affected versions
>= 10.1.1, <= 10.2.1. Theis*classification API was introduced forAddress4in 10.1.1 and extended toAddress6in 10.2.0; releases before 10.1.1 do not expose it and are not affected through this vector. The containment guard itself is much older, butisInSubnetalone is a subnet-containment predicate whose behavior here is correct.This also defeats the fix released in 10.2.1 for GHSA-22jq-vg5j-6vgg: that release classifies IPv4-mapped and NAT64 addresses by their embedded IPv4 address, but the normalization is reached through
isInSubnet, so::ffff:127.0.0.1/0reverts to being reported as non-internal.Impact
Every classifier is affected on both
Address4andAddress6. The sole exception isAddress6.isLinkLocal()for nativefe80::/10addresses, which compares raw bits directly; its IPv4-mapped path is still affected.127.0.0.1/0127.0.0.0/8)10.0.0.1/0,10.0.0.5/710/8172.16.5.5/0172.16/12192.168.1.1/0192.168/16169.254.169.254/0100.64.0.1/0100.64/100.0.0.0/0,255.255.255.255/0::1/0fc00::1/0fc00::/7ff02::1/0::ffff:127.0.0.1/0::ffff:169.254.169.254/064:ff9b::7f00:1/0getType()returnsGlobal unicastfor all of the IPv6 cases above, andgetScope()follows it.Reachability
A CIDR suffix is not legal in a URL host, so this is not reachable through the most common SSRF shape.
new URL('http://127.0.0.1/0')parseshostnameas127.0.0.1andpathnameas/0, and a guard that classifies the extracted hostname is unaffected. Exploitation requires an application that accepts a bare address string that may carry a suffix and passes it to the constructor before classifying — for example an allow/deny field, a webhook target, or a proxy destination taken as a plain host rather than parsed out of a URL.Proof of concept
npm i ip-address@10.2.1, then:On affected versions every suffixed internal target is allowed, and
correctForm()shows the request would reach the real internal address:The first three lines are blocked as expected; the same destinations with a CIDR suffix are allowed through.
Remediation
Upgrade to the patched release. In the fix, classification no longer consults the address's own prefix: a new
isHostInSubnet()compares the address's host bits against the reference range only, and every classifier (isLoopback,isPrivate,isLinkLocal,isCGNAT,isMulticast,isUnspecified,isBroadcast,isULA,isMapped4,isTeredo,is6to4,isDocumentation,getType, and the IPv4-mapped/NAT64 normalization behindembeddedIPv4) uses it.isInSubnetkeeps its subnet-containment semantics unchanged, including the guard that a wider network is not contained in a narrower one. After upgrading,new Address4('127.0.0.1/0').isLoopback()returnstrue.If you cannot upgrade immediately, strip the suffix before classifying by re-parsing
addressMinusSuffix:A note on SSRF defense
These methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the resolved IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.
Credit
Reported by @hi-im-glitchless.
Severity
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
ip-address: Address4 decodes leading-zero octets as decimal while resolvers decode them as octal, allowing SSRF and trust-boundary bypass
CVE-2026-69192 / GHSA-mwp4-54f8-5fhr
More information
Details
Summary
Address4accepts an octet written with a leading zero and decodes it as decimal, while the WHATWG URL host parser,inet_aton, andgetaddrinfoall decode a leading zero as octal. The library and the network stack therefore disagree about which host a string names.new Address4('012.0.0.1')reportscorrectForm()of12.0.0.1andisPrivate()offalse, butfetch('http://012.0.0.1/')connects to10.0.0.1.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
Address4.parsegates untrusted input onRE_ADDRESS(src/v4/constants.ts:5), whose per-octet alternative is:The
[01]?[0-9][0-9]?branch matches a leading zero, so012passes validation. Every downstream decode then reads the octet withparseInt(part, 10)(src/common.ts:87), yielding 12. A resolver reading the same string treats the leading0as base 8 and yields 10.The defect is in the parse gate rather than in any one classifier, so every consumer of
Address4inherits it:isPrivate(),isLoopback(),isLinkLocal(),isCGNAT(),isInSubnet(),isHostInSubnet(), andcorrectForm()are all computed from the mis-decoded octets.Address6already rejects this notation on its IPv4-in-IPv6 path, throwing "IPv4 addresses can't have leading zeroes." (src/ipv6.ts:751-762), soAddress4is the outlier within the library.Affected versions
<= 10.3.0. Unlike GHSA-22jq-vg5j-6vgg and GHSA-4xrf-jv44-h6hh, which were bounded below by theis*classification API introduced in 10.1.1, this defect is inparseand reaches every release: a guard built onisInSubnet()against the RFC 1918 ranges is affected in versions predating that API.Impact
The disagreement runs in both directions. Under-blocking is the security-relevant case; over-blocking is a correctness and availability problem.
correctForm()012.0.0.112.0.0.110.0.0.1012.012.012.01212.12.12.1210.10.10.10010.0.0.110.0.0.18.0.0.1Reachable targets are those whose leading octet is expressible as a three-character octal literal, which covers the whole of
10.0.0.0/8and0.0.0.0/8. A four-character octet such as0177for 127 is rejected by the regex, so loopback is not reachable through this path; see the note on rejection below for why rejection is not the same as safety.Reachability
A leading-zero address is a legal URL host, so this is reachable through the ordinary URL path with no unusual application shape required:
This distinguishes it from GHSA-4xrf-jv44-h6hh, where the
/0CIDR suffix could not survive URL parsing and exploitation therefore required an application that accepted a bare suffix-bearing string. Here the attack rides the same code path a normal user-supplied URL takes.Proof of concept
npm i ip-address@10.3.0, then:On affected versions:
The literal RFC 1918 address is blocked as expected; the octal-ambiguous spellings of the same destinations are allowed through.
Remediation
Upgrade to the patched release. In the fix,
Address4.parserejects any octet with a leading zero followed by further digits, mirroring the checkAddress6already applies atsrc/ipv6.ts:751, andRE_ADDRESSis tightened so those forms no longer appear in the valid corpus. After upgrading,Address4.isValid('012.0.0.1')returnsfalseand the constructor throwsAddressError.This rejects input that previous releases accepted. An application that deliberately feeds zero-padded addresses such as
010.010.010.010from a legacy system must strip the padding before parsing.If you cannot upgrade immediately, reject any host whose octets carry a leading zero before you parse it:
A note on SSRF defense
These methods are address classifiers, not a complete SSRF defense. Regardless of this fix, a robust SSRF guard must resolve the hostname and validate the resolved IP against the socket it connects to, and account for DNS rebinding and redirects. Treat these checks as one layer, not the only one.
One specific pitfall is worth naming, because the fix above does not remove it.
Address4.isValid()returningfalsemeans "this is not a dotted-quad IPv4 literal"; it does not mean "this is not an address that will reach an internal host". Every one of the following is rejected byisValid()and still resolves to loopback:A guard shaped
if (Address4.isValid(h)) { check() } else { treatAsHostname() }therefore routes all of them past the IP check. Rejecting these is correct behavior for an IPv4 parser and is not changed by this advisory, but a guard must treat "not a valid literal" as a case to resolve and re-check, never as a case to allow.Severity
CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:N/VC:L/VI:N/VA:N/SC:H/SI:N/SA:NReferences
This data is provided by the GitHub Advisory Database (CC-BY 4.0).
Release Notes
beaugunderson/ip-address (ip-address)
v10.3.1Compare Source
Full Changelog: beaugunderson/ip-address@v10.3.0...v10.3.1
v10.3.0Compare Source
Full Changelog: beaugunderson/ip-address@v10.2.2...v10.3.0
v10.2.2Compare Source
Full Changelog: beaugunderson/ip-address@v10.2.1...v10.2.2
v10.2.1Compare Source
Full Changelog: beaugunderson/ip-address@v10.2.0...v10.2.1
v10.2.0Compare Source
Configuration
📅 Schedule: (in timezone UTC)
🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.
♻ Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.
🔕 Ignore: Close this PR and you won't be reminded about this update again.
This PR was generated by Mend Renovate. View the repository job log.