From 2043d7ee29a4b10a0fc294db9520973fc550e913 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 07:32:53 +0000 Subject: bump dependencies --- src/assets/js/bundle.js | 58 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 8 deletions(-) (limited to 'src/assets/js/bundle.js') diff --git a/src/assets/js/bundle.js b/src/assets/js/bundle.js index 8327238..5764765 100644 --- a/src/assets/js/bundle.js +++ b/src/assets/js/bundle.js @@ -52,8 +52,20 @@ function isInSubnet(address) { * {@link isInSubnet} when classifying a single address — notably when the * address came from untrusted input and the result backs a trust-boundary * decision such as an SSRF allow/deny filter. + * + * An address of one family is never inside a network of the other, so an + * `Address4` against an `Address6` (or the reverse) is `false`. To compare + * across families, convert first: `Address6.fromAddress4()`, `to4()`, or + * `toAddress4Nat64()`. */ function isHostInSubnet(address) { + // mask() is a bit string of the family's width, and the leading bits of a + // 32-bit string can coincide with those of a 128-bit one (a00::1 and + // 10.0.0.0/8 both mask to 00001010), so the widths must agree before the + // strings are compared. + if (this.binaryZeroPad().length !== address.binaryZeroPad().length) { + return false; + } return this.mask(address.subnetMask) === address.mask(); } /** @@ -205,7 +217,9 @@ class Address4 { */ this.isCorrect = isCorrect4; /** - * Returns true if the given address is in the subnet of the current address + * Returns true if the given address is in the subnet of the current address. + * An `Address6` is never in the subnet of an `Address4`; convert with + * `to4()` or `Address6.fromAddress4()` to compare across families. * @returns {boolean} */ this.isInSubnet = common.isInSubnet; @@ -215,6 +229,8 @@ class Address4 { * when classifying a single address, so the answer doesn't change with the * CIDR suffix the caller happened to write — notably when the address came * from untrusted input and the result backs a trust-boundary decision. + * An `Address6` is never in the subnet of an `Address4`; convert with + * `to4()` or `Address6.fromAddress4()` to compare across families. * @returns {boolean} */ this.isHostInSubnet = common.isHostInSubnet; @@ -229,6 +245,13 @@ class Address4 { } address = address.replace(constants.RE_SUBNET_STRING, ''); } + // Four three-digit octets and three dots: the longest well-formed address + // is 15 characters. Longer input is rejected before parsing, as Address6 + // does at its own limit. + const longest = constants.GROUPS * 4 - 1; + if (address.length > longest) { + throw new address_error_1.AddressError(`IPv4 addresses are at most ${longest} characters.`); + } this.addressMinusSuffix = address; this.parsedAddress = this.parse(address); } @@ -370,16 +393,20 @@ class Address4 { return Address4.fromHex(integer.toString(16).padStart(8, '0')); } /** - * Return an address from in-addr.arpa form + * Return an address from in-addr.arpa form: the four octets reversed, with + * or without the `.in-addr.arpa` suffix and root dot, in any case. Throws + * `AddressError` unless the reversed labels form a valid IPv4 address, so + * `fromArpa(x.reverseForm())` round-trips {@link reverseForm}. * @param {string} arpaFormAddress - an 'in-addr.arpa' form ipv4 address * @returns {Adress4} * @example - * var address = Address4.fromArpa(42.2.0.192.in-addr.arpa.) + * var address = Address4.fromArpa('42.2.0.192.in-addr.arpa.') * address.correctForm(); // '192.0.2.42' */ static fromArpa(arpaFormAddress) { - // remove ending ".in-addr.arpa." or just "." - const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.$/, ''); + // remove an ending ".in-addr.arpa", in any case and with or without the + // root dot, as Address6.fromArpa does for ".ip6.arpa" + const leader = arpaFormAddress.replace(/(\.in-addr\.arpa)?\.?$/i, ''); const address = leader.split('.').reverse().join('.'); return new Address4(address); } @@ -830,7 +857,9 @@ class Address6 { this.zone = ''; // #region Attributes /** - * Returns true if the given address is in the subnet of the current address + * Returns true if the given address is in the subnet of the current address. + * An `Address4` is never in the subnet of an `Address6`; convert with + * `Address6.fromAddress4()` or `to4()` to compare across families. * @returns {boolean} */ this.isInSubnet = common.isInSubnet; @@ -840,6 +869,8 @@ class Address6 { * when classifying a single address, so the answer doesn't change with the * CIDR suffix the caller happened to write — notably when the address came * from untrusted input and the result backs a trust-boundary decision. + * An `Address4` is never in the subnet of an `Address6`; convert with + * `Address6.fromAddress4()` or `to4()` to compare across families. * @returns {boolean} */ this.isHostInSubnet = common.isHostInSubnet; @@ -878,6 +909,16 @@ class Address6 { this.zone = zone[0]; address = address.replace(constants6.RE_ZONE_STRING, ''); } + // The longest well-formed address is all but the last two groups written + // as four hex digits with their colons, then a 15-character dotted quad: + // 5 * (groups - 2) + 15, which is 45 for eight groups, the same line + // CPython's ipaddress module draws. Rejecting longer input here keeps the + // parse diagnostics, which wrap every offending character in a span, + // proportional to an address rather than to whatever was passed in. + const longest = this.groups * 5 + 5; + if (address.length > longest) { + throw new address_error_1.AddressError(`IPv6 addresses are at most ${longest} characters.`); + } this.addressMinusSuffix = address; this.parsedAddress = this.parse(this.addressMinusSuffix); } @@ -1089,8 +1130,9 @@ class Address6 { * Address6.fromArpa('8.b.d.0.1.0.0.2.ip6.arpa.').networkForm(); // '2001:db8::/32' */ static fromArpa(arpaFormAddress) { - // remove an ending ".ip6.arpa", with or without the root dot - const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)?\.?$/, ''); + // remove an ending ".ip6.arpa", in any case and with or without the root + // dot + const nibbles = arpaFormAddress.replace(/(\.ip6\.arpa)?\.?$/i, ''); if (!/^[0-9a-f](\.[0-9a-f]){0,31}$/i.test(nibbles)) { throw new address_error_1.AddressError("Invalid 'ip6.arpa' form."); } -- cgit v1.3