File size: 695 Bytes
45a105b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Open-redirect protection: only allow http(s) URLs whose host is explicitly allowed.
// Provider "requires_action" URLs are validated before navigation.
export function isSafeExternalUrl(url: string, allowedHosts: readonly string[]): boolean {
let u: URL
try {
u = new URL(url)
} catch {
return false
}
if (u.protocol !== 'https:' && u.protocol !== 'http:') return false
return allowedHosts.some(
(h) => u.hostname === h || u.hostname.endsWith(`.${h}`),
)
}
/** Relative in-app paths are always safe (no host); reject protocol-relative //evil. */
export function isSafeInternalPath(path: string): boolean {
return path.startsWith('/') && !path.startsWith('//')
}
|