(host: string)
| 124 | } |
| 125 | |
| 126 | function isPrivateOrLoopbackIPv6(host: string): boolean { |
| 127 | const stripped = host.startsWith('[') && host.endsWith(']') ? host.slice(1, -1) : host |
| 128 | const lower = stripped.toLowerCase() |
| 129 | if (lower === '::' || lower === '::1') return true |
| 130 | if (/^fc[0-9a-f]{2}:/.test(lower) || /^fd[0-9a-f]{2}:/.test(lower)) return true |
| 131 | if (lower.startsWith('fe80:')) return true |
| 132 | return false |
| 133 | } |
| 134 | |
| 135 | /** Validate a URL is https and not pointing to a private/loopback host. */ |
| 136 | export function assertSafeExternalUrl(rawUrl: string, label: string): URL { |
no test coverage detected