/** * Deterministic fast path prefix matcher for dynamic bypasses */ export function isPathBypassed( requestPath: string, bypassPaths?: string[], ): boolean { if (!bypassPaths || bypassPaths.length === 0) return false; for (const pattern of bypassPaths) { if (pattern === requestPath) return true; if (pattern.endsWith("/*")) { const prefix = pattern.slice(0, -2); if (requestPath === prefix || requestPath.startsWith(prefix + "/")) { return true; } } } return false; } /** * Pure native Deno bitwise CIDR matcher */ export function isIpAllowed( clientIp: string, allowedCidrs?: string[], ): boolean { if (!allowedCidrs || allowedCidrs.length === 0) return false; const parseIp4 = (ip: string) => { const parts = ip.split("."); if (parts.length !== 4) return null; return parts.reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) >>> 0; }; const primaryIp = clientIp.split(",")[0].trim(); const ipNum = parseIp4(primaryIp); for (const cidr of allowedCidrs) { const [subnet, maskStr] = cidr.split("/"); if (!maskStr) { if (subnet === primaryIp) return true; continue; } if (ipNum !== null && subnet.includes(".")) { const subnetNum = parseIp4(subnet); if (subnetNum !== null) { const maskBits = parseInt(maskStr, 10); const mask = maskBits === 0 ? 0 : ((0xffffffff << (32 - maskBits)) >>> 0); if ((ipNum & mask) === (subnetNum & mask)) { return true; } } } else if (subnet === clientIp) { return true; } } return false; } /** * Validates a given URL to ensure it is safe to redirect to. */ export function isSafeRedirectUrl( rawUrl: string, customDomain?: string, ): boolean { if (!rawUrl) return false; if (rawUrl.startsWith("/") && !rawUrl.startsWith("//")) { return true; } try { const parsed = new URL(rawUrl); const host = parsed.hostname; const root = customDomain || Deno.env.get("RP_ID") || "atyg.org"; const cleanRoot = root.replace(/^\./, ""); if ( host === "localhost" || host === "atyg.org" || host.endsWith(".atyg.org") || host === cleanRoot || host.endsWith(`.${cleanRoot}`) ) { return true; } } catch (_e) { return false; } return false; }