@agent-inspect/redact 6.31.4 → 6.31.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -59,7 +59,7 @@ function isCredentialSensitiveKey(key, sensitiveKeys) {
59
59
  }
60
60
 
61
61
  // packages/redact/src/key-value-secret.ts
62
- var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})`;
62
+ var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?]))([^\s"'\\]{8,})`;
63
63
  var KEY_VALUE_SECRET_PATTERN = new RegExp(
64
64
  KEY_VALUE_SECRET_PATTERN_SOURCE,
65
65
  "i"
@@ -71,6 +71,21 @@ function valueContainsKeyValueSecret(value) {
71
71
 
72
72
  // packages/redact/src/url-redaction.ts
73
73
  var HTTP_URL = /^https?:\/\/[^\s]+$/i;
74
+ var CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
75
+ "postgres:",
76
+ "postgresql:",
77
+ "mysql:",
78
+ "mariadb:",
79
+ "mongodb:",
80
+ "mongodb+srv:",
81
+ "redis:",
82
+ "rediss:",
83
+ "amqp:",
84
+ "amqps:"
85
+ ]);
86
+ var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
87
+ var CONNECTION_USERINFO = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
88
+ var CONNECTION_HAS_USERINFO = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
74
89
  var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
75
90
  var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
76
91
  var NUMERIC_SEGMENT = /^\d{5,}$/;
@@ -78,14 +93,47 @@ var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
78
93
  function looksLikeHttpUrl(value) {
79
94
  return HTTP_URL.test(value.trim());
80
95
  }
