Fix contains() throwing on cross-family addresses (#62) - #63
Open
youdie006 wants to merge 1 commit into
Open
Conversation
Netmask.contains() is a boolean predicate but threw a low-level parser error when
the argument is a validly-formatted address of the other family than the range
(e.g. new Netmask('0.0.0.0/8').contains('::ffff:127.0.0.1') -> 'empty octet', and
the reverse). A predicate that throws on a valid other-family address crashes
callers using contains() in allowlist/SSRF guards, where the expected answer is
false. The unified contains() delegated a plain IP string straight to
this._impl.contains(), and the impl parser throws on an other-family address.
Detect the argument's family with a plain string ':' check (the same signal the
constructor uses) and short-circuit to false on family mismatch, avoiding the
security-sensitive parsing internals entirely.
Fixes rs#62
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.
Fixes #62.
Problem
Netmask.contains()is a boolean predicate, but it throws a low-level parser error when the argument is a validly-formatted address of the other family than the range:A predicate that throws on a valid other-family address crashes callers that use
contains()in allowlist / SSRF guards, where the expected answer is simplyfalse. Both throws are reported in #62 (v4 range + v6 address, and the reverse).Root cause
The unified
contains()delegates a plain IP string straight tothis._impl.contains(...). When the range and the address are different families, the impl's parser (ip2long/parseNumfor v4,parseIPv6Purefor v6) throws instead of returning a boolean.Fix
Before delegating, detect the argument's family with a plain string
':'check -- the same signal the constructor already uses to pick the impl -- and short-circuit toreturn falsewhen it differs from the range's family. This deliberately avoids the security-sensitive parsing internals (this library has parsing CVEs); it is a pure string check, no address parsing on the reject path. Returningfalsematches the reporter's stated expectation.Note: normalizing IPv4-mapped IPv6 addresses (
::ffff:x) to their IPv4 form is out of scope here; for the issue's own example it would still befalse, since0.0.0.0/8does not cover127.0.0.1.Tests
Added
tests/contains-cross-family.ts. Red/green verified: with the fix reverted the two cross-family cases throw the exact errors from the issue; with the fix all pass. Same-family containment (v4-in-v4, v6-in-v6) is asserted to still work. Full suite 182 passing,tsc --noEmitclean.AI-assisted: this change was prepared with Claude Code (red/green tested).