UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

86 lines (85 loc) 3.13 kB
//#region packages/net-policy/src/redact-sensitive-url.ts function normalizeLowercaseStringOrEmpty(value) { return typeof value === "string" ? value.trim().toLowerCase() : ""; } /** Config UI hint tag for URL-like values that may embed credentials or tokens. */ const SENSITIVE_URL_HINT_TAG = "url-secret"; const SENSITIVE_URL_QUERY_PARAM_NAMES = new Set([ "token", "key", "api_key", "apikey", "secret", "access_token", "auth_token", "password", "pass", "passwd", "auth", "jwt", "session", "id_token", "code", "client_secret", "app_secret", "hook_token", "refresh_token", "signature", "x_amz_signature", "x_amz_security_token", "private_key", "credential", "authorization" ]); const URL_QUERY_NAME_SEPARATOR_RE = /[\p{C}\p{Z}\u115F\u1160\u3164\uFFA0+]/gu; function normalizeUrlQueryParamName(name) { const stripped = name.replace(URL_QUERY_NAME_SEPARATOR_RE, ""); try { return normalizeLowercaseStringOrEmpty(decodeURIComponent(stripped).replace(URL_QUERY_NAME_SEPARATOR_RE, "")).replaceAll("-", "_"); } catch { return normalizeLowercaseStringOrEmpty(stripped).replaceAll("-", "_"); } } /** True for auth-like URL query parameter names that should be redacted. */ function isSensitiveUrlQueryParamName(name) { const normalized = normalizeUrlQueryParamName(name); return SENSITIVE_URL_QUERY_PARAM_NAMES.has(normalized); } /** True for config paths whose URL values may contain credentials or secret query params. */ function isSensitiveUrlConfigPath(path) { if (path.endsWith(".baseUrl") || path.endsWith(".httpUrl")) return true; if (path.endsWith(".cdpUrl")) return true; if (path.endsWith(".request.proxy.url")) return true; return /^mcp\.servers\.(?:\*|[^.]+)\.url$/.test(path); } /** True when a config UI hint explicitly marks a URL-like value as secret-bearing. */ function hasSensitiveUrlHintTag(hint) { return hint?.tags?.includes(SENSITIVE_URL_HINT_TAG) === true; } /** Redacts credentials and sensitive query params from parseable URLs. */ function redactSensitiveUrl(value) { try { const parsed = new URL(value); let mutated = false; if (parsed.username || parsed.password) { parsed.username = parsed.username ? "***" : ""; parsed.password = parsed.password ? "***" : ""; mutated = true; } for (const key of Array.from(parsed.searchParams.keys())) if (isSensitiveUrlQueryParamName(key)) { parsed.searchParams.set(key, "***"); mutated = true; } return mutated ? parsed.toString() : value; } catch { return value; } } /** Redacts sensitive URL-looking substrings even when the full value is not a valid URL. */ function redactSensitiveUrlLikeString(value) { const redactedUrl = redactSensitiveUrl(value); if (redactedUrl !== value) return redactedUrl; return value.replace(/\/\/([^@/?#\s]+)@/g, "//***:***@").replace(/([?&])([^=&]+)=([^&]*)/g, (match, prefix, key) => isSensitiveUrlQueryParamName(key) ? `${prefix}${key}=***` : match); } //#endregion export { redactSensitiveUrl as a, isSensitiveUrlQueryParamName as i, hasSensitiveUrlHintTag as n, redactSensitiveUrlLikeString as o, isSensitiveUrlConfigPath as r, SENSITIVE_URL_HINT_TAG as t };