{"version":3,"sources":["../../src/helpers/ip/ranges.ts","../../src/helpers/ip/utils.ts","../../src/helpers/ip/ipv4.ts","../../src/helpers/ip/ipv6.ts","../../src/helpers/ip/index.ts","../../src/helpers/urls.ts"],"sourcesContent":["export default {\n    /** localhost IP ranges */\n    localhost: {\n        /** the localhost address ranges for IPv4 */\n        ipv4: ['127.0.0.0/8'],\n\n        /** the localhost address ranges for IPv6 */\n        ipv6: ['::1/128'],\n    },\n\n    /** private IP ranges */\n    private: {\n        /** private address ranges for IPv4 */\n        ipv4: [\n            '10.0.0.0/8', // RFC 1918\n            '172.16.0.0/12', // RFC 1918\n            '192.168.0.0/16', // RFC 1918\n        ],\n\n        /** private address ranges for IPv6 */\n        ipv6: [\n            'fe80::/10', // link-local address\n            'fc00::/7', // unique local address (ULA)\n        ],\n    },\n\n    /** reserved IP ranges */\n    reserved: {\n        /** reserved address ranges for IPv4 */\n        ipv4: [\n            '0.0.0.0/8', // broadcast \"this\"\n            '100.64.0.0/10', // carrier-grade NAT\n            '169.254.0.0/16', // DHCP fallback\n            '192.0.0.0/24', // IANA Special Purpose Address Registry\n            '192.0.2.0/24', // TEST-NET-1 for documentation examples\n            '192.88.99.0/24', // deprecated 6to4 anycast relays\n            '198.18.0.0/15', // for testing inter-network comms between two subnets\n            '198.51.100.0/24', // TEST-NET-2 for documentation examples\n            '203.0.113.0/24', // TEST-NET-3 for documentation examples\n            '224.0.0.0/4', // multicast\n            '240.0.0.0/4', // reserved unspecified\n            '255.255.255.255/32', // limited broadcast address\n        ],\n\n        /** reserved address ranges for IPv6 */\n        ipv6: [\n            '::/128', // unspecified address\n            '64:ff9b::/96', // IPv4/IPv6 translation\n            '100::/64', // discard prefix\n            '2001::/32', // Teredo tunneling\n            '2001:10::/28', // deprecated\n            '2001:20::/28', // ORCHIDv2\n            '2001:db8::/32', // for documentation and examples\n            '2002::/16', // 6to4\n            'ff00::/8', // multicast\n        ],\n    },\n}","// RegExp for testing if a string represents an IPv4 address\nconst v4Seg = '(?:[0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'\nconst v4Str = `(${v4Seg}[.]){3}${v4Seg}`\nconst IPv4Reg = new RegExp(`^${v4Str}$`)\n\n// RegExp for testing if a string represents an IPv6 address\nconst v6Seg = '(?:[0-9a-fA-F]{1,4})'\nconst IPv6Reg = new RegExp(\n    '^(' +\n    `(?:${v6Seg}:){7}(?:${v6Seg}|:)|` +\n    `(?:${v6Seg}:){6}(?:${v4Str}|:${v6Seg}|:)|` +\n    `(?:${v6Seg}:){5}(?::${v4Str}|(:${v6Seg}){1,2}|:)|` +\n    `(?:${v6Seg}:){4}(?:(:${v6Seg}){0,1}:${v4Str}|(:${v6Seg}){1,3}|:)|` +\n    `(?:${v6Seg}:){3}(?:(:${v6Seg}){0,2}:${v4Str}|(:${v6Seg}){1,4}|:)|` +\n    `(?:${v6Seg}:){2}(?:(:${v6Seg}){0,3}:${v4Str}|(:${v6Seg}){1,5}|:)|` +\n    `(?:${v6Seg}:){1}(?:(:${v6Seg}){0,4}:${v4Str}|(:${v6Seg}){1,6}|:)|` +\n    `(?::((?::${v6Seg}){0,5}:${v4Str}|(?::${v6Seg}){1,7}|:))` +\n    ')(%[0-9a-zA-Z]{1,})?$'\n)\n\n/**\n * Returns true if the string represents an IPv4 address. Matches Node.js net.isIPv4\n * functionality.\n */\nexport function isIPv4 (s: string) {\n    return IPv4Reg.test(s)\n}\n\n/**\n * Returns true if the string represents an IPv6 address. Matches Node.js net.isIPv6\n * functionality.\n */\nexport function isIPv6 (s: string) {\n    return IPv6Reg.test(s)\n}\n\nexport function isIP (s: string) {\n    if (isIPv4(s)) return 4\n    if (isIPv6(s)) return 6\n    return 0\n}\n","import ipRanges from './ranges'\nimport * as util from './utils'\n\n/**\n * Given an IPv4 address, convert it to a 32-bit long integer.\n * @param ip the IPv4 address to expand\n * @throws if the string is not a valid IPv4 address\n */\nfunction ipv4ToLong (ip: string) {\n    if (!util.isIPv4(ip)) {\n        throw new Error(`not a valid IPv4 address: ${ip}`)\n    }\n    const octets = ip.split('.')\n    return (\n        ((parseInt(octets[0], 10) << 24) +\n            (parseInt(octets[1], 10) << 16) +\n            (parseInt(octets[2], 10) << 8) +\n            parseInt(octets[3], 10)) >>>\n        0\n    )\n}\n\n// this is the most optimised checker.\nfunction createLongChecker (subnet: string): (addressLong: number) => boolean {\n    const [subnetAddress, prefixLengthString] = subnet.split('/')\n    const prefixLength = parseInt(prefixLengthString, 10)\n    if (!subnetAddress || !Number.isInteger(prefixLength)) {\n        throw new Error(`not a valid IPv4 subnet: ${subnet}`)\n    }\n\n    if (prefixLength < 0 || prefixLength > 32) {\n        throw new Error(`not a valid IPv4 prefix length: ${prefixLength} (from ${subnet})`)\n    }\n\n    const subnetLong = ipv4ToLong(subnetAddress)\n    return addressLong => {\n        if (prefixLength === 0) {\n            return true\n        }\n        const subnetPrefix = subnetLong >> (32 - prefixLength)\n        const addressPrefix = addressLong >> (32 - prefixLength)\n\n        return subnetPrefix === addressPrefix\n    }\n}\n\n/**\n * The functional version, creates a checking function that takes an IPv4 Address and\n * returns whether or not it is contained in (one of) the subnet(s).\n * @param subnetOrSubnets the IPv4 CIDR to test (or an array of them)\n * @throws if the subnet is not a valid IP addresses, or the CIDR prefix length\n *  is not valid\n */\nexport function createChecker (\n    subnetOrSubnets: string | string[]\n): (address: string) => boolean {\n    if (Array.isArray(subnetOrSubnets)) {\n        const checks = subnetOrSubnets.map(subnet => createLongChecker(subnet))\n        return address => {\n            const addressLong = ipv4ToLong(address)\n            return checks.some(check => check(addressLong))\n        }\n    }\n    const check = createLongChecker(subnetOrSubnets)\n    return address => {\n        const addressLong = ipv4ToLong(address)\n        return check(addressLong)\n    }\n}\n\n/**\n * Test if the given IPv4 address is contained in the specified subnet.\n * @param address the IPv4 address to check\n * @param subnetOrSubnets the IPv4 CIDR to test (or an array of them)\n * @throws if the address or subnet are not valid IP addresses, or the CIDR prefix length\n *  is not valid\n */\nexport function isInSubnet (address: string, subnetOrSubnets: string | string[]): boolean {\n    return createChecker(subnetOrSubnets)(address)\n}\n\n// cache these special subnet checkers\nconst specialNetsCache: Record<string, (address: string) => boolean> = {}\n\n/** Test if the given IP address is a private/internal IP address. */\nexport function isPrivate (address: string) {\n    if (!('private' in specialNetsCache)) {\n        specialNetsCache['private'] = createChecker(ipRanges.private.ipv4)\n    }\n    return specialNetsCache['private'](address)\n}\n\n/** Test if the given IP address is a localhost address. */\nexport function isLocalhost (address: string) {\n    if (!('localhost' in specialNetsCache)) {\n        specialNetsCache['localhost'] = createChecker(ipRanges.localhost.ipv4)\n    }\n    return specialNetsCache['localhost'](address)\n}\n\n/** Test if the given IP address is in a known reserved range and not a normal host IP */\nexport function isReserved (address: string) {\n    if (!('reserved' in specialNetsCache)) {\n        specialNetsCache['reserved'] = createChecker(ipRanges.reserved.ipv4)\n    }\n    return specialNetsCache['reserved'](address)\n}\n\n/**\n * Test if the given IP address is a special address of any kind (private, reserved,\n * localhost)\n */\nexport function isSpecial (address: string) {\n    if (!('special' in specialNetsCache)) {\n        specialNetsCache['special'] = createChecker([\n            ...ipRanges.private.ipv4,\n            ...ipRanges.localhost.ipv4,\n            ...ipRanges.reserved.ipv4,\n        ])\n    }\n    return specialNetsCache['special'](address)\n}","import ipRanges from './ranges'\nimport * as util from './utils'\n\n// Note: Profiling shows that on recent versions of Node, string.split(RegExp) is faster\n// than string.split(string).\nconst dot = /\\./\nconst mappedIpv4 = /^(.+:ffff:)(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})(?:%.+)?$/\nconst colon = /:/\nconst doubleColon = /::/\n\n/**\n * Given a mapped IPv4 address (e.g. ::ffff:203.0.113.38 or similar), convert it to the\n * equivalent standard IPv6 address.\n * @param ip the IPv4-to-IPv6 mapped address\n */\nfunction mappedIpv4ToIpv6 (ip: string) {\n    const matches = ip.match(mappedIpv4)\n\n    if (!matches || !util.isIPv4(matches[2])) {\n        throw new Error(`not a mapped IPv4 address: ${ip}`)\n    }\n\n    // mapped IPv4 address\n    const prefix = matches[1]\n    const ipv4 = matches[2]\n\n    const parts = ipv4.split(dot).map(x => parseInt(x, 10))\n\n    const segment7 = ((parts[0] << 8) + parts[1]).toString(16)\n    const segment8 = ((parts[2] << 8) + parts[3]).toString(16)\n\n    return `${prefix}${segment7}:${segment8}`\n}\n\n/**\n * Given a mapped IPv4 address, return the bare IPv4 equivalent.\n */\nexport function extractMappedIpv4 (ip: string) {\n    const matches = ip.match(mappedIpv4)\n\n    if (!matches || !util.isIPv4(matches[2])) {\n        throw new Error(`not a mapped IPv4 address: ${ip}`)\n    }\n\n    return matches[2]\n}\n\n/**\n * Given an IP address that may have double-colons, expand all segments and return them\n * as an array of 8 segments (16-bit words). As a peformance enhancement (indicated by\n * profiling), for any segment that was missing but should be a '0', returns undefined.\n * @param ip the IPv6 address to expand\n * @throws if the string is not a valid IPv6 address\n */\nfunction getIpv6Segments (ip: string): string[] {\n    if (!util.isIPv6(ip)) {\n        throw new Error(`not a valid IPv6 address: ${ip}`)\n    }\n\n    if (dot.test(ip)) {\n        return getIpv6Segments(mappedIpv4ToIpv6(ip))\n    }\n\n    // break it into an array, including missing \"::\" segments\n    const [beforeChunk, afterChunk] = ip.split(doubleColon)\n\n    const beforeParts = (beforeChunk && beforeChunk.split(colon)) || []\n    const afterParts = (afterChunk && afterChunk.split(colon)) || []\n    const missingSegments = new Array<string>(8 - (beforeParts.length + afterParts.length))\n\n    return beforeParts.concat(missingSegments, afterParts)\n}\n\n/**\n * Test if the given IPv6 address is contained in the specified subnet.\n * @param address the IPv6 address to check\n * @param subnetOrSubnets the IPv6 CIDR to test (or an array of them)\n * @throws if the address or subnet are not valid IP addresses, or the CIDR prefix length\n *  is not valid\n */\nexport function isInSubnet (address: string, subnetOrSubnets: string | string[]): boolean {\n    return createChecker(subnetOrSubnets)(address)\n}\n\n/**\n * Create a function to test if a given IPv6 address is contained in the specified subnet.\n * @param subnetOrSubnets the IPv6 CIDR to test (or an array of them)\n * @throws if the subnet(s) are not valid IP addresses, or the CIDR prefix lengths\n *  are not valid\n */\nexport function createChecker (\n    subnetOrSubnets: string | string[]\n): (address: string) => boolean {\n    if (Array.isArray(subnetOrSubnets)) {\n        const checks = subnetOrSubnets.map(subnet => createSegmentChecker(subnet))\n        return address => {\n            const segments = getIpv6Segments(address)\n            return checks.some(check => check(segments))\n        }\n    }\n    const check = createSegmentChecker(subnetOrSubnets)\n    return address => {\n        const segments = getIpv6Segments(address)\n        return check(segments)\n    }\n}\n\n// This creates the last function that works on the most deconstructed data\nfunction createSegmentChecker (subnet: string): (segments: string[]) => boolean {\n    const [subnetAddress, prefixLengthString] = subnet.split('/')\n    const prefixLength = parseInt(prefixLengthString, 10)\n\n    if (!subnetAddress || !Number.isInteger(prefixLength)) {\n        throw new Error(`not a valid IPv6 CIDR subnet: ${subnet}`)\n    }\n\n    if (prefixLength < 0 || prefixLength > 128) {\n        throw new Error(`not a valid IPv6 prefix length: ${prefixLength} (from ${subnet})`)\n    }\n\n    // the next line throws if the address is not a valid IPv6 address\n    const subnetSegments = getIpv6Segments(subnetAddress)\n\n    return addressSegments => {\n        for (let i = 0; i < 8; ++i) {\n            const bitCount = Math.min(prefixLength - i * 16, 16)\n\n            if (bitCount <= 0) {\n                break\n            }\n\n            const subnetPrefix =\n                ((subnetSegments[i] && parseInt(subnetSegments[i], 16)) || 0) >> (16 - bitCount)\n\n            const addressPrefix =\n                ((addressSegments[i] && parseInt(addressSegments[i], 16)) || 0) >>\n                (16 - bitCount)\n\n            if (subnetPrefix !== addressPrefix) {\n                return false\n            }\n        }\n\n        return true\n    }\n}\n\n// cache these special subnet checkers\nconst specialNetsCache: Record<string, (address: string) => boolean> = {}\n\n/** Test if the given IP address is a private/internal IP address. */\nexport function isPrivate (address: string) {\n    if (!('private' in specialNetsCache)) {\n        specialNetsCache['private'] = createChecker(ipRanges.private.ipv6)\n    }\n    return specialNetsCache['private'](address)\n}\n\n/** Test if the given IP address is a localhost address. */\nexport function isLocalhost (address: string) {\n    if (!('localhost' in specialNetsCache)) {\n        specialNetsCache['localhost'] = createChecker(ipRanges.localhost.ipv6)\n    }\n    return specialNetsCache['localhost'](address)\n}\n\n/** Test if the given IP address is an IPv4 address mapped onto IPv6 */\nexport function isIPv4MappedAddress (address: string) {\n    if (!('mapped' in specialNetsCache)) {\n        specialNetsCache['mapped'] = createChecker('::ffff:0:0/96')\n    }\n    if (specialNetsCache['mapped'](address)) {\n        const matches = address.match(mappedIpv4)\n        return Boolean(matches && util.isIPv4(matches[2]))\n    }\n    return false\n}\n\n/** Test if the given IP address is in a known reserved range and not a normal host IP */\nexport function isReserved (address: string) {\n    if (!('reserved' in specialNetsCache)) {\n        specialNetsCache['reserved'] = createChecker(ipRanges.reserved.ipv6)\n    }\n    return specialNetsCache['reserved'](address)\n}\n\n/**\n * Test if the given IP address is a special address of any kind (private, reserved,\n * localhost)\n */\nexport function isSpecial (address: string) {\n    if (!('special' in specialNetsCache)) {\n        specialNetsCache['special'] = createChecker([\n            ...ipRanges.private.ipv6,\n            ...ipRanges.localhost.ipv6,\n            ...ipRanges.reserved.ipv6,\n        ])\n    }\n    return specialNetsCache['special'](address)\n}","import * as IPv4 from './ipv4'\nimport * as IPv6 from './ipv6'\nimport * as util from './utils'\n\nexport { isIP, isIPv4, isIPv6 } from './utils'\nexport { IPv4, IPv6 }\n\n/**\n * Test if the given IP address is contained in the specified subnet.\n * @param address the IPv4 or IPv6 address to check\n * @param subnetOrSubnets the IPv4 or IPv6 CIDR to test (or an array of them)\n * @throws if any of the address or subnet(s) are not valid IP addresses, or the CIDR\n *  prefix length is not valid\n */\nexport function isInSubnet (address: string, subnetOrSubnets: string | string[]): boolean {\n    return createChecker(subnetOrSubnets)(address)\n}\n/**\n * Create a function to test if the given IP address is contained in the specified subnet.\n * @param subnetOrSubnets the IPv4 or IPv6 CIDR to test (or an array of them)\n * @throws if any of the subnet(s) are not valid IP addresses, or the CIDR\n *  prefix length is not valid\n */\nexport function createChecker (\n    subnetOrSubnets: string | string[]\n): (address: string) => boolean {\n    if (!Array.isArray(subnetOrSubnets)) {\n        return createChecker([subnetOrSubnets])\n    }\n\n    const subnetsByVersion = subnetOrSubnets.reduce(\n        (acc, subnet) => {\n            const ip = subnet.split('/')[0];\n            (acc[util.isIP(ip)] as string[]).push(subnet)\n            return acc\n        },\n        { 0: [], 4: [], 6: [] }\n    )\n\n    if (subnetsByVersion[0].length !== 0) {\n        throw new Error(`some subnets are not valid IP addresses: ${subnetsByVersion[0]}`)\n    }\n\n    const check4 = IPv4.createChecker(subnetsByVersion[4])\n    const check6 = IPv6.createChecker(subnetsByVersion[6])\n\n    return address => {\n        if (!util.isIP(address)) {\n            throw new Error(`not a valid IPv4 or IPv6 address: ${address}`)\n        }\n\n        // for mapped IPv4 addresses, compare against both IPv6 and IPv4 subnets\n        if (util.isIPv6(address) && IPv6.isIPv4MappedAddress(address)) {\n            return check6(address) || check4(IPv6.extractMappedIpv4(address))\n        }\n\n        if (util.isIPv6(address)) {\n            return check6(address)\n        } else {\n            return check4(address)\n        }\n    }\n}\n\n/** Test if the given IP address is a private/internal IP address. */\nexport function isPrivate (address: string) {\n    if (util.isIPv6(address)) {\n        if (IPv6.isIPv4MappedAddress(address)) {\n            return IPv4.isPrivate(IPv6.extractMappedIpv4(address))\n        }\n        return IPv6.isPrivate(address)\n    } else {\n        return IPv4.isPrivate(address)\n    }\n}\n\n/** Test if the given IP address is a localhost address. */\nexport function isLocalhost (address: string) {\n    if (util.isIPv6(address)) {\n        if (IPv6.isIPv4MappedAddress(address)) {\n            return IPv4.isLocalhost(IPv6.extractMappedIpv4(address))\n        }\n        return IPv6.isLocalhost(address)\n    } else {\n        return IPv4.isLocalhost(address)\n    }\n}\n\n/** Test if the given IP address is an IPv4 address mapped onto IPv6 */\nexport function isIPv4MappedAddress (address: string) {\n    if (util.isIPv6(address)) {\n        return IPv6.isIPv4MappedAddress(address)\n    } else {\n        return false\n    }\n}\n\n/** Test if the given IP address is in a known reserved range and not a normal host IP */\nexport function isReserved (address: string) {\n    if (util.isIPv6(address)) {\n        if (IPv6.isIPv4MappedAddress(address)) {\n            return IPv4.isReserved(IPv6.extractMappedIpv4(address))\n        }\n        return IPv6.isReserved(address)\n    } else {\n        return IPv4.isReserved(address)\n    }\n}\n\n/**\n * Test if the given IP address is a special address of any kind (private, reserved,\n * localhost)\n */\nexport function isSpecial (address: string) {\n    if (util.isIPv6(address)) {\n        if (IPv6.isIPv4MappedAddress(address)) {\n            return IPv4.isSpecial(IPv6.extractMappedIpv4(address))\n        }\n        return IPv6.isSpecial(address)\n    } else {\n        return IPv4.isSpecial(address)\n    }\n}\n\nexport const check = isInSubnet","const REGEXP_ESCAPE_CHARS = /[\\\\^$.*+?()[\\]{}|]/g\nconst WILDCARD_REGEXP_PART = '([a-zA-Z0-9-]{1,63})'\nconst WILDCARD_REGEXP_PART_ESCAPED = _escapeRegexp(WILDCARD_REGEXP_PART)\n\ntype URLCache = Map<string, URL>\ntype RegExpCache = Map<string, RegExp>\n\nimport { isIP, isLocalhost, isSpecial } from './ip'\n\nexport function isSafeUrl (url: unknown): boolean {\n    if (!url || typeof url !== 'string') return false\n    \n    let decodedUrl: string\n    try {\n        decodedUrl = decodeURI(url)\n    } catch (error) {\n        // If decodeURI fails, treat as unsafe\n        return false\n    }\n\n    // ReDoS-safe approach: normalize the string first, then use simple regex\n    // Remove all control characters and whitespace, then check for javascript:\n    const normalizedUrl = decodedUrl\n        // eslint-disable-next-line no-control-regex\n        .replace(/[\\u0000-\\u001F\\s]/g, '') // Remove control chars and whitespace\n        .toLowerCase()\n    \n    return !normalizedUrl.includes('javascript:')\n}\n\nexport function replaceDomainPrefix (originalUrl: string, prefix: string): string {\n    const url = new URL(originalUrl)\n\n    const originalHostnameParts = url.hostname.split('.')\n    const suffixParts = originalHostnameParts.length > 2 ? originalHostnameParts.slice(1) : originalHostnameParts\n    const suffix = suffixParts.join('.')\n\n    url.hostname = `${prefix}.${suffix}`\n\n    return url.toString()\n}\n\nfunction _escapeRegexp (source: string) {\n    return source.replace(REGEXP_ESCAPE_CHARS, '\\\\$&')\n}\n\nexport type ReplaceDomainOptions = { encoded?: boolean, urlsCache?: URLCache, regexpsCache?: RegExpCache }\n\nfunction _getUrl (strUrl: string, cache?: URLCache): URL {\n    if (!cache) return new URL(strUrl)\n\n    let parsed = cache.get(strUrl)\n    if (!parsed) {\n        parsed = new URL(strUrl)\n        cache.set(strUrl, parsed)\n    }\n    return parsed\n}\n\n/** NOTE: Don't use it outside of this file, since it mutates lastIndex */\nfunction _getCachedRegexp (pattern: string, cache?: RegExpCache): RegExp {\n    // NOTE: no user input here\n    // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n    if (!cache) return new RegExp(pattern, 'g')\n\n    let re = cache.get(pattern)\n    if (!re) {\n        // NOTE: no user input here\n        // nosemgrep: javascript.lang.security.audit.detect-non-literal-regexp.detect-non-literal-regexp\n        re = new RegExp(pattern, 'g')\n        cache.set(pattern, re)\n    }\n    re.lastIndex = 0\n    return re\n}\n\nexport function getWildcardDomain (domain: string, cache?: URLCache) {\n    const url = _getUrl(domain, cache)\n    const [prefix, ...rest] = url.hostname.split('.')\n    const port = url.port ? `:${url.port}` : ''\n    return {\n        wildcardDomain: `${url.protocol}//*.${rest.join('.')}${port}`,\n        prefix,\n    }\n}\n\nexport function replaceDomain (source: string, from: string, to: string, options: ReplaceDomainOptions = {}): string {\n    const { encoded = false, urlsCache, regexpsCache } = options\n\n    const fromUrl = _getUrl(from, urlsCache)\n    // NOTE: URL parser encodes * as %2A in some browsers (Chromium), so decode the hostname to check for wildcards\n    const decodedHostname = decodeURIComponent(fromUrl.hostname)\n\n    // NOTE: for non-wildcard domain just do simple replace\n    if (!decodedHostname.startsWith('*.')) {\n        // Add negative lookahead to ensure domain boundary\n        // Not followed by: dot+domain chars, or domain chars directly\n        const escapedFrom = _escapeRegexp(from)\n        const fromWithBoundary = `${escapedFrom}(?!\\\\.${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n        const fromSearch = _getCachedRegexp(fromWithBoundary, regexpsCache)\n        let replaced = source.replace(fromSearch, to)\n\n        if (encoded) {\n            const fromEncoded = encodeURIComponent(from)\n            const escapedFromEncoded = _escapeRegexp(fromEncoded)\n            // For encoded: not followed by %2E+domain chars or domain chars directly\n            const fromEncodedWithBoundary = `${escapedFromEncoded}(?!%2E${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n            const fromEncodedSearch = _getCachedRegexp(fromEncodedWithBoundary, regexpsCache)\n            replaced = replaced.replace(fromEncodedSearch, encodeURIComponent(to))\n        }\n\n        return replaced\n    }\n\n    // NOTE: need to apply some magic on wildcards\n    // NOTE: only first * is needed\n    // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n    const fromPattern = from.replace('*', WILDCARD_REGEXP_PART)\n    // NOTE: only first * is needed\n    // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n    const toPattern = to.replace('*', '$1')\n\n    const escapedFrom = _escapeRegexp(fromPattern).replace(WILDCARD_REGEXP_PART_ESCAPED, WILDCARD_REGEXP_PART)\n    // Add negative lookahead to ensure domain boundary\n    const fromWithBoundary = `${escapedFrom}(?!\\\\.${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})`\n    const fromSearch = _getCachedRegexp(fromWithBoundary, regexpsCache)\n\n    let replaced = source.replace(fromSearch, toPattern)\n\n    if (encoded) {\n        // NOTE: only first * is needed\n        // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n        const fromEncoded = encodeURIComponent(from).replace('*', WILDCARD_REGEXP_PART)\n        // NOTE: only first * is needed\n        // nosemgrep: javascript.lang.security.audit.incomplete-sanitization.incomplete-sanitization\n        const toEncoded = encodeURIComponent(to).replace('*', '$1')\n\n        const escapedFromEncoded = _escapeRegexp(fromEncoded).replace(WILDCARD_REGEXP_PART_ESCAPED, WILDCARD_REGEXP_PART)\n        // For encoded: not followed by %2E+domain chars or domain chars directly\n        const fromEncodedWithBoundary = `${escapedFromEncoded}(?!%2E${WILDCARD_REGEXP_PART}|${WILDCARD_REGEXP_PART})` \n        const fromEncodedSearch = _getCachedRegexp(fromEncodedWithBoundary, regexpsCache)\n\n        replaced = replaced.replace(fromEncodedSearch, toEncoded)\n    }\n\n    return replaced\n}\n\ntype URLWithMeta = Readonly<URL> & {\n    isIP: boolean\n    isSpecialIP: boolean\n    isLocalhost: boolean\n}\n\nexport function getUrlMeta (url: string): URLWithMeta | null {\n    try {\n        const u: URLWithMeta = new URL(url) as URLWithMeta\n        const hostnameUnWrapped = (u.hostname.startsWith('[') && u.hostname.endsWith(']'))\n            ? u.hostname.slice(1, -1)\n            : u.hostname\n        u.isIP = isIP(hostnameUnWrapped) > 0\n        u.isSpecialIP = u.isIP && isSpecial(hostnameUnWrapped)\n        u.isLocalhost = u.hostname === 'localhost' || (u.isIP && isLocalhost(hostnameUnWrapped))\n\n        return u\n    } catch {\n        return null\n    }\n}\n"],"mappings":";AAAA,IAAO,iBAAQ;AAAA;AAAA,EAEX,WAAW;AAAA;AAAA,IAEP,MAAM,CAAC,aAAa;AAAA;AAAA,IAGpB,MAAM,CAAC,SAAS;AAAA,EACpB;AAAA;AAAA,EAGA,SAAS;AAAA;AAAA,IAEL,MAAM;AAAA,MACF;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACJ;AAAA;AAAA,IAGA,MAAM;AAAA,MACF;AAAA;AAAA,MACA;AAAA;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA,EAGA,UAAU;AAAA;AAAA,IAEN,MAAM;AAAA,MACF;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACJ;AAAA;AAAA,IAGA,MAAM;AAAA,MACF;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACJ;AAAA,EACJ;AACJ;;;ACxDA,IAAM,QAAQ;AACd,IAAM,QAAQ,IAAI,KAAK,UAAU,KAAK;AACtC,IAAM,UAAU,IAAI,OAAO,IAAI,KAAK,GAAG;AAGvC,IAAM,QAAQ;AACd,IAAM,UAAU,IAAI;AAAA,EAChB,QACM,KAAK,WAAW,KAAK,UACrB,KAAK,WAAW,KAAK,KAAK,KAAK,UAC/B,KAAK,YAAY,KAAK,MAAM,KAAK,gBACjC,KAAK,aAAa,KAAK,UAAU,KAAK,MAAM,KAAK,gBACjD,KAAK,aAAa,KAAK,UAAU,KAAK,MAAM,KAAK,gBACjD,KAAK,aAAa,KAAK,UAAU,KAAK,MAAM,KAAK,gBACjD,KAAK,aAAa,KAAK,UAAU,KAAK,MAAM,KAAK,sBAC3C,KAAK,UAAU,KAAK,QAAQ,KAAK;AAEjD;AAMO,SAAS,OAAQ,GAAW;AAC/B,SAAO,QAAQ,KAAK,CAAC;AACzB;AAMO,SAAS,OAAQ,GAAW;AAC/B,SAAO,QAAQ,KAAK,CAAC;AACzB;AAEO,SAAS,KAAM,GAAW;AAC7B,MAAI,OAAO,CAAC,EAAG,QAAO;AACtB,MAAI,OAAO,CAAC,EAAG,QAAO;AACtB,SAAO;AACX;;;AChCA,SAAS,WAAY,IAAY;AAC7B,MAAI,CAAM,OAAO,EAAE,GAAG;AAClB,UAAM,IAAI,MAAM,6BAA6B,EAAE,EAAE;AAAA,EACrD;AACA,QAAM,SAAS,GAAG,MAAM,GAAG;AAC3B,UACM,SAAS,OAAO,CAAC,GAAG,EAAE,KAAK,OACxB,SAAS,OAAO,CAAC,GAAG,EAAE,KAAK,OAC3B,SAAS,OAAO,CAAC,GAAG,EAAE,KAAK,KAC5B,SAAS,OAAO,CAAC,GAAG,EAAE,MAC1B;AAER;AAGA,SAAS,kBAAmB,QAAkD;AAC1E,QAAM,CAAC,eAAe,kBAAkB,IAAI,OAAO,MAAM,GAAG;AAC5D,QAAM,eAAe,SAAS,oBAAoB,EAAE;AACpD,MAAI,CAAC,iBAAiB,CAAC,OAAO,UAAU,YAAY,GAAG;AACnD,UAAM,IAAI,MAAM,4BAA4B,MAAM,EAAE;AAAA,EACxD;AAEA,MAAI,eAAe,KAAK,eAAe,IAAI;AACvC,UAAM,IAAI,MAAM,mCAAmC,YAAY,UAAU,MAAM,GAAG;AAAA,EACtF;AAEA,QAAM,aAAa,WAAW,aAAa;AAC3C,SAAO,iBAAe;AAClB,QAAI,iBAAiB,GAAG;AACpB,aAAO;AAAA,IACX;AACA,UAAM,eAAe,cAAe,KAAK;AACzC,UAAM,gBAAgB,eAAgB,KAAK;AAE3C,WAAO,iBAAiB;AAAA,EAC5B;AACJ;AASO,SAAS,cACZ,iBAC4B;AAC5B,MAAI,MAAM,QAAQ,eAAe,GAAG;AAChC,UAAM,SAAS,gBAAgB,IAAI,YAAU,kBAAkB,MAAM,CAAC;AACtE,WAAO,aAAW;AACd,YAAM,cAAc,WAAW,OAAO;AACtC,aAAO,OAAO,KAAK,CAAAA,WAASA,OAAM,WAAW,CAAC;AAAA,IAClD;AAAA,EACJ;AACA,QAAM,QAAQ,kBAAkB,eAAe;AAC/C,SAAO,aAAW;AACd,UAAM,cAAc,WAAW,OAAO;AACtC,WAAO,MAAM,WAAW;AAAA,EAC5B;AACJ;AAcA,IAAM,mBAAiE,CAAC;AAWjE,SAAS,YAAa,SAAiB;AAC1C,MAAI,EAAE,eAAe,mBAAmB;AACpC,qBAAiB,WAAW,IAAI,cAAc,eAAS,UAAU,IAAI;AAAA,EACzE;AACA,SAAO,iBAAiB,WAAW,EAAE,OAAO;AAChD;AAcO,SAAS,UAAW,SAAiB;AACxC,MAAI,EAAE,aAAa,mBAAmB;AAClC,qBAAiB,SAAS,IAAI,cAAc;AAAA,MACxC,GAAG,eAAS,QAAQ;AAAA,MACpB,GAAG,eAAS,UAAU;AAAA,MACtB,GAAG,eAAS,SAAS;AAAA,IACzB,CAAC;AAAA,EACL;AACA,SAAO,iBAAiB,SAAS,EAAE,OAAO;AAC9C;;;ACpHA,IAAM,MAAM;AACZ,IAAM,aAAa;AACnB,IAAM,QAAQ;AACd,IAAM,cAAc;AAOpB,SAAS,iBAAkB,IAAY;AACnC,QAAM,UAAU,GAAG,MAAM,UAAU;AAEnC,MAAI,CAAC,WAAW,CAAM,OAAO,QAAQ,CAAC,CAAC,GAAG;AACtC,UAAM,IAAI,MAAM,8BAA8B,EAAE,EAAE;AAAA,EACtD;AAGA,QAAM,SAAS,QAAQ,CAAC;AACxB,QAAM,OAAO,QAAQ,CAAC;AAEtB,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,OAAK,SAAS,GAAG,EAAE,CAAC;AAEtD,QAAM,aAAa,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG,SAAS,EAAE;AACzD,QAAM,aAAa,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,GAAG,SAAS,EAAE;AAEzD,SAAO,GAAG,MAAM,GAAG,QAAQ,IAAI,QAAQ;AAC3C;AAKO,SAAS,kBAAmB,IAAY;AAC3C,QAAM,UAAU,GAAG,MAAM,UAAU;AAEnC,MAAI,CAAC,WAAW,CAAM,OAAO,QAAQ,CAAC,CAAC,GAAG;AACtC,UAAM,IAAI,MAAM,8BAA8B,EAAE,EAAE;AAAA,EACtD;AAEA,SAAO,QAAQ,CAAC;AACpB;AASA,SAAS,gBAAiB,IAAsB;AAC5C,MAAI,CAAM,OAAO,EAAE,GAAG;AAClB,UAAM,IAAI,MAAM,6BAA6B,EAAE,EAAE;AAAA,EACrD;AAEA,MAAI,IAAI,KAAK,EAAE,GAAG;AACd,WAAO,gBAAgB,iBAAiB,EAAE,CAAC;AAAA,EAC/C;AAGA,QAAM,CAAC,aAAa,UAAU,IAAI,GAAG,MAAM,WAAW;AAEtD,QAAM,cAAe,eAAe,YAAY,MAAM,KAAK,KAAM,CAAC;AAClE,QAAM,aAAc,cAAc,WAAW,MAAM,KAAK,KAAM,CAAC;AAC/D,QAAM,kBAAkB,IAAI,MAAc,KAAK,YAAY,SAAS,WAAW,OAAO;AAEtF,SAAO,YAAY,OAAO,iBAAiB,UAAU;AACzD;AAmBO,SAASC,eACZ,iBAC4B;AAC5B,MAAI,MAAM,QAAQ,eAAe,GAAG;AAChC,UAAM,SAAS,gBAAgB,IAAI,YAAU,qBAAqB,MAAM,CAAC;AACzE,WAAO,aAAW;AACd,YAAM,WAAW,gBAAgB,OAAO;AACxC,aAAO,OAAO,KAAK,CAAAC,WAASA,OAAM,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACJ;AACA,QAAM,QAAQ,qBAAqB,eAAe;AAClD,SAAO,aAAW;AACd,UAAM,WAAW,gBAAgB,OAAO;AACxC,WAAO,MAAM,QAAQ;AAAA,EACzB;AACJ;AAGA,SAAS,qBAAsB,QAAiD;AAC5E,QAAM,CAAC,eAAe,kBAAkB,IAAI,OAAO,MAAM,GAAG;AAC5D,QAAM,eAAe,SAAS,oBAAoB,EAAE;AAEpD,MAAI,CAAC,iBAAiB,CAAC,OAAO,UAAU,YAAY,GAAG;AACnD,UAAM,IAAI,MAAM,iCAAiC,MAAM,EAAE;AAAA,EAC7D;AAEA,MAAI,eAAe,KAAK,eAAe,KAAK;AACxC,UAAM,IAAI,MAAM,mCAAmC,YAAY,UAAU,MAAM,GAAG;AAAA,EACtF;AAGA,QAAM,iBAAiB,gBAAgB,aAAa;AAEpD,SAAO,qBAAmB;AACtB,aAAS,IAAI,GAAG,IAAI,GAAG,EAAE,GAAG;AACxB,YAAM,WAAW,KAAK,IAAI,eAAe,IAAI,IAAI,EAAE;AAEnD,UAAI,YAAY,GAAG;AACf;AAAA,MACJ;AAEA,YAAM,gBACA,eAAe,CAAC,KAAK,SAAS,eAAe,CAAC,GAAG,EAAE,KAAM,MAAO,KAAK;AAE3E,YAAM,iBACA,gBAAgB,CAAC,KAAK,SAAS,gBAAgB,CAAC,GAAG,EAAE,KAAM,MAC5D,KAAK;AAEV,UAAI,iBAAiB,eAAe;AAChC,eAAO;AAAA,MACX;AAAA,IACJ;AAEA,WAAO;AAAA,EACX;AACJ;AAGA,IAAMC,oBAAiE,CAAC;AAWjE,SAASC,aAAa,SAAiB;AAC1C,MAAI,EAAE,eAAeC,oBAAmB;AACpC,IAAAA,kBAAiB,WAAW,IAAIC,eAAc,eAAS,UAAU,IAAI;AAAA,EACzE;AACA,SAAOD,kBAAiB,WAAW,EAAE,OAAO;AAChD;AAGO,SAAS,oBAAqB,SAAiB;AAClD,MAAI,EAAE,YAAYA,oBAAmB;AACjC,IAAAA,kBAAiB,QAAQ,IAAIC,eAAc,eAAe;AAAA,EAC9D;AACA,MAAID,kBAAiB,QAAQ,EAAE,OAAO,GAAG;AACrC,UAAM,UAAU,QAAQ,MAAM,UAAU;AACxC,WAAO,QAAQ,WAAgB,OAAO,QAAQ,CAAC,CAAC,CAAC;AAAA,EACrD;AACA,SAAO;AACX;AAcO,SAASE,WAAW,SAAiB;AACxC,MAAI,EAAE,aAAaC,oBAAmB;AAClC,IAAAA,kBAAiB,SAAS,IAAIC,eAAc;AAAA,MACxC,GAAG,eAAS,QAAQ;AAAA,MACpB,GAAG,eAAS,UAAU;AAAA,MACtB,GAAG,eAAS,SAAS;AAAA,IACzB,CAAC;AAAA,EACL;AACA,SAAOD,kBAAiB,SAAS,EAAE,OAAO;AAC9C;;;AC1HO,SAASE,aAAa,SAAiB;AAC1C,MAAS,OAAO,OAAO,GAAG;AACtB,QAAS,oBAAoB,OAAO,GAAG;AACnC,aAAY,YAAiB,kBAAkB,OAAO,CAAC;AAAA,IAC3D;AACA,WAAYA,aAAY,OAAO;AAAA,EACnC,OAAO;AACH,WAAY,YAAY,OAAO;AAAA,EACnC;AACJ;AA2BO,SAASC,WAAW,SAAiB;AACxC,MAAS,OAAO,OAAO,GAAG;AACtB,QAAS,oBAAoB,OAAO,GAAG;AACnC,aAAY,UAAe,kBAAkB,OAAO,CAAC;AAAA,IACzD;AACA,WAAYA,WAAU,OAAO;AAAA,EACjC,OAAO;AACH,WAAY,UAAU,OAAO;AAAA,EACjC;AACJ;;;AC1HA,IAAM,sBAAsB;AAC5B,IAAM,uBAAuB;AAC7B,IAAM,+BAA+B,cAAc,oBAAoB;AAOhE,SAAS,UAAW,KAAuB;AAC9C,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO;AAE5C,MAAI;AACJ,MAAI;AACA,iBAAa,UAAU,GAAG;AAAA,EAC9B,SAAS,OAAO;AAEZ,WAAO;AAAA,EACX;AAIA,QAAM,gBAAgB,WAEjB,QAAQ,sBAAsB,EAAE,EAChC,YAAY;AAEjB,SAAO,CAAC,cAAc,SAAS,aAAa;AAChD;AAEO,SAAS,oBAAqB,aAAqB,QAAwB;AAC9E,QAAM,MAAM,IAAI,IAAI,WAAW;AAE/B,QAAM,wBAAwB,IAAI,SAAS,MAAM,GAAG;AACpD,QAAM,cAAc,sBAAsB,SAAS,IAAI,sBAAsB,MAAM,CAAC,IAAI;AACxF,QAAM,SAAS,YAAY,KAAK,GAAG;AAEnC,MAAI,WAAW,GAAG,MAAM,IAAI,MAAM;AAElC,SAAO,IAAI,SAAS;AACxB;AAEA,SAAS,cAAe,QAAgB;AACpC,SAAO,OAAO,QAAQ,qBAAqB,MAAM;AACrD;AAIA,SAAS,QAAS,QAAgB,OAAuB;AACrD,MAAI,CAAC,MAAO,QAAO,IAAI,IAAI,MAAM;AAEjC,MAAI,SAAS,MAAM,IAAI,MAAM;AAC7B,MAAI,CAAC,QAAQ;AACT,aAAS,IAAI,IAAI,MAAM;AACvB,UAAM,IAAI,QAAQ,MAAM;AAAA,EAC5B;AACA,SAAO;AACX;AAGA,SAAS,iBAAkB,SAAiB,OAA6B;AAGrE,MAAI,CAAC,MAAO,QAAO,IAAI,OAAO,SAAS,GAAG;AAE1C,MAAI,KAAK,MAAM,IAAI,OAAO;AAC1B,MAAI,CAAC,IAAI;AAGL,SAAK,IAAI,OAAO,SAAS,GAAG;AAC5B,UAAM,IAAI,SAAS,EAAE;AAAA,EACzB;AACA,KAAG,YAAY;AACf,SAAO;AACX;AAEO,SAAS,kBAAmB,QAAgB,OAAkB;AACjE,QAAM,MAAM,QAAQ,QAAQ,KAAK;AACjC,QAAM,CAAC,QAAQ,GAAG,IAAI,IAAI,IAAI,SAAS,MAAM,GAAG;AAChD,QAAM,OAAO,IAAI,OAAO,IAAI,IAAI,IAAI,KAAK;AACzC,SAAO;AAAA,IACH,gBAAgB,GAAG,IAAI,QAAQ,OAAO,KAAK,KAAK,GAAG,CAAC,GAAG,IAAI;AAAA,IAC3D;AAAA,EACJ;AACJ;AAEO,SAAS,cAAe,QAAgB,MAAc,IAAY,UAAgC,CAAC,GAAW;AACjH,QAAM,EAAE,UAAU,OAAO,WAAW,aAAa,IAAI;AAErD,QAAM,UAAU,QAAQ,MAAM,SAAS;AAEvC,QAAM,kBAAkB,mBAAmB,QAAQ,QAAQ;AAG3D,MAAI,CAAC,gBAAgB,WAAW,IAAI,GAAG;AAGnC,UAAMC,eAAc,cAAc,IAAI;AACtC,UAAMC,oBAAmB,GAAGD,YAAW,SAAS,oBAAoB,IAAI,oBAAoB;AAC5F,UAAME,cAAa,iBAAiBD,mBAAkB,YAAY;AAClE,QAAIE,YAAW,OAAO,QAAQD,aAAY,EAAE;AAE5C,QAAI,SAAS;AACT,YAAM,cAAc,mBAAmB,IAAI;AAC3C,YAAM,qBAAqB,cAAc,WAAW;AAEpD,YAAM,0BAA0B,GAAG,kBAAkB,SAAS,oBAAoB,IAAI,oBAAoB;AAC1G,YAAM,oBAAoB,iBAAiB,yBAAyB,YAAY;AAChF,MAAAC,YAAWA,UAAS,QAAQ,mBAAmB,mBAAmB,EAAE,CAAC;AAAA,IACzE;AAEA,WAAOA;AAAA,EACX;AAKA,QAAM,cAAc,KAAK,QAAQ,KAAK,oBAAoB;AAG1D,QAAM,YAAY,GAAG,QAAQ,KAAK,IAAI;AAEtC,QAAM,cAAc,cAAc,WAAW,EAAE,QAAQ,8BAA8B,oBAAoB;AAEzG,QAAM,mBAAmB,GAAG,WAAW,SAAS,oBAAoB,IAAI,oBAAoB;AAC5F,QAAM,aAAa,iBAAiB,kBAAkB,YAAY;AAElE,MAAI,WAAW,OAAO,QAAQ,YAAY,SAAS;AAEnD,MAAI,SAAS;AAGT,UAAM,cAAc,mBAAmB,IAAI,EAAE,QAAQ,KAAK,oBAAoB;AAG9E,UAAM,YAAY,mBAAmB,EAAE,EAAE,QAAQ,KAAK,IAAI;AAE1D,UAAM,qBAAqB,cAAc,WAAW,EAAE,QAAQ,8BAA8B,oBAAoB;AAEhH,UAAM,0BAA0B,GAAG,kBAAkB,SAAS,oBAAoB,IAAI,oBAAoB;AAC1G,UAAM,oBAAoB,iBAAiB,yBAAyB,YAAY;AAEhF,eAAW,SAAS,QAAQ,mBAAmB,SAAS;AAAA,EAC5D;AAEA,SAAO;AACX;AAQO,SAAS,WAAY,KAAiC;AACzD,MAAI;AACA,UAAM,IAAiB,IAAI,IAAI,GAAG;AAClC,UAAM,oBAAqB,EAAE,SAAS,WAAW,GAAG,KAAK,EAAE,SAAS,SAAS,GAAG,IAC1E,EAAE,SAAS,MAAM,GAAG,EAAE,IACtB,EAAE;AACR,MAAE,OAAO,KAAK,iBAAiB,IAAI;AACnC,MAAE,cAAc,EAAE,QAAQC,WAAU,iBAAiB;AACrD,MAAE,cAAc,EAAE,aAAa,eAAgB,EAAE,QAAQC,aAAY,iBAAiB;AAEtF,WAAO;AAAA,EACX,QAAQ;AACJ,WAAO;AAAA,EACX;AACJ;","names":["check","createChecker","check","specialNetsCache","isLocalhost","specialNetsCache","createChecker","isSpecial","specialNetsCache","createChecker","isLocalhost","isSpecial","escapedFrom","fromWithBoundary","fromSearch","replaced","isSpecial","isLocalhost"]}