81
- function parseHttpUrl(value) {
96
+ function looksLikeConnectionUri(value) {
97
+ return CONNECTION_URI.test(value.trim());
98
+ }
99
+ function looksLikeUrlForRedaction(value) {
100
+ return looksLikeHttpUrl(value) || looksLikeConnectionUri(value);
101
+ }
102
+ function parseRedactableUrl(value) {
82
103
  try {
83
104
  const url = new URL(value.trim());
84
- return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
105
+ if (url.protocol === "http:" || url.protocol === "https:") return url;
106
+ if (CONNECTION_PROTOCOLS.has(url.protocol)) return url;
107
+ return void 0;
85
108
  } catch {
86
109
  return void 0;
87
110
  }
88
111
  }
112
+ function redactConnectionUserinfoFallback(value, replacement) {
113
+ const trimmed = value.trim();
114
+ const match = CONNECTION_USERINFO.exec(trimmed);
115
+ if (match) {
116
+ const [, scheme, , rest] = match;
117
+ if (scheme && rest && rest.length > 0) {
118
+ return {
119
+ value: `${scheme}://${rest}`,
120
+ credentialRedacted: true,
121
+ identifiersMasked: false
122
+ };
123
+ }
124
+ }
125
+ if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {
126
+ return {
127
+ value: replacement,
128
+ credentialRedacted: true,
129
+ identifiersMasked: false
130
+ };
131
+ }
132
+ return void 0;
133
+ }
134
+ function isHttpProtocol(protocol) {
135
+ return protocol === "http:" || protocol === "https:";
136
+ }
89
137
  function isIdentifierSegment(segment) {
90
138
  if (UUID_SEGMENT.test(segment)) return true;
91
139
  if (HEX_SEGMENT.test(segment)) return true;
@@ -123,15 +171,18 @@ function redactUrlString(value, options) {
123
171
  credentialRedacted: false,
124
172
  identifiersMasked: false
125
173
  };
126
- if (!looksLikeHttpUrl(value)) return unchanged;
127
- const url = parseHttpUrl(value);
128
- if (!url) return unchanged;
174
+ if (!looksLikeUrlForRedaction(value)) return unchanged;
129
175
  const replacement = options.replacement ?? "[REDACTED]";
176
+ const url = parseRedactableUrl(value);
177
+ if (!url) {
178
+ return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;
179
+ }
130
180
  const idPlaceholder = options.idPlaceholder ?? "[id]";
181
+ const http = isHttpProtocol(url.protocol);
131
182
  let credentialRedacted = url.username.length > 0 || url.password.length > 0;
132
183
  let identifiersMasked = false;
133
184
  let pathname = url.pathname;
134
- if (options.maskPathIds === true) {
185
+ if (http && options.maskPathIds === true) {
135
186
  pathname = url.pathname.split("/").map((segment) => {
136
187
  if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
137
188
  return segment;
@@ -581,7 +632,7 @@ var Redactor = class {
581
632
  return applyRule(rule, value, this.#replacement);
582
633
  }
583
634
  }
584
- if (typeof value === "string" && looksLikeHttpUrl(value)) {
635
+ if (typeof value === "string" && looksLikeUrlForRedaction(value)) {
585
636
  const url = redactUrlString(value, {
586
637
  sensitiveKeys: this.#sensitiveKeys,
587
638
  isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== void 0,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/url-redaction.ts","../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are\n * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).\n * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\\[(?:REDACTED(?::[^\\]]*)?|HASH:[0-9a-f]{8})\\](?![^\\s\"'\\\\&#?;/]))([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","/**\n * URL-aware redaction for http(s) values.\n *\n * Keeps scheme, host and path so two attempts of the same step stay\n * comparable, and removes credentials carried in userinfo, query params and\n * fragment params. Identifier-looking path segments are masked when the\n * profile redacts identifiers.\n *\n * Mirrors `packages/core/src/safety/url-redaction.ts`. Keep both copies in sync.\n */\n\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport interface UrlRedactionOptions {\n /** Field names the active profile redacts, used for query and fragment params. */\n sensitiveKeys: readonly string[];\n /** Value-level credential check, usually the profile's detectors. */\n isSensitiveValue: (value: string) => boolean;\n replacement?: string;\n /** Mask identifier-looking path segments (share and strict profiles). */\n maskPathIds?: boolean;\n idPlaceholder?: string;\n}\n\nexport interface UrlRedactionResult {\n value: string;\n credentialRedacted: boolean;\n identifiersMasked: boolean;\n}\n\nconst HTTP_URL = /^https?:\\/\\/[^\\s]+$/i;\n\nconst UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst HEX_SEGMENT = /^[0-9a-f]{12,}$/i;\nconst NUMERIC_SEGMENT = /^\\d{5,}$/;\nconst OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;\n\n/** True when the whole string is a single http(s) URL. */\nexport function looksLikeHttpUrl(value: string): boolean {\n return HTTP_URL.test(value.trim());\n}\n\nfunction parseHttpUrl(value: string): URL | undefined {\n try {\n const url = new URL(value.trim());\n return url.protocol === \"http:\" || url.protocol === \"https:\" ? url : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isIdentifierSegment(segment: string): boolean {\n if (UUID_SEGMENT.test(segment)) return true;\n if (HEX_SEGMENT.test(segment)) return true;\n if (NUMERIC_SEGMENT.test(segment)) return true;\n return OPAQUE_SEGMENT.test(segment) && /\\d/.test(segment) && /[A-Za-z]/.test(segment);\n}\n\nfunction decodeParam(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, \" \"));\n } catch {\n return value;\n }\n}\n\nfunction redactParams(\n raw: string,\n options: UrlRedactionOptions,\n replacement: string,\n): { value: string; redacted: boolean } {\n let redacted = false;\n const parts = raw.split(\"&\").map((part) => {\n if (part.length === 0) return part;\n const separator = part.indexOf(\"=\");\n if (separator < 0) return part;\n const rawKey = part.slice(0, separator);\n const rawValue = part.slice(separator + 1);\n const key = decodeParam(rawKey);\n const value = decodeParam(rawValue);\n if (\n isCredentialSensitiveKey(key, options.sensitiveKeys) ||\n options.isSensitiveValue(value)\n ) {\n redacted = true;\n return `${rawKey}=${replacement}`;\n }\n return part;\n });\n return { value: parts.join(\"&\"), redacted };\n}\n\n/**\n * Redacts the sensitive parts of an http(s) URL. Returns the value unchanged\n * when it is not a URL or has nothing to remove.\n */\nexport function redactUrlString(\n value: string,\n options: UrlRedactionOptions,\n): UrlRedactionResult {\n const unchanged: UrlRedactionResult = {\n value,\n credentialRedacted: false,\n identifiersMasked: false,\n };\n if (!looksLikeHttpUrl(value)) return unchanged;\n\n const url = parseHttpUrl(value);\n if (!url) return unchanged;\n\n const replacement = options.replacement ?? \"[REDACTED]\";\n const idPlaceholder = options.idPlaceholder ?? \"[id]\";\n\n let credentialRedacted = url.username.length > 0 || url.password.length > 0;\n let identifiersMasked = false;\n\n let pathname = url.pathname;\n if (options.maskPathIds === true) {\n pathname = url.pathname\n .split(\"/\")\n .map((segment) => {\n if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {\n return segment;\n }\n identifiersMasked = true;\n return idPlaceholder;\n })\n .join(\"/\");\n }\n\n let search = \"\";\n if (url.search.length > 1) {\n const params = redactParams(url.search.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n search = `?${params.value}`;\n } else if (url.search.length === 1) {\n search = \"?\";\n }\n\n let hash = url.hash;\n if (url.hash.includes(\"=\")) {\n const params = redactParams(url.hash.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n hash = `#${params.value}`;\n }\n\n if (!credentialRedacted && !identifiersMasked) return unchanged;\n\n return {\n value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,\n credentialRedacted,\n identifiersMasked,\n };\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\nimport { looksLikeHttpUrl, redactUrlString } from \"./url-redaction.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule = (\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" }\n) & { raw?: string };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) =>\n isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key]),\n );\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key, raw: rule.raw ?? rule.key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #sensitiveKeys: readonly string[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #detect(\n value: string,\n key: string | undefined,\n path: string,\n ): { detector: RedactionDetector; detection: RedactionDetection } | undefined {\n for (const detector of this.#detectors) {\n for (const detection of detector.detect({ path, key, value })) {\n if ((detection.action ?? \"replace\") !== \"keep\") return { detector, detection };\n }\n }\n return undefined;\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n if (typeof value === \"string\" && looksLikeHttpUrl(value)) {\n const url = redactUrlString(value, {\n sensitiveKeys: this.#sensitiveKeys,\n isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== undefined,\n replacement: this.#replacement,\n maskPathIds: this.#profile !== \"local\",\n });\n if (url.value !== value) {\n this.#recordFinding(\n state,\n makeFinding(\n path,\n url.credentialRedacted ? \"value.urlCredential\" : \"value.urlIdentifier\",\n \"replace\",\n \"value\",\n url.credentialRedacted ? \"error\" : \"warning\",\n ),\n );\n const residual = this.#detect(\n url.value.split(this.#replacement).join(\"\"),\n key,\n path,\n );\n if (residual === undefined) return url.value;\n this.#recordFinding(\n state,\n makeFinding(\n path,\n residual.detector.id,\n \"replace\",\n residual.detection.matchKind ?? residual.detector.matchKind ?? \"custom\",\n residual.detection.severity ?? residual.detector.severity ?? \"warning\",\n ),\n );\n return this.#replacement;\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
1
+ {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/url-redaction.ts","../src/index.ts"],"names":["crypto"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are\n * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).\n * A marker used as a prefix (`[REDACTED]canary…`) or incomplete marker\n * (`[REDACTED]/canary…`) is still a secret. Query separators (`&`, `#`, `?`)\n * may end a complete placeholder when the same form appears in a URL query;\n * `/` and `;` do **not** — they are ordinary free-text characters.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\\[(?:REDACTED(?::[^\\]]*)?|HASH:[0-9a-f]{8})\\](?![^\\s\"'\\\\&#?]))([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","/**\n * URL-aware redaction for http(s) and common connection-string schemes.\n *\n * Keeps scheme, host and path so two attempts of the same step stay\n * comparable, and removes credentials carried in userinfo, query params and\n * fragment params. Identifier-looking path segments are masked on http(s)\n * when the profile redacts identifiers. Connection URIs only strip userinfo\n * and sensitive params so database/queue paths stay intact.\n *\n * Mirrors `packages/core/src/safety/url-redaction.ts`. Keep both copies in sync.\n */\n\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport interface UrlRedactionOptions {\n /** Field names the active profile redacts, used for query and fragment params. */\n sensitiveKeys: readonly string[];\n /** Value-level credential check, usually the profile's detectors. */\n isSensitiveValue: (value: string) => boolean;\n replacement?: string;\n /** Mask identifier-looking path segments (share and strict profiles, http(s) only). */\n maskPathIds?: boolean;\n idPlaceholder?: string;\n}\n\nexport interface UrlRedactionResult {\n value: string;\n credentialRedacted: boolean;\n identifiersMasked: boolean;\n}\n\nconst HTTP_URL = /^https?:\\/\\/[^\\s]+$/i;\n\n/** Connection schemes common in agent tool attributes (DB, cache, queue). */\nconst CONNECTION_PROTOCOLS = new Set([\n \"postgres:\",\n \"postgresql:\",\n \"mysql:\",\n \"mariadb:\",\n \"mongodb:\",\n \"mongodb+srv:\",\n \"redis:\",\n \"rediss:\",\n \"amqp:\",\n \"amqps:\",\n]);\n\nconst CONNECTION_URI =\n /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/[^\\s]+$/i;\n\n/**\n * Connection strings are not always WHATWG URLs (multihost + IP-literal\n * authorities). When `new URL` fails, strip a clear userinfo@ authority\n * prefix so credentials never survive as unchanged SAFE text.\n * @see https://github.com/mongodb/specifications/blob/master/source/connection-string/connection-string-spec.md#host-information\n */\nconst CONNECTION_USERINFO =\n /^(postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/([^@/?#]+)@(.+)$/i;\n\nconst CONNECTION_HAS_USERINFO =\n /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/[^@/?#]+@/i;\n\n\nconst UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst HEX_SEGMENT = /^[0-9a-f]{12,}$/i;\nconst NUMERIC_SEGMENT = /^\\d{5,}$/;\nconst OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;\n\n/** True when the whole string is a single http(s) URL. */\nexport function looksLikeHttpUrl(value: string): boolean {\n return HTTP_URL.test(value.trim());\n}\n\n/** True when the whole string is a known connection URI with a scheme:// authority. */\nexport function looksLikeConnectionUri(value: string): boolean {\n return CONNECTION_URI.test(value.trim());\n}\n\n/** True when the value is eligible for URL-aware rewrite (http(s) or connection URI). */\nexport function looksLikeUrlForRedaction(value: string): boolean {\n return looksLikeHttpUrl(value) || looksLikeConnectionUri(value);\n}\n\nfunction parseRedactableUrl(value: string): URL | undefined {\n try {\n const url = new URL(value.trim());\n if (url.protocol === \"http:\" || url.protocol === \"https:\") return url;\n if (CONNECTION_PROTOCOLS.has(url.protocol)) return url;\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Strip userinfo when the generic URL parser cannot handle a recognized\n * connection authority (e.g. comma-separated multihost lists).\n */\nfunction redactConnectionUserinfoFallback(\n value: string,\n replacement: string,\n): UrlRedactionResult | undefined {\n const trimmed = value.trim();\n const match = CONNECTION_USERINFO.exec(trimmed);\n if (match) {\n const [, scheme, , rest] = match;\n if (scheme && rest && rest.length > 0) {\n return {\n value: `${scheme}://${rest}`,\n credentialRedacted: true,\n identifiersMasked: false,\n };\n }\n }\n // Recognized scheme with userinfo that still cannot be rewritten safely:\n // withhold the whole value rather than leave credentials unchanged.\n if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {\n return {\n value: replacement,\n credentialRedacted: true,\n identifiersMasked: false,\n };\n }\n return undefined;\n}\n\nfunction isHttpProtocol(protocol: string): boolean {\n return protocol === \"http:\" || protocol === \"https:\";\n}\n\nfunction isIdentifierSegment(segment: string): boolean {\n if (UUID_SEGMENT.test(segment)) return true;\n if (HEX_SEGMENT.test(segment)) return true;\n if (NUMERIC_SEGMENT.test(segment)) return true;\n return OPAQUE_SEGMENT.test(segment) && /\\d/.test(segment) && /[A-Za-z]/.test(segment);\n}\n\nfunction decodeParam(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, \" \"));\n } catch {\n return value;\n }\n}\n\nfunction redactParams(\n raw: string,\n options: UrlRedactionOptions,\n replacement: string,\n): { value: string; redacted: boolean } {\n let redacted = false;\n const parts = raw.split(\"&\").map((part) => {\n if (part.length === 0) return part;\n const separator = part.indexOf(\"=\");\n if (separator < 0) return part;\n const rawKey = part.slice(0, separator);\n const rawValue = part.slice(separator + 1);\n const key = decodeParam(rawKey);\n const value = decodeParam(rawValue);\n if (\n isCredentialSensitiveKey(key, options.sensitiveKeys) ||\n options.isSensitiveValue(value)\n ) {\n redacted = true;\n return `${rawKey}=${replacement}`;\n }\n return part;\n });\n return { value: parts.join(\"&\"), redacted };\n}\n\n/**\n * Redacts the sensitive parts of an http(s) or connection URI. Returns the\n * value unchanged when it is not a supported URL or has nothing to remove.\n */\nexport function redactUrlString(\n value: string,\n options: UrlRedactionOptions,\n): UrlRedactionResult {\n const unchanged: UrlRedactionResult = {\n value,\n credentialRedacted: false,\n identifiersMasked: false,\n };\n if (!looksLikeUrlForRedaction(value)) return unchanged;\n\n const replacement = options.replacement ?? \"[REDACTED]\";\n const url = parseRedactableUrl(value);\n if (!url) {\n return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;\n }\n\n const idPlaceholder = options.idPlaceholder ?? \"[id]\";\n const http = isHttpProtocol(url.protocol);\n\n let credentialRedacted = url.username.length > 0 || url.password.length > 0;\n let identifiersMasked = false;\n\n let pathname = url.pathname;\n if (http && options.maskPathIds === true) {\n pathname = url.pathname\n .split(\"/\")\n .map((segment) => {\n if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {\n return segment;\n }\n identifiersMasked = true;\n return idPlaceholder;\n })\n .join(\"/\");\n }\n\n let search = \"\";\n if (url.search.length > 1) {\n const params = redactParams(url.search.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n search = `?${params.value}`;\n } else if (url.search.length === 1) {\n search = \"?\";\n }\n\n let hash = url.hash;\n if (url.hash.includes(\"=\")) {\n const params = redactParams(url.hash.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n hash = `#${params.value}`;\n }\n\n if (!credentialRedacted && !identifiersMasked) return unchanged;\n\n return {\n value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,\n credentialRedacted,\n identifiersMasked,\n };\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\nimport { looksLikeUrlForRedaction, redactUrlString } from \"./url-redaction.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule = (\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" }\n) & { raw?: string };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) =>\n isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key]),\n );\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key, raw: rule.raw ?? rule.key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #sensitiveKeys: readonly string[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #detect(\n value: string,\n key: string | undefined,\n path: string,\n ): { detector: RedactionDetector; detection: RedactionDetection } | undefined {\n for (const detector of this.#detectors) {\n for (const detection of detector.detect({ path, key, value })) {\n if ((detection.action ?? \"replace\") !== \"keep\") return { detector, detection };\n }\n }\n return undefined;\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n if (typeof value === \"string\" && looksLikeUrlForRedaction(value)) {\n const url = redactUrlString(value, {\n sensitiveKeys: this.#sensitiveKeys,\n isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== undefined,\n replacement: this.#replacement,\n maskPathIds: this.#profile !== \"local\",\n });\n if (url.value !== value) {\n this.#recordFinding(\n state,\n makeFinding(\n path,\n url.credentialRedacted ? \"value.urlCredential\" : \"value.urlIdentifier\",\n \"replace\",\n \"value\",\n url.credentialRedacted ? \"error\" : \"warning\",\n ),\n );\n const residual = this.#detect(\n url.value.split(this.#replacement).join(\"\"),\n key,\n path,\n );\n if (residual === undefined) return url.value;\n this.#recordFinding(\n state,\n makeFinding(\n path,\n residual.detector.id,\n \"replace\",\n residual.detection.matchKind ?? residual.detector.matchKind ?? \"custom\",\n residual.detection.severity ?? residual.detector.severity ?? \"warning\",\n ),\n );\n return this.#replacement;\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
package/dist/index.d.cts CHANGED
@@ -10,7 +10,10 @@
10
10
  * Intentionally does **not** match metric/config lookalikes such as
