function parseRequestAuthority(value) { if ( value === '' || /[\s/@?#]/.test(value) || value.endsWith(':') ) return undefined try { const parsed = new URL(`http://${value}`) return parsed.hostname === '' ? undefined : parsed } catch { return undefined } } export function isLoopbackHostname(hostname) { if (hostname === 'localhost' || hostname === '[::1]') return true const parts = hostname.split('.') return parts.length === 4 && parts[0] === '127' && parts.every(part => /^\d{1,3}$/.test(part) && Number(part) <= 255) } function matchesTrustedAuthority(requestUrl, trustedHosts) { if (trustedHosts.wildcard) return true return trustedHosts.authorities.some((entry) => ( entry.anyPort ? entry.hostname === requestUrl.hostname : entry.matchAuthority === requestUrl.host )) } export function inspectExternalRequest(headers, trustedHosts, { allowCrossOrigin = false, allowUntrustedAuthority = false, } = {}) { const host = headers.host if (typeof host !== 'string') return Object.freeze({ accepted: false, reason: 'missing-host' }) const hostUrl = parseRequestAuthority(host) if (hostUrl === undefined) return Object.freeze({ accepted: false, reason: 'invalid-host' }) if (!allowUntrustedAuthority && !isLoopbackHostname(hostUrl.hostname) && !matchesTrustedAuthority(hostUrl, trustedHosts)) { return Object.freeze({ accepted: false, reason: 'untrusted-host' }) } if (!allowCrossOrigin && headers['sec-fetch-site'] === 'cross-site') { return Object.freeze({ accepted: false, reason: 'cross-site' }) } const origin = headers.origin if (!allowCrossOrigin && origin !== undefined) { if (typeof origin !== 'string') return Object.freeze({ accepted: false, reason: 'invalid-origin' }) try { if (new URL(origin).host !== hostUrl.host) { return Object.freeze({ accepted: false, reason: 'origin-mismatch' }) } } catch { return Object.freeze({ accepted: false, reason: 'invalid-origin' }) } } return Object.freeze({ accepted: true, externalAuthority: hostUrl.host }) }