UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

22 lines (21 loc) 1.36 kB
import { domainToASCII } from "node:url"; import net from "node:net"; //#region src/secrets/exact-hostname.ts /** * Canonical exact-host contract shared by per-secret destination bindings and the * egress-proxy config allowlists: lowercase ASCII/punycode, unbracketed IP literals, * no wildcard, scheme, path, or port. Throws with an operator-actionable message so * config validation and the secret store surface the same policy. */ function normalizeExactAllowedHost(raw) { const trimmed = raw.trim().toLowerCase().replace(/\.+$/u, ""); if (trimmed.includes("*")) throw new Error(`Allowed host "${raw}" cannot contain a wildcard; use one exact hostname.`); const unbracketed = trimmed.startsWith("[") && trimmed.endsWith("]") ? trimmed.slice(1, -1) : trimmed; if (net.isIP(unbracketed)) return unbracketed; if (!unbracketed || unbracketed.includes(":") || /[\s/?#@]/u.test(unbracketed)) throw new Error(`Allowed host "${raw}" must be a hostname without a scheme, path, wildcard, or port.`); const ascii = domainToASCII(unbracketed); if (!ascii || ascii.length > 253 || ascii.split(".").some((label) => !label || label.length > 63 || label.startsWith("-") || label.endsWith("-") || !/^[a-z0-9-]+$/u.test(label))) throw new Error(`Allowed host "${raw}" is not a valid hostname.`); return ascii; } //#endregion export { normalizeExactAllowedHost as t };