11
11
  * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are
12
12
  * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).
13
- * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.
13
+ * A marker used as a prefix (`[REDACTED]canary…`) or incomplete marker
14
+ * (`[REDACTED]/canary…`) is still a secret. Query separators (`&`, `#`, `?`)
15
+ * may end a complete placeholder when the same form appears in a URL query;
16
+ * `/` and `;` do **not** — they are ordinary free-text characters.
14
17
  */
15
18
  declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
16
19
  declare const KEY_VALUE_SECRET_PATTERN: RegExp;
package/dist/index.d.ts CHANGED
@@ -10,7 +10,10 @@
10
10
  * Intentionally does **not** match metric/config lookalikes such as
11
11
  * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are
12
12
  * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).
13
- * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.
13
+ * A marker used as a prefix (`[REDACTED]canary…`) or incomplete marker
14
+ * (`[REDACTED]/canary…`) is still a secret. Query separators (`&`, `#`, `?`)
15
+ * may end a complete placeholder when the same form appears in a URL query;
16
+ * `/` and `;` do **not** — they are ordinary free-text characters.
14
17
  */
15
18
  declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
16
19
  declare const KEY_VALUE_SECRET_PATTERN: RegExp;
package/dist/index.mjs CHANGED
@@ -53,7 +53,7 @@ function isCredentialSensitiveKey(key, sensitiveKeys) {
53
53
  }
54
54
 
55
55
  // packages/redact/src/key-value-secret.ts
56
- var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?;/]))([^\s"'\\]{8,})`;
56
+ var KEY_VALUE_SECRET_PATTERN_SOURCE = String.raw`\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\[(?:REDACTED(?::[^\]]*)?|HASH:[0-9a-f]{8})\](?![^\s"'\\&#?]))([^\s"'\\]{8,})`;
57
57
  var KEY_VALUE_SECRET_PATTERN = new RegExp(
58
58
  KEY_VALUE_SECRET_PATTERN_SOURCE,
59
59
  "i"
@@ -65,6 +65,21 @@ function valueContainsKeyValueSecret(value) {
65
65
 
66
66
  // packages/redact/src/url-redaction.ts
67
67
  var HTTP_URL = /^https?:\/\/[^\s]+$/i;
68
+ var CONNECTION_PROTOCOLS = /* @__PURE__ */ new Set([
69
+ "postgres:",
70
+ "postgresql:",
71
+ "mysql:",
72
+ "mariadb:",
73
+ "mongodb:",
74
+ "mongodb+srv:",
75
+ "redis:",
76
+ "rediss:",
77
+ "amqp:",
78
+ "amqps:"
79
+ ]);
80
+ var CONNECTION_URI = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^\s]+$/i;
81
+ var CONNECTION_USERINFO = /^(postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/([^@/?#]+)@(.+)$/i;
82
+ var CONNECTION_HAS_USERINFO = /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\+srv)?|rediss?|amqps?):\/\/[^@/?#]+@/i;
68
83
  var UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
69
84
  var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
70
85
  var NUMERIC_SEGMENT = /^\d{5,}$/;
@@ -72,14 +87,47 @@ var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
72
87
  function looksLikeHttpUrl(value) {
73
88
  return HTTP_URL.test(value.trim());
74
89
  }
75
- function parseHttpUrl(value) {
90
+ function looksLikeConnectionUri(value) {
91
+ return CONNECTION_URI.test(value.trim());
92
+ }
93
+ function looksLikeUrlForRedaction(value) {
94
+ return looksLikeHttpUrl(value) || looksLikeConnectionUri(value);
95
+ }
96
+ function parseRedactableUrl(value) {
76
97
  try {
77
98
  const url = new URL(value.trim());
78
- return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
99
+ if (url.protocol === "http:" || url.protocol === "https:") return url;
100
+ if (CONNECTION_PROTOCOLS.has(url.protocol)) return url;
101
+ return void 0;
79
102
  } catch {
80
103
  return void 0;
81
104
  }
82
105
  }
106
+ function redactConnectionUserinfoFallback(value, replacement) {
107
+ const trimmed = value.trim();
108
+ const match = CONNECTION_USERINFO.exec(trimmed);
109
+ if (match) {
110
+ const [, scheme, , rest] = match;
111
+ if (scheme && rest && rest.length > 0) {
112
+ return {
113
+ value: `${scheme}://${rest}`,
114
+ credentialRedacted: true,
115
+ identifiersMasked: false
116
+ };
117
+ }
118
+ }
119
+ if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {
120
+ return {
121
+ value: replacement,
122
+ credentialRedacted: true,
123
+ identifiersMasked: false
124
+ };
125
+ }
126
+ return void 0;
127
+ }
128
+ function isHttpProtocol(protocol) {
129
+ return protocol === "http:" || protocol === "https:";
130
+ }
83
131
  function isIdentifierSegment(segment) {
84
132
  if (UUID_SEGMENT.test(segment)) return true;
85
133
  if (HEX_SEGMENT.test(segment)) return true;
@@ -117,15 +165,18 @@ function redactUrlString(value, options) {
117
165
  credentialRedacted: false,
118
166
  identifiersMasked: false
119
167
  };
120
- if (!looksLikeHttpUrl(value)) return unchanged;
121
- const url = parseHttpUrl(value);
122
- if (!url) return unchanged;
168
+ if (!looksLikeUrlForRedaction(value)) return unchanged;
123
169
  const replacement = options.replacement ?? "[REDACTED]";
170
+ const url = parseRedactableUrl(value);
171
+ if (!url) {
172
+ return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;
173
+ }
124
174
  const idPlaceholder = options.idPlaceholder ?? "[id]";
175
+ const http = isHttpProtocol(url.protocol);
125
176
  let credentialRedacted = url.username.length > 0 || url.password.length > 0;
126
177
  let identifiersMasked = false;
127
178
  let pathname = url.pathname;
128
- if (options.maskPathIds === true) {
179
+ if (http && options.maskPathIds === true) {
129
180
  pathname = url.pathname.split("/").map((segment) => {
130
181
  if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
131
182
  return segment;
@@ -575,7 +626,7 @@ var Redactor = class {
575
626
  return applyRule(rule, value, this.#replacement);
576
627
  }
577
628
  }
578
- if (typeof value === "string" && looksLikeHttpUrl(value)) {
629
+ if (typeof value === "string" && looksLikeUrlForRedaction(value)) {
579
630
  const url = redactUrlString(value, {
580
631
  sensitiveKeys: this.#sensitiveKeys,
581
632
  isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== void 0,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/url-redaction.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are\n * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).\n * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\\[(?:REDACTED(?::[^\\]]*)?|HASH:[0-9a-f]{8})\\](?![^\\s\"'\\\\&#?;/]))([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","/**\n * URL-aware redaction for http(s) values.\n *\n * Keeps scheme, host and path so two attempts of the same step stay\n * comparable, and removes credentials carried in userinfo, query params and\n * fragment params. Identifier-looking path segments are masked when the\n * profile redacts identifiers.\n *\n * Mirrors `packages/core/src/safety/url-redaction.ts`. Keep both copies in sync.\n */\n\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport interface UrlRedactionOptions {\n /** Field names the active profile redacts, used for query and fragment params. */\n sensitiveKeys: readonly string[];\n /** Value-level credential check, usually the profile's detectors. */\n isSensitiveValue: (value: string) => boolean;\n replacement?: string;\n /** Mask identifier-looking path segments (share and strict profiles). */\n maskPathIds?: boolean;\n idPlaceholder?: string;\n}\n\nexport interface UrlRedactionResult {\n value: string;\n credentialRedacted: boolean;\n identifiersMasked: boolean;\n}\n\nconst HTTP_URL = /^https?:\\/\\/[^\\s]+$/i;\n\nconst UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst HEX_SEGMENT = /^[0-9a-f]{12,}$/i;\nconst NUMERIC_SEGMENT = /^\\d{5,}$/;\nconst OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;\n\n/** True when the whole string is a single http(s) URL. */\nexport function looksLikeHttpUrl(value: string): boolean {\n return HTTP_URL.test(value.trim());\n}\n\nfunction parseHttpUrl(value: string): URL | undefined {\n try {\n const url = new URL(value.trim());\n return url.protocol === \"http:\" || url.protocol === \"https:\" ? url : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isIdentifierSegment(segment: string): boolean {\n if (UUID_SEGMENT.test(segment)) return true;\n if (HEX_SEGMENT.test(segment)) return true;\n if (NUMERIC_SEGMENT.test(segment)) return true;\n return OPAQUE_SEGMENT.test(segment) && /\\d/.test(segment) && /[A-Za-z]/.test(segment);\n}\n\nfunction decodeParam(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, \" \"));\n } catch {\n return value;\n }\n}\n\nfunction redactParams(\n raw: string,\n options: UrlRedactionOptions,\n replacement: string,\n): { value: string; redacted: boolean } {\n let redacted = false;\n const parts = raw.split(\"&\").map((part) => {\n if (part.length === 0) return part;\n const separator = part.indexOf(\"=\");\n if (separator < 0) return part;\n const rawKey = part.slice(0, separator);\n const rawValue = part.slice(separator + 1);\n const key = decodeParam(rawKey);\n const value = decodeParam(rawValue);\n if (\n isCredentialSensitiveKey(key, options.sensitiveKeys) ||\n options.isSensitiveValue(value)\n ) {\n redacted = true;\n return `${rawKey}=${replacement}`;\n }\n return part;\n });\n return { value: parts.join(\"&\"), redacted };\n}\n\n/**\n * Redacts the sensitive parts of an http(s) URL. Returns the value unchanged\n * when it is not a URL or has nothing to remove.\n */\nexport function redactUrlString(\n value: string,\n options: UrlRedactionOptions,\n): UrlRedactionResult {\n const unchanged: UrlRedactionResult = {\n value,\n credentialRedacted: false,\n identifiersMasked: false,\n };\n if (!looksLikeHttpUrl(value)) return unchanged;\n\n const url = parseHttpUrl(value);\n if (!url) return unchanged;\n\n const replacement = options.replacement ?? \"[REDACTED]\";\n const idPlaceholder = options.idPlaceholder ?? \"[id]\";\n\n let credentialRedacted = url.username.length > 0 || url.password.length > 0;\n let identifiersMasked = false;\n\n let pathname = url.pathname;\n if (options.maskPathIds === true) {\n pathname = url.pathname\n .split(\"/\")\n .map((segment) => {\n if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {\n return segment;\n }\n identifiersMasked = true;\n return idPlaceholder;\n })\n .join(\"/\");\n }\n\n let search = \"\";\n if (url.search.length > 1) {\n const params = redactParams(url.search.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n search = `?${params.value}`;\n } else if (url.search.length === 1) {\n search = \"?\";\n }\n\n let hash = url.hash;\n if (url.hash.includes(\"=\")) {\n const params = redactParams(url.hash.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n hash = `#${params.value}`;\n }\n\n if (!credentialRedacted && !identifiersMasked) return unchanged;\n\n return {\n value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,\n credentialRedacted,\n identifiersMasked,\n };\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\nimport { looksLikeHttpUrl, redactUrlString } from \"./url-redaction.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule = (\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" }\n) & { raw?: string };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) =>\n isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key]),\n );\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key, raw: rule.raw ?? rule.key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #sensitiveKeys: readonly string[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #detect(\n value: string,\n key: string | undefined,\n path: string,\n ): { detector: RedactionDetector; detection: RedactionDetection } | undefined {\n for (const detector of this.#detectors) {\n for (const detection of detector.detect({ path, key, value })) {\n if ((detection.action ?? \"replace\") !== \"keep\") return { detector, detection };\n }\n }\n return undefined;\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n if (typeof value === \"string\" && looksLikeHttpUrl(value)) {\n const url = redactUrlString(value, {\n sensitiveKeys: this.#sensitiveKeys,\n isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== undefined,\n replacement: this.#replacement,\n maskPathIds: this.#profile !== \"local\",\n });\n if (url.value !== value) {\n this.#recordFinding(\n state,\n makeFinding(\n path,\n url.credentialRedacted ? \"value.urlCredential\" : \"value.urlIdentifier\",\n \"replace\",\n \"value\",\n url.credentialRedacted ? \"error\" : \"warning\",\n ),\n );\n const residual = this.#detect(\n url.value.split(this.#replacement).join(\"\"),\n key,\n path,\n );\n if (residual === undefined) return url.value;\n this.#recordFinding(\n state,\n makeFinding(\n path,\n residual.detector.id,\n \"replace\",\n residual.detection.matchKind ?? residual.detector.matchKind ?? \"custom\",\n residual.detection.severity ?? residual.detector.severity ?? \"warning\",\n ),\n );\n return this.#replacement;\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
1
+ {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.ts","../src/url-redaction.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Mirrors `packages/core/src/safety/sensitive-key.ts` for dependency-light\n * @agent-inspect/redact consumers. Keep both copies in sync (6.14.2 parity).\n */\n\n/** True when the original key already uses an explicit separator. */\nfunction keyHasExplicitSeparator(value: string): boolean {\n return /[_\\-.]/.test(value);\n}\n\n/**\n * Canonicalize field names so camelCase / kebab / dot / snake forms share a\n * snake_case shape the compound matcher can recognize (`userPassword` →\n * `user_password`).\n */\nexport function normalizeSensitiveKey(value: string): string {\n return value\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\");\n}\n\nexport const NON_CREDENTIAL_TOKEN_CONFIG_KEYS: ReadonlySet<string> = new Set(\n [\n \"tokens\",\n \"max_tokens\",\n \"min_tokens\",\n \"ls_max_tokens\",\n \"token_count\",\n \"token_limit\",\n \"token_budget\",\n \"input_tokens\",\n \"output_tokens\",\n \"total_tokens\",\n \"cached_tokens\",\n \"prompt_tokens\",\n \"completion_tokens\",\n ].map(normalizeSensitiveKey),\n);\n\nfunction isTokenCredentialKey(normalized: string): boolean {\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n if (normalized === \"token\") return true;\n if (normalized.endsWith(\"tokens\")) return false;\n return normalized.endsWith(\"token\");\n}\n\n/**\n * True when the field name looks credential-sensitive under the shared policy.\n *\n * Suffix compounds (`user_password`, `userPassword`) always match. Prefix\n * compounds (`email_note`) match only when the original key already contained\n * an explicit separator, so camelCase topic fields like `emailNote` stay for\n * value detectors instead of key redaction.\n */\nexport function isCredentialSensitiveKey(\n key: string | undefined,\n sensitiveKeys: readonly string[],\n): boolean {\n if (!key) return false;\n const normalized = normalizeSensitiveKey(key);\n if (!normalized) return false;\n if (NON_CREDENTIAL_TOKEN_CONFIG_KEYS.has(normalized)) return false;\n\n const allowPrefixCompound = keyHasExplicitSeparator(key);\n\n for (const sensitive of sensitiveKeys) {\n const s = normalizeSensitiveKey(sensitive);\n if (!s) continue;\n if (s === \"token\") {\n if (isTokenCredentialKey(normalized)) return true;\n continue;\n }\n if (normalized === s) return true;\n if (normalized.endsWith(`_${s}`)) return true;\n if (allowPrefixCompound && normalized.startsWith(`${s}_`)) return true;\n }\n return false;\n}\n","/**\n * High-confidence key/value credential forms shared with core\n * `safety.secretPattern` / `key-value-secret` (keep sources in sync).\n *\n * Matches house-format credentials such as:\n * internal_token=<credential>\n * token=<credential>\n * api_key=<credential>\n *\n * Intentionally does **not** match metric/config lookalikes such as\n * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are\n * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).\n * A marker used as a prefix (`[REDACTED]canary…`) or incomplete marker\n * (`[REDACTED]/canary…`) is still a secret. Query separators (`&`, `#`, `?`)\n * may end a complete placeholder when the same form appears in a URL query;\n * `/` and `;` do **not** — they are ordinary free-text characters.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=(?!\\[(?:REDACTED(?::[^\\]]*)?|HASH:[0-9a-f]{8})\\](?![^\\s\"'\\\\&#?]))([^\\s\"'\\\\]{8,})`;\n\nexport const KEY_VALUE_SECRET_PATTERN = new RegExp(\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n \"i\",\n);\n\nexport function valueContainsKeyValueSecret(value: string): boolean {\n KEY_VALUE_SECRET_PATTERN.lastIndex = 0;\n return KEY_VALUE_SECRET_PATTERN.test(value);\n}\n","/**\n * URL-aware redaction for http(s) and common connection-string schemes.\n *\n * Keeps scheme, host and path so two attempts of the same step stay\n * comparable, and removes credentials carried in userinfo, query params and\n * fragment params. Identifier-looking path segments are masked on http(s)\n * when the profile redacts identifiers. Connection URIs only strip userinfo\n * and sensitive params so database/queue paths stay intact.\n *\n * Mirrors `packages/core/src/safety/url-redaction.ts`. Keep both copies in sync.\n */\n\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\n\nexport interface UrlRedactionOptions {\n /** Field names the active profile redacts, used for query and fragment params. */\n sensitiveKeys: readonly string[];\n /** Value-level credential check, usually the profile's detectors. */\n isSensitiveValue: (value: string) => boolean;\n replacement?: string;\n /** Mask identifier-looking path segments (share and strict profiles, http(s) only). */\n maskPathIds?: boolean;\n idPlaceholder?: string;\n}\n\nexport interface UrlRedactionResult {\n value: string;\n credentialRedacted: boolean;\n identifiersMasked: boolean;\n}\n\nconst HTTP_URL = /^https?:\\/\\/[^\\s]+$/i;\n\n/** Connection schemes common in agent tool attributes (DB, cache, queue). */\nconst CONNECTION_PROTOCOLS = new Set([\n \"postgres:\",\n \"postgresql:\",\n \"mysql:\",\n \"mariadb:\",\n \"mongodb:\",\n \"mongodb+srv:\",\n \"redis:\",\n \"rediss:\",\n \"amqp:\",\n \"amqps:\",\n]);\n\nconst CONNECTION_URI =\n /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/[^\\s]+$/i;\n\n/**\n * Connection strings are not always WHATWG URLs (multihost + IP-literal\n * authorities). When `new URL` fails, strip a clear userinfo@ authority\n * prefix so credentials never survive as unchanged SAFE text.\n * @see https://github.com/mongodb/specifications/blob/master/source/connection-string/connection-string-spec.md#host-information\n */\nconst CONNECTION_USERINFO =\n /^(postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/([^@/?#]+)@(.+)$/i;\n\nconst CONNECTION_HAS_USERINFO =\n /^(?:postgres|postgresql|mysql|mariadb|mongodb(?:\\+srv)?|rediss?|amqps?):\\/\\/[^@/?#]+@/i;\n\n\nconst UUID_SEGMENT = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst HEX_SEGMENT = /^[0-9a-f]{12,}$/i;\nconst NUMERIC_SEGMENT = /^\\d{5,}$/;\nconst OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;\n\n/** True when the whole string is a single http(s) URL. */\nexport function looksLikeHttpUrl(value: string): boolean {\n return HTTP_URL.test(value.trim());\n}\n\n/** True when the whole string is a known connection URI with a scheme:// authority. */\nexport function looksLikeConnectionUri(value: string): boolean {\n return CONNECTION_URI.test(value.trim());\n}\n\n/** True when the value is eligible for URL-aware rewrite (http(s) or connection URI). */\nexport function looksLikeUrlForRedaction(value: string): boolean {\n return looksLikeHttpUrl(value) || looksLikeConnectionUri(value);\n}\n\nfunction parseRedactableUrl(value: string): URL | undefined {\n try {\n const url = new URL(value.trim());\n if (url.protocol === \"http:\" || url.protocol === \"https:\") return url;\n if (CONNECTION_PROTOCOLS.has(url.protocol)) return url;\n return undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Strip userinfo when the generic URL parser cannot handle a recognized\n * connection authority (e.g. comma-separated multihost lists).\n */\nfunction redactConnectionUserinfoFallback(\n value: string,\n replacement: string,\n): UrlRedactionResult | undefined {\n const trimmed = value.trim();\n const match = CONNECTION_USERINFO.exec(trimmed);\n if (match) {\n const [, scheme, , rest] = match;\n if (scheme && rest && rest.length > 0) {\n return {\n value: `${scheme}://${rest}`,\n credentialRedacted: true,\n identifiersMasked: false,\n };\n }\n }\n // Recognized scheme with userinfo that still cannot be rewritten safely:\n // withhold the whole value rather than leave credentials unchanged.\n if (looksLikeConnectionUri(trimmed) && CONNECTION_HAS_USERINFO.test(trimmed)) {\n return {\n value: replacement,\n credentialRedacted: true,\n identifiersMasked: false,\n };\n }\n return undefined;\n}\n\nfunction isHttpProtocol(protocol: string): boolean {\n return protocol === \"http:\" || protocol === \"https:\";\n}\n\nfunction isIdentifierSegment(segment: string): boolean {\n if (UUID_SEGMENT.test(segment)) return true;\n if (HEX_SEGMENT.test(segment)) return true;\n if (NUMERIC_SEGMENT.test(segment)) return true;\n return OPAQUE_SEGMENT.test(segment) && /\\d/.test(segment) && /[A-Za-z]/.test(segment);\n}\n\nfunction decodeParam(value: string): string {\n try {\n return decodeURIComponent(value.replace(/\\+/g, \" \"));\n } catch {\n return value;\n }\n}\n\nfunction redactParams(\n raw: string,\n options: UrlRedactionOptions,\n replacement: string,\n): { value: string; redacted: boolean } {\n let redacted = false;\n const parts = raw.split(\"&\").map((part) => {\n if (part.length === 0) return part;\n const separator = part.indexOf(\"=\");\n if (separator < 0) return part;\n const rawKey = part.slice(0, separator);\n const rawValue = part.slice(separator + 1);\n const key = decodeParam(rawKey);\n const value = decodeParam(rawValue);\n if (\n isCredentialSensitiveKey(key, options.sensitiveKeys) ||\n options.isSensitiveValue(value)\n ) {\n redacted = true;\n return `${rawKey}=${replacement}`;\n }\n return part;\n });\n return { value: parts.join(\"&\"), redacted };\n}\n\n/**\n * Redacts the sensitive parts of an http(s) or connection URI. Returns the\n * value unchanged when it is not a supported URL or has nothing to remove.\n */\nexport function redactUrlString(\n value: string,\n options: UrlRedactionOptions,\n): UrlRedactionResult {\n const unchanged: UrlRedactionResult = {\n value,\n credentialRedacted: false,\n identifiersMasked: false,\n };\n if (!looksLikeUrlForRedaction(value)) return unchanged;\n\n const replacement = options.replacement ?? \"[REDACTED]\";\n const url = parseRedactableUrl(value);\n if (!url) {\n return redactConnectionUserinfoFallback(value, replacement) ?? unchanged;\n }\n\n const idPlaceholder = options.idPlaceholder ?? \"[id]\";\n const http = isHttpProtocol(url.protocol);\n\n let credentialRedacted = url.username.length > 0 || url.password.length > 0;\n let identifiersMasked = false;\n\n let pathname = url.pathname;\n if (http && options.maskPathIds === true) {\n pathname = url.pathname\n .split(\"/\")\n .map((segment) => {\n if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {\n return segment;\n }\n identifiersMasked = true;\n return idPlaceholder;\n })\n .join(\"/\");\n }\n\n let search = \"\";\n if (url.search.length > 1) {\n const params = redactParams(url.search.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n search = `?${params.value}`;\n } else if (url.search.length === 1) {\n search = \"?\";\n }\n\n let hash = url.hash;\n if (url.hash.includes(\"=\")) {\n const params = redactParams(url.hash.slice(1), options, replacement);\n if (params.redacted) credentialRedacted = true;\n hash = `#${params.value}`;\n }\n\n if (!credentialRedacted && !identifiersMasked) return unchanged;\n\n return {\n value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,\n credentialRedacted,\n identifiersMasked,\n };\n}\n","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.js\";\nimport { looksLikeUrlForRedaction, redactUrlString } from \"./url-redaction.js\";\n\nexport type RedactionProfile = \"local\" | \"share\" | \"strict\";\n\nexport type RedactionAction = \"replace\" | \"hash\" | \"prefix\" | \"truncate\" | \"keep\";\n\nexport type RedactionSeverity = \"info\" | \"warning\" | \"error\";\n\nexport type RedactionMatchKind = \"key\" | \"value\" | \"custom\";\n\nexport type RedactionRule =\n | string\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep?: number }\n | { key: string; strategy: \"hash\" };\n\nexport interface RedactionFinding {\n path: string;\n detector: string;\n action: RedactionAction;\n severity: RedactionSeverity;\n matchKind: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetection {\n action?: RedactionAction;\n replacement?: unknown;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n preview?: string;\n}\n\nexport interface RedactionDetectorInput {\n path: string;\n key?: string;\n value: unknown;\n}\n\nexport interface RedactionDetector {\n id: string;\n severity?: RedactionSeverity;\n matchKind?: RedactionMatchKind;\n detect(input: RedactionDetectorInput): RedactionDetection[];\n}\n\nexport interface RedactionResult<T = unknown> {\n value: T;\n findings: RedactionFinding[];\n redacted: boolean;\n profile: RedactionProfile;\n}\n\nexport interface ResolvedRedactionProfile {\n profile: RedactionProfile;\n extraKeys: readonly string[];\n maxMetadataValueLengthCap?: number;\n maxPreviewLengthCap?: number;\n}\n\nexport interface RedactOptions {\n profile?: RedactionProfile;\n detectors?: RedactionDetector[];\n rules?: RedactionRule[];\n replacement?: string;\n maxDepth?: number;\n maxStringLength?: number;\n collectFindings?: boolean;\n}\n\nexport interface RedactorOptions extends RedactOptions {\n extraKeys?: readonly string[];\n}\n\nexport const DEFAULT_REDACT_KEYS = [\n \"authorization\",\n \"cookie\",\n \"token\",\n \"apiKey\",\n \"password\",\n \"secret\",\n \"email\",\n] as const;\n\nexport const SHARE_PROFILE_EXTRA_KEYS = [\n \"userEmail\",\n \"customerEmail\",\n \"phone\",\n \"phoneNumber\",\n \"address\",\n \"ip\",\n \"ipAddress\",\n \"sessionId\",\n \"requestId\",\n \"correlationId\",\n \"decisionId\",\n \"groupId\",\n \"customerId\",\n \"userId\",\n \"accountId\",\n \"tenantId\",\n \"orgId\",\n \"organizationId\",\n \"traceId\",\n \"spanId\",\n \"parentSpanId\",\n \"currentTask\",\n \"task\",\n \"userInput\",\n \"requestText\",\n \"conversationText\",\n] as const;\n\nexport const STRICT_PROFILE_EXTRA_KEYS = [\n \"prompt\",\n \"completion\",\n \"input\",\n \"output\",\n \"inputPreview\",\n \"outputPreview\",\n \"message\",\n \"messages\",\n \"transcript\",\n \"context\",\n \"document\",\n \"documents\",\n \"chunk\",\n \"chunks\",\n \"retrieval\",\n \"query\",\n] as const;\n\ntype CompiledRule = (\n | { key: string; strategy: \"full\" }\n | { key: string; strategy: \"prefix\"; keep: number }\n | { key: string; strategy: \"hash\" }\n) & { raw?: string };\n\ninterface RedactionState {\n findings: RedactionFinding[];\n seen: WeakMap<object, unknown>;\n}\n\ninterface PatternDetectorOptions {\n id: string;\n pattern: RegExp;\n severity?: RedactionSeverity;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n\nfunction toKey(key: string): string {\n return key.toLowerCase();\n}\n\nfunction findCompiledKeyRule(\n key: string,\n rules: readonly CompiledRule[],\n): CompiledRule | undefined {\n const exact = toKey(key);\n const direct = rules.find((candidate) => candidate.key === exact);\n if (direct) return direct;\n return rules.find((candidate) =>\n isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key]),\n );\n}\n\nfunction stableHash(value: string): string {\n const hash = crypto.createHash(\"sha256\").update(value, \"utf8\").digest(\"hex\");\n return hash.slice(0, 8);\n}\n\nfunction stringifyScalar(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\" || typeof value === \"bigint\") {\n return String(value);\n }\n return undefined;\n}\n\nfunction patternDetector(options: PatternDetectorOptions): RedactionDetector {\n return {\n id: options.id,\n severity: options.severity ?? \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n options.pattern.lastIndex = 0;\n return options.pattern.test(input.value)\n ? [{ action: \"replace\", severity: options.severity ?? \"warning\", matchKind: \"value\" }]\n : [];\n },\n };\n}\n\nfunction digitsOnly(value: string): string {\n return value.replace(/\\D/g, \"\");\n}\n\nfunction passesLuhn(value: string): boolean {\n const digits = digitsOnly(value);\n if (digits.length < 13 || digits.length > 19) return false;\n\n let sum = 0;\n let double = false;\n for (let i = digits.length - 1; i >= 0; i -= 1) {\n let digit = Number(digits[i]);\n if (double) {\n digit *= 2;\n if (digit > 9) digit -= 9;\n }\n sum += digit;\n double = !double;\n }\n return sum % 10 === 0;\n}\n\nconst UUID_RE =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n/** 13-digit Unix epoch milliseconds in a plausible modern range. */\nconst EPOCH_MS_RE = /^1[0-9]{12}$/;\n\nconst EMAIL_RE = /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi;\n\nfunction pathSuggestsNonCard(path: string): boolean {\n const normalized = path.toLowerCase().replace(/[^a-z0-9._]/g, \"\");\n return (\n /(^|\\.)(tokenusage|usage)(\\.|$)/.test(normalized) ||\n /(startedat|endedat|durationms|timestamp|createdat|updatedat)(\\.|$)/.test(normalized) ||\n /(^|\\.)(runid|traceid|spanid|eventid|sessionid|userid|parentid|requestid|correlationid)(\\.|$)/.test(\n normalized,\n ) ||\n /(^|\\.)ts(\\.|$)/.test(normalized)\n );\n}\n\nfunction isUuidLike(value: string): boolean {\n return UUID_RE.test(value.trim());\n}\n\nfunction isPlausibleCardCandidate(candidate: string, fullValue: string): boolean {\n const digits = digitsOnly(candidate);\n if (digits.length < 13 || digits.length > 19) return false;\n if (!passesLuhn(candidate)) return false;\n\n const trimmed = fullValue.trim();\n if (isUuidLike(trimmed)) return false;\n\n // Naked epoch-ms timestamps are not PANs.\n if (EPOCH_MS_RE.test(digits) && digitsOnly(trimmed) === digits && /^\\d+$/.test(trimmed)) {\n return false;\n }\n\n // Reject candidates glued inside longer alphanumeric IDs without card separators.\n const start = fullValue.indexOf(candidate);\n if (start >= 0) {\n const before = fullValue[start - 1];\n const after = fullValue[start + candidate.length];\n if (before && /[A-Za-z0-9_]/.test(before)) return false;\n if (after && /[A-Za-z0-9_]/.test(after)) return false;\n }\n\n return true;\n}\n\nfunction looksLikePathOrPackageOrUrl(value: string): boolean {\n const trimmed = value.trim();\n if (/^(?:[a-z][a-z0-9+.-]*:)?\\/\\//i.test(trimmed)) return true;\n if (/^webpack:/i.test(trimmed)) return true;\n if (/^@[A-Za-z0-9_.-]+\\/[A-Za-z0-9_.@/-]+$/.test(trimmed)) return true;\n if (/^[A-Za-z]:[\\\\/]/.test(trimmed) || /^[/\\\\]/.test(trimmed)) return true;\n // Path-like single token (slashes, no whitespace).\n if (/[\\\\/]/.test(trimmed) && !/\\s/.test(trimmed)) return true;\n return false;\n}\n\nfunction emailMatchIsPathAdjacent(value: string, index: number, length: number): boolean {\n const before = value[index - 1];\n const after = value[index + length];\n return before === \"/\" || before === \"\\\\\" || after === \"/\" || after === \"\\\\\";\n}\n\nfunction valueContainsEmail(value: string): boolean {\n if (looksLikePathOrPackageOrUrl(value)) return false;\n EMAIL_RE.lastIndex = 0;\n for (const match of value.matchAll(EMAIL_RE)) {\n const text = match[0] ?? \"\";\n const index = match.index ?? 0;\n if (emailMatchIsPathAdjacent(value, index, text.length)) continue;\n return true;\n }\n return false;\n}\n\nconst credentialDetectors: readonly RedactionDetector[] = [\n patternDetector({\n id: \"value.authorizationHeader\",\n pattern: /^(?:basic|bearer|digest|apikey)\\s+[a-z0-9._~+/=-]+$/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.bearerToken\",\n pattern: /\\bbearer\\s+[a-z0-9._~+/=-]{12,}\\b/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.cookie\",\n pattern: /\\b[a-z0-9_.-]+=[^;\\s]+(?:;\\s*[a-z0-9_.-]+=[^;\\s]+)+/i,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.jwt\",\n pattern: /\\beyJ[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\.[a-zA-Z0-9_-]{8,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.providerApiKey\",\n pattern: /\\b(?:sk-(?:proj-)?[a-zA-Z0-9_-]{16,}|sk-ant-[a-zA-Z0-9_-]{16,}|AIza[0-9A-Za-z_-]{20,})\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.githubToken\",\n pattern: /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{20,}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.awsAccessKey\",\n pattern: /\\b(?:AKIA|ASIA)[A-Z0-9]{16}\\b/,\n severity: \"error\",\n }),\n patternDetector({\n id: \"value.privateKey\",\n pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\\s\\S]*-----END [A-Z ]*PRIVATE KEY-----/,\n severity: \"error\",\n }),\n {\n id: \"value.keyValueSecret\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsKeyValueSecret(input.value)\n ? [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }]\n : [];\n },\n },\n {\n id: \"value.creditCard\",\n severity: \"error\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n if (pathSuggestsNonCard(input.path)) return [];\n if (isUuidLike(input.value)) return [];\n const candidatePattern = /(?:\\d[ -]?){13,19}/g;\n for (const match of input.value.matchAll(candidatePattern)) {\n const candidate = match[0] ?? \"\";\n if (isPlausibleCardCandidate(candidate, input.value)) {\n return [{ action: \"replace\", severity: \"error\", matchKind: \"value\" }];\n }\n }\n return [];\n },\n },\n];\n\nconst identifierDetectors: readonly RedactionDetector[] = [\n {\n id: \"value.email\",\n severity: \"warning\",\n matchKind: \"value\",\n detect(input) {\n if (typeof input.value !== \"string\") return [];\n return valueContainsEmail(input.value)\n ? [{ action: \"replace\", severity: \"warning\", matchKind: \"value\" }]\n : [];\n },\n },\n patternDetector({\n id: \"value.phone\",\n pattern: /\\b(?:\\+\\d{1,3}[\\s.-]?)?(?:\\(?\\d{3}\\)?[\\s.-])\\d{3}[\\s.-]\\d{4}\\b/,\n }),\n patternDetector({\n id: \"value.ipv4\",\n pattern: /\\b(?:(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|1?\\d?\\d)\\b/,\n }),\n patternDetector({\n id: \"value.ipv6\",\n pattern: /\\b(?:[0-9a-f]{1,4}:){2,7}[0-9a-f]{1,4}\\b/i,\n }),\n];\n\nfunction builtInDetectorsForProfile(profile: RedactionProfile): readonly RedactionDetector[] {\n if (profile === \"local\") return credentialDetectors;\n return [...credentialDetectors, ...identifierDetectors];\n}\n\nfunction compileRules(\n rules?: RedactionRule[],\n extraKeys?: readonly string[],\n): CompiledRule[] {\n const out = new Map<string, CompiledRule>();\n\n const set = (rule: CompiledRule) => {\n const key = toKey(rule.key);\n out.set(key, { ...rule, key, raw: rule.raw ?? rule.key } as CompiledRule);\n };\n\n for (const key of DEFAULT_REDACT_KEYS) {\n set({ key, strategy: \"full\" });\n }\n\n for (const key of extraKeys ?? []) {\n if (typeof key === \"string\" && key.length > 0) {\n set({ key, strategy: \"full\" });\n }\n }\n\n for (const rule of rules ?? []) {\n if (typeof rule === \"string\") {\n set({ key: rule, strategy: \"full\" });\n continue;\n }\n\n if (rule.strategy === \"full\") set({ key: rule.key, strategy: \"full\" });\n if (rule.strategy === \"hash\") set({ key: rule.key, strategy: \"hash\" });\n if (rule.strategy === \"prefix\") {\n set({\n key: rule.key,\n strategy: \"prefix\",\n keep: typeof rule.keep === \"number\" ? rule.keep : 8,\n });\n }\n }\n\n return [...out.values()];\n}\n\nfunction actionForRule(rule: CompiledRule): RedactionAction {\n if (rule.strategy === \"full\") return \"replace\";\n return rule.strategy;\n}\n\nfunction applyRule(\n rule: CompiledRule,\n value: unknown,\n replacement: string,\n): unknown {\n if (rule.strategy === \"full\") return replacement;\n\n const asString = stringifyScalar(value);\n if (rule.strategy === \"prefix\") {\n if (asString === undefined) return replacement;\n const keep = Math.max(0, Math.floor(rule.keep));\n return asString.length <= keep ? `${asString}…` : `${asString.slice(0, keep)}…`;\n }\n\n if (rule.strategy === \"hash\") {\n if (asString === undefined) return \"[HASH:unknown]\";\n return `[HASH:${stableHash(asString)}]`;\n }\n\n return value;\n}\n\nfunction childPath(path: string, key: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key)) {\n return path ? `${path}.${key}` : key;\n }\n return `${path || \"$\"}[${JSON.stringify(key)}]`;\n}\n\nfunction indexPath(path: string, index: number): string {\n return `${path || \"$\"}[${index}]`;\n}\n\nfunction makeFinding(\n path: string,\n detector: string,\n action: RedactionAction,\n matchKind: RedactionMatchKind,\n severity: RedactionSeverity = \"warning\",\n preview?: string,\n): RedactionFinding {\n return preview === undefined\n ? { path, detector, action, severity, matchKind }\n : { path, detector, action, severity, matchKind, preview };\n}\n\nexport function createRedactionProfile(profile: RedactionProfile = \"local\"): ResolvedRedactionProfile {\n switch (profile) {\n case \"local\":\n return { profile: \"local\", extraKeys: [] };\n case \"share\":\n return {\n profile: \"share\",\n extraKeys: SHARE_PROFILE_EXTRA_KEYS,\n maxMetadataValueLengthCap: 500,\n maxPreviewLengthCap: 200,\n };\n case \"strict\":\n return {\n profile: \"strict\",\n extraKeys: [...SHARE_PROFILE_EXTRA_KEYS, ...STRICT_PROFILE_EXTRA_KEYS],\n maxMetadataValueLengthCap: 200,\n maxPreviewLengthCap: 80,\n };\n }\n}\n\nexport class Redactor {\n readonly #rules: CompiledRule[];\n readonly #sensitiveKeys: readonly string[];\n readonly #detectors: readonly RedactionDetector[];\n readonly #profile: RedactionProfile;\n readonly #replacement: string;\n readonly #maxDepth: number;\n readonly #collectFindings: boolean;\n\n constructor(options?: RedactorOptions) {\n const resolved = createRedactionProfile(options?.profile ?? \"local\");\n this.#profile = resolved.profile;\n this.#rules = compileRules(options?.rules, [\n ...resolved.extraKeys,\n ...(options?.extraKeys ?? []),\n ]);\n this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);\n this.#detectors = [\n ...builtInDetectorsForProfile(this.#profile),\n ...(options?.detectors ?? []),\n ];\n this.#replacement = options?.replacement ?? \"[REDACTED]\";\n this.#maxDepth = options?.maxDepth ?? 32;\n this.#collectFindings = options?.collectFindings ?? true;\n }\n\n redactValue(key: string, value: unknown): unknown {\n return this.#redactValue(value, key, key, 0, {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n });\n }\n\n redactRecord(record: Record<string, unknown>): Record<string, unknown> {\n return this.redact(record).value as Record<string, unknown>;\n }\n\n redact<T = unknown>(value: T): RedactionResult<T> {\n const state: RedactionState = {\n findings: [],\n seen: new WeakMap<object, unknown>(),\n };\n const redacted = this.#redactValue(value, undefined, \"$\", 0, state);\n return {\n value: redacted as T,\n findings: state.findings,\n redacted: state.findings.some((finding) => finding.action !== \"keep\"),\n profile: this.#profile,\n };\n }\n\n #recordFinding(state: RedactionState, finding: RedactionFinding): void {\n if (this.#collectFindings) state.findings.push(finding);\n }\n\n #detect(\n value: string,\n key: string | undefined,\n path: string,\n ): { detector: RedactionDetector; detection: RedactionDetection } | undefined {\n for (const detector of this.#detectors) {\n for (const detection of detector.detect({ path, key, value })) {\n if ((detection.action ?? \"replace\") !== \"keep\") return { detector, detection };\n }\n }\n return undefined;\n }\n\n #redactValue(\n value: unknown,\n key: string | undefined,\n path: string,\n depth: number,\n state: RedactionState,\n ): unknown {\n if (depth > this.#maxDepth) {\n this.#recordFinding(\n state,\n makeFinding(path, \"structure.maxDepth\", \"truncate\", \"value\", \"warning\"),\n );\n return \"[Truncated]\";\n }\n\n if (key !== undefined) {\n const rule = findCompiledKeyRule(key, this.#rules);\n if (rule) {\n this.#recordFinding(\n state,\n makeFinding(path, `key.${rule.key}`, actionForRule(rule), \"key\", \"warning\"),\n );\n return applyRule(rule, value, this.#replacement);\n }\n }\n\n if (typeof value === \"string\" && looksLikeUrlForRedaction(value)) {\n const url = redactUrlString(value, {\n sensitiveKeys: this.#sensitiveKeys,\n isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== undefined,\n replacement: this.#replacement,\n maskPathIds: this.#profile !== \"local\",\n });\n if (url.value !== value) {\n this.#recordFinding(\n state,\n makeFinding(\n path,\n url.credentialRedacted ? \"value.urlCredential\" : \"value.urlIdentifier\",\n \"replace\",\n \"value\",\n url.credentialRedacted ? \"error\" : \"warning\",\n ),\n );\n const residual = this.#detect(\n url.value.split(this.#replacement).join(\"\"),\n key,\n path,\n );\n if (residual === undefined) return url.value;\n this.#recordFinding(\n state,\n makeFinding(\n path,\n residual.detector.id,\n \"replace\",\n residual.detection.matchKind ?? residual.detector.matchKind ?? \"custom\",\n residual.detection.severity ?? residual.detector.severity ?? \"warning\",\n ),\n );\n return this.#replacement;\n }\n }\n\n for (const detector of this.#detectors) {\n const detections = detector.detect({ path, key, value });\n for (const detection of detections) {\n const action = detection.action ?? \"replace\";\n this.#recordFinding(\n state,\n makeFinding(\n path,\n detector.id,\n action,\n detection.matchKind ?? detector.matchKind ?? \"custom\",\n detection.severity ?? detector.severity ?? \"warning\",\n detection.preview,\n ),\n );\n if (action !== \"keep\") {\n return detection.replacement ?? this.#replacement;\n }\n }\n }\n\n if (Array.isArray(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: unknown[] = [];\n state.seen.set(value, out);\n value.forEach((item, index) => {\n out[index] = this.#redactValue(item, undefined, indexPath(path, index), depth + 1, state);\n });\n return out;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) return state.seen.get(value);\n const out: Record<string, unknown> = {};\n state.seen.set(value, out);\n for (const [entryKey, entryValue] of Object.entries(value)) {\n out[entryKey] = this.#redactValue(\n entryValue,\n entryKey,\n childPath(path === \"$\" ? \"\" : path, entryKey),\n depth + 1,\n state,\n );\n }\n return out;\n }\n\n return value;\n }\n}\n\nexport function createRedactor(options?: RedactorOptions): Redactor {\n return new Redactor(options);\n}\n\nexport function redact<T = unknown>(value: T, options?: RedactOptions): RedactionResult<T> {\n return createRedactor(options).redact(value);\n}\n\nexport {\n KEY_VALUE_SECRET_PATTERN,\n KEY_VALUE_SECRET_PATTERN_SOURCE,\n valueContainsKeyValueSecret,\n} from \"./key-value-secret.js\";\n\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-inspect/redact",
3
- "version": "6.31.4",
3
+ "version": "6.31.6",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Reusable deterministic redaction utilities for local AgentInspect workflows",