UNPKG

@ogcio/o11y-sdk-node

Version:

Opentelemetry standard instrumentation SDK for NodeJS based project

74 lines (73 loc) 3.49 kB
import { BasicRedactor } from "./basic-redactor.js"; // iOS < 16.6 compatible: no lookbehind/lookahead // Building blocks — composed programmatically to avoid regex complexity & duplication const H = String.raw `[\da-f]{1,4}`; // single hex group const PCT = String.raw `(?:%[\da-f]{2})`; // percent-encoded byte const OCTET = String.raw `(?:25[0-5]|2[0-4]\d|[01]?\d\d?)`; // IPv4 octet 0-255 const IPV4_PATTERN = String.raw `${PCT}?${OCTET}(?:\.${OCTET}){3}${PCT}?`; const IPV6_ALTERNATIVES = [ `(?:${H}:){7}${H}`, // full 8-group `(?:${H}:){1,6}:${H}`, // :: after 1-6 groups + 1 trailing `(?:${H}:){1,5}(?::${H}){1,2}`, // :: after 1-5 + 1-2 trailing `(?:${H}:){1,4}(?::${H}){1,3}`, // :: after 1-4 + 1-3 trailing `(?:${H}:){1,3}(?::${H}){1,4}`, // :: after 1-3 + 1-4 trailing `(?:${H}:){1,2}(?::${H}){1,5}`, // :: after 1-2 + 1-5 trailing `${H}:(?::${H}){1,6}`, // :: after 1 + 1-6 trailing `::(?:${H}:){0,5}${H}`, // leading :: `${H}::(?:${H}:){0,5}${H}`, // 1 group + :: `(?:${H}:){2}::(?:${H}:){0,4}${H}`, // 2 groups + :: `(?:${H}:){3}::(?:${H}:){0,3}${H}`, // 3 groups + :: `(?:${H}:){4}::(?:${H}:){0,2}${H}`, // 4 groups + :: `(?:${H}:){5}::(?:${H}:)?${H}`, // 5 groups + :: `(?:${H}:){6}::${H}`, // 6 groups + :: `(?:${H}:){1,7}:`, // trailing :: String.raw `(?:${H}:){1,4}:${OCTET}(?:\.${OCTET}){3}`, // mixed IPv4 form ]; const IPV6_PATTERN = `${PCT}?(${IPV6_ALTERNATIVES.join("|")})${PCT}?`; export class IpRedactor extends BasicRedactor { static IPV4_REGEX = new RegExp(IPV4_PATTERN, "gi"); static IPV6_REGEX = new RegExp(IPV6_PATTERN, "gi"); redact(value) { const counters = {}; // First pass: redact IPv4 with boundary checking const tempValue = value.replace(IpRedactor.IPV4_REGEX, (match, ...args) => { const offset = args.at(-2); const before = offset > 0 ? value[offset - 1] : ""; const after = offset + match.length < value.length ? value[offset + match.length] : ""; // Check if surrounded by non-digit characters const isValidBefore = !before || !/\d/.test(before); const isValidAfter = !after || !/\d/.test(after); if (isValidBefore && isValidAfter) { counters["IPv4"] = (counters["IPv4"] || 0) + 1; return "[REDACTED IPV4]"; } return match; }); // Second pass: redact IPv6 with boundary checking const redactedValue = tempValue.replace(IpRedactor.IPV6_REGEX, (match, ...args) => { const offset = args.at(-2); const before = offset > 0 ? tempValue[offset - 1] : ""; const after = offset + match.length < tempValue.length ? tempValue[offset + match.length] : ""; // For IPv6: // Reject if there's a colon before (indicating :::) // Reject if there's a hex digit or colon after const isValidBefore = !before || !/[\da-f:]/i.test(before); const isValidAfter = !after || !/[\da-f:]/i.test(after); if (isValidBefore && isValidAfter) { counters["IPv6"] = (counters["IPv6"] || 0) + 1; return "[REDACTED IPV6]"; } return match; }); return { redactedValue: redactedValue, context: { counters, }, }; } }