const HOUSEKEEPING_ORIGIN = "https://housekeeping.invalid"; function containsControlCharacter(value: string): boolean { return Array.from(value).some((character) => { const code = character.codePointAt(0) ?? 0; return code < 32 || code === 127; }); } function decodedVariants(value: string): readonly string[] | null { const variants = [value]; for (let pass = 0; pass < 3; pass += 1) { let decoded: string; try { decoded = decodeURIComponent(variants.at(-1) ?? ""); } catch { return null; } if (decoded === variants.at(-1)) break; variants.push(decoded); } return variants; } function containsDotSegment(path: string): boolean { return path.split("/").some((segment) => segment === "." || segment === ".."); } export function isSafeHousekeepingHref(href: string): boolean { if ( href.length === 0 || !href.startsWith("/") || href.startsWith("//") || containsControlCharacter(href) || href.includes("\\") ) { return false; } const variants = decodedVariants(href); if ( variants === null || variants.some( (value) => containsControlCharacter(value) || value.includes("\\"), ) ) { return false; } const rawPath = href.split(/[?#]/u, 1)[0] ?? ""; const pathVariants = decodedVariants(rawPath); if ( pathVariants === null || pathVariants.some((path) => containsDotSegment(path)) ) { return false; } let normalized: URL; try { normalized = new URL(href, HOUSEKEEPING_ORIGIN); } catch { return false; } return ( normalized.origin === HOUSEKEEPING_ORIGIN && (normalized.pathname === "/ase" || normalized.pathname.startsWith("/ase/")) ); }