@agent-inspect/redact 6.31.2 → 6.31.4

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/README.md CHANGED
@@ -39,6 +39,7 @@ console.log(result.value, result.findings);
39
39
  - Profiles: `local` · `share` · `strict`
40
40
  - Redaction is best-effort, not a safety certification — run `verify-safe` before sharing
41
41
  - High-confidence credentials (including bounded `token=` / `api_key=` / `internal_token=` forms) are covered by built-in profiles
42
+ - http(s) URLs keep scheme, host and path; userinfo and credential-looking query or fragment params are replaced, and identifier-like path segments become `[id]` under `share` and `strict`
42
43
  - Context-sensitive findings may still require review; CLI custom policies are not yet supported (use programmatic `detectors`)
43
44
  - `strict` adds more key rules; it does not guarantee different bytes from `share` on every input
44
45
 
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)=([^\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"
@@ -69,6 +69,99 @@ function valueContainsKeyValueSecret(value) {
69
69
  return KEY_VALUE_SECRET_PATTERN.test(value);
70
70
  }
71
71
 
72
+ // packages/redact/src/url-redaction.ts
73
+ var HTTP_URL = /^https?:\/\/[^\s]+$/i;
74
+ 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
+ var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
76
+ var NUMERIC_SEGMENT = /^\d{5,}$/;
77
+ var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
78
+ function looksLikeHttpUrl(value) {
79
+ return HTTP_URL.test(value.trim());
80
+ }
81
+ function parseHttpUrl(value) {
82
+ try {
83
+ const url = new URL(value.trim());
84
+ return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
85
+ } catch {
86
+ return void 0;
87
+ }
88
+ }
89
+ function isIdentifierSegment(segment) {
90
+ if (UUID_SEGMENT.test(segment)) return true;
91
+ if (HEX_SEGMENT.test(segment)) return true;
92
+ if (NUMERIC_SEGMENT.test(segment)) return true;
93
+ return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
94
+ }
95
+ function decodeParam(value) {
96
+ try {
97
+ return decodeURIComponent(value.replace(/\+/g, " "));
98
+ } catch {
99
+ return value;
100
+ }
101
+ }
102
+ function redactParams(raw, options, replacement) {
103
+ let redacted = false;
104
+ const parts = raw.split("&").map((part) => {
105
+ if (part.length === 0) return part;
106
+ const separator = part.indexOf("=");
107
+ if (separator < 0) return part;
108
+ const rawKey = part.slice(0, separator);
109
+ const rawValue = part.slice(separator + 1);
110
+ const key = decodeParam(rawKey);
111
+ const value = decodeParam(rawValue);
112
+ if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
113
+ redacted = true;
114
+ return `${rawKey}=${replacement}`;
115
+ }
116
+ return part;
117
+ });
118
+ return { value: parts.join("&"), redacted };
119
+ }
120
+ function redactUrlString(value, options) {
121
+ const unchanged = {
122
+ value,
123
+ credentialRedacted: false,
124
+ identifiersMasked: false
125
+ };
126
+ if (!looksLikeHttpUrl(value)) return unchanged;
127
+ const url = parseHttpUrl(value);
128
+ if (!url) return unchanged;
129
+ const replacement = options.replacement ?? "[REDACTED]";
130
+ const idPlaceholder = options.idPlaceholder ?? "[id]";
131
+ let credentialRedacted = url.username.length > 0 || url.password.length > 0;
132
+ let identifiersMasked = false;
133
+ let pathname = url.pathname;
134
+ if (options.maskPathIds === true) {
135
+ pathname = url.pathname.split("/").map((segment) => {
136
+ if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
137
+ return segment;
138
+ }
139
+ identifiersMasked = true;
140
+ return idPlaceholder;
141
+ }).join("/");
142
+ }
143
+ let search = "";
144
+ if (url.search.length > 1) {
145
+ const params = redactParams(url.search.slice(1), options, replacement);
146
+ if (params.redacted) credentialRedacted = true;
147
+ search = `?${params.value}`;
148
+ } else if (url.search.length === 1) {
149
+ search = "?";
150
+ }
151
+ let hash = url.hash;
152
+ if (url.hash.includes("=")) {
153
+ const params = redactParams(url.hash.slice(1), options, replacement);
154
+ if (params.redacted) credentialRedacted = true;
155
+ hash = `#${params.value}`;
156
+ }
157
+ if (!credentialRedacted && !identifiersMasked) return unchanged;
158
+ return {
159
+ value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
160
+ credentialRedacted,
161
+ identifiersMasked
162
+ };
163
+ }
164
+
72
165
  // packages/redact/src/index.ts
73
166
  var DEFAULT_REDACT_KEYS = [
74
167
  "authorization",
@@ -135,7 +228,9 @@ function findCompiledKeyRule(key, rules) {
135
228
  const exact = toKey(key);
136
229
  const direct = rules.find((candidate) => candidate.key === exact);
137
230
  if (direct) return direct;
138
- return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));
231
+ return rules.find(
232
+ (candidate) => isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key])
233
+ );
139
234
  }
140
235
  function stableHash(value) {
141
236
  const hash = crypto__default.default.createHash("sha256").update(value, "utf8").digest("hex");
@@ -334,7 +429,7 @@ function compileRules(rules, extraKeys) {
334
429
  const out = /* @__PURE__ */ new Map();
335
430
  const set = (rule) => {
336
431
  const key = toKey(rule.key);
337
- out.set(key, { ...rule, key });
432
+ out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
338
433
  };
339
434
  for (const key of DEFAULT_REDACT_KEYS) {
340
435
  set({ key, strategy: "full" });
@@ -413,6 +508,7 @@ function createRedactionProfile(profile = "local") {
413
508
  }
414
509
  var Redactor = class {
415
510
  #rules;
511
+ #sensitiveKeys;
416
512
  #detectors;
417
513
  #profile;
418
514
  #replacement;
@@ -425,6 +521,7 @@ var Redactor = class {
425
521
  ...resolved.extraKeys,
426
522
  ...options?.extraKeys ?? []
427
523
  ]);
524
+ this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
428
525
  this.#detectors = [
429
526
  ...builtInDetectorsForProfile(this.#profile),
430
527
  ...options?.detectors ?? []
@@ -458,6 +555,14 @@ var Redactor = class {
458
555
  #recordFinding(state, finding) {
459
556
  if (this.#collectFindings) state.findings.push(finding);
460
557
  }
558
+ #detect(value, key, path) {
559
+ for (const detector of this.#detectors) {
560
+ for (const detection of detector.detect({ path, key, value })) {
561
+ if ((detection.action ?? "replace") !== "keep") return { detector, detection };
562
+ }
563
+ }
564
+ return void 0;
565
+ }
461
566
  #redactValue(value, key, path, depth, state) {
462
567
  if (depth > this.#maxDepth) {
463
568
  this.#recordFinding(
@@ -476,6 +581,43 @@ var Redactor = class {
476
581
  return applyRule(rule, value, this.#replacement);
477
582
  }
478
583
  }
584
+ if (typeof value === "string" && looksLikeHttpUrl(value)) {
585
+ const url = redactUrlString(value, {
586
+ sensitiveKeys: this.#sensitiveKeys,
587
+ isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== void 0,
588
+ replacement: this.#replacement,
589
+ maskPathIds: this.#profile !== "local"
590
+ });
591
+ if (url.value !== value) {
592
+ this.#recordFinding(
593
+ state,
594
+ makeFinding(
595
+ path,
596
+ url.credentialRedacted ? "value.urlCredential" : "value.urlIdentifier",
597
+ "replace",
598
+ "value",
599
+ url.credentialRedacted ? "error" : "warning"
600
+ )
601
+ );
602
+ const residual = this.#detect(
603
+ url.value.split(this.#replacement).join(""),
604
+ key,
605
+ path
606
+ );
607
+ if (residual === void 0) return url.value;
608
+ this.#recordFinding(
609
+ state,
610
+ makeFinding(
611
+ path,
612
+ residual.detector.id,
613
+ "replace",
614
+ residual.detection.matchKind ?? residual.detector.matchKind ?? "custom",
615
+ residual.detection.severity ?? residual.detector.severity ?? "warning"
616
+ )
617
+ );
618
+ return this.#replacement;
619
+ }
620
+ }
479
621
  for (const detector of this.#detectors) {
480
622
  const detections = detector.detect({ path, key, value });
481
623
  for (const detection of detections) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.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, or short placeholders.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\\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","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.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\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) => isCredentialSensitiveKey(key, [candidate.key]));\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 } 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 #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.#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 #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 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…`) 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"]}
package/dist/index.d.cts CHANGED
@@ -8,7 +8,9 @@
8
8
  * api_key=<credential>
9
9
  *
10
10
  * Intentionally does **not** match metric/config lookalikes such as
11
- * maxTokens=, tokenCount=, secret=false, or short placeholders.
11
+ * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are
12
+ * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).
13
+ * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.
12
14
  */
13
15
  declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
14
16
  declare const KEY_VALUE_SECRET_PATTERN: RegExp;
package/dist/index.d.ts CHANGED
@@ -8,7 +8,9 @@
8
8
  * api_key=<credential>
9
9
  *
10
10
  * Intentionally does **not** match metric/config lookalikes such as
11
- * maxTokens=, tokenCount=, secret=false, or short placeholders.
11
+ * maxTokens=, tokenCount=, secret=false, short placeholders, or values that are
12
+ * *entirely* a redaction placeholder (`[REDACTED]`, `[REDACTED:…]`, `[HASH:xxxxxxxx]`).
13
+ * A marker used as a prefix (`[REDACTED]canary…`) is still a secret.
12
14
  */
13
15
  declare const KEY_VALUE_SECRET_PATTERN_SOURCE: string;
14
16
  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)=([^\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"
@@ -63,6 +63,99 @@ function valueContainsKeyValueSecret(value) {
63
63
  return KEY_VALUE_SECRET_PATTERN.test(value);
64
64
  }
65
65
 
66
+ // packages/redact/src/url-redaction.ts
67
+ var HTTP_URL = /^https?:\/\/[^\s]+$/i;
68
+ 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
+ var HEX_SEGMENT = /^[0-9a-f]{12,}$/i;
70
+ var NUMERIC_SEGMENT = /^\d{5,}$/;
71
+ var OPAQUE_SEGMENT = /^[A-Za-z0-9_-]{20,}$/;
72
+ function looksLikeHttpUrl(value) {
73
+ return HTTP_URL.test(value.trim());
74
+ }
75
+ function parseHttpUrl(value) {
76
+ try {
77
+ const url = new URL(value.trim());
78
+ return url.protocol === "http:" || url.protocol === "https:" ? url : void 0;
79
+ } catch {
80
+ return void 0;
81
+ }
82
+ }
83
+ function isIdentifierSegment(segment) {
84
+ if (UUID_SEGMENT.test(segment)) return true;
85
+ if (HEX_SEGMENT.test(segment)) return true;
86
+ if (NUMERIC_SEGMENT.test(segment)) return true;
87
+ return OPAQUE_SEGMENT.test(segment) && /\d/.test(segment) && /[A-Za-z]/.test(segment);
88
+ }
89
+ function decodeParam(value) {
90
+ try {
91
+ return decodeURIComponent(value.replace(/\+/g, " "));
92
+ } catch {
93
+ return value;
94
+ }
95
+ }
96
+ function redactParams(raw, options, replacement) {
97
+ let redacted = false;
98
+ const parts = raw.split("&").map((part) => {
99
+ if (part.length === 0) return part;
100
+ const separator = part.indexOf("=");
101
+ if (separator < 0) return part;
102
+ const rawKey = part.slice(0, separator);
103
+ const rawValue = part.slice(separator + 1);
104
+ const key = decodeParam(rawKey);
105
+ const value = decodeParam(rawValue);
106
+ if (isCredentialSensitiveKey(key, options.sensitiveKeys) || options.isSensitiveValue(value)) {
107
+ redacted = true;
108
+ return `${rawKey}=${replacement}`;
109
+ }
110
+ return part;
111
+ });
112
+ return { value: parts.join("&"), redacted };
113
+ }
114
+ function redactUrlString(value, options) {
115
+ const unchanged = {
116
+ value,
117
+ credentialRedacted: false,
118
+ identifiersMasked: false
119
+ };
120
+ if (!looksLikeHttpUrl(value)) return unchanged;
121
+ const url = parseHttpUrl(value);
122
+ if (!url) return unchanged;
123
+ const replacement = options.replacement ?? "[REDACTED]";
124
+ const idPlaceholder = options.idPlaceholder ?? "[id]";
125
+ let credentialRedacted = url.username.length > 0 || url.password.length > 0;
126
+ let identifiersMasked = false;
127
+ let pathname = url.pathname;
128
+ if (options.maskPathIds === true) {
129
+ pathname = url.pathname.split("/").map((segment) => {
130
+ if (segment.length === 0 || !isIdentifierSegment(decodeParam(segment))) {
131
+ return segment;
132
+ }
133
+ identifiersMasked = true;
134
+ return idPlaceholder;
135
+ }).join("/");
136
+ }
137
+ let search = "";
138
+ if (url.search.length > 1) {
139
+ const params = redactParams(url.search.slice(1), options, replacement);
140
+ if (params.redacted) credentialRedacted = true;
141
+ search = `?${params.value}`;
142
+ } else if (url.search.length === 1) {
143
+ search = "?";
144
+ }
145
+ let hash = url.hash;
146
+ if (url.hash.includes("=")) {
147
+ const params = redactParams(url.hash.slice(1), options, replacement);
148
+ if (params.redacted) credentialRedacted = true;
149
+ hash = `#${params.value}`;
150
+ }
151
+ if (!credentialRedacted && !identifiersMasked) return unchanged;
152
+ return {
153
+ value: `${url.protocol}//${url.host}${pathname}${search}${hash}`,
154
+ credentialRedacted,
155
+ identifiersMasked
156
+ };
157
+ }
158
+
66
159
  // packages/redact/src/index.ts
67
160
  var DEFAULT_REDACT_KEYS = [
68
161
  "authorization",
@@ -129,7 +222,9 @@ function findCompiledKeyRule(key, rules) {
129
222
  const exact = toKey(key);
130
223
  const direct = rules.find((candidate) => candidate.key === exact);
131
224
  if (direct) return direct;
132
- return rules.find((candidate) => isCredentialSensitiveKey(key, [candidate.key]));
225
+ return rules.find(
226
+ (candidate) => isCredentialSensitiveKey(key, [candidate.raw ?? candidate.key])
227
+ );
133
228
  }
134
229
  function stableHash(value) {
135
230
  const hash = crypto.createHash("sha256").update(value, "utf8").digest("hex");
@@ -328,7 +423,7 @@ function compileRules(rules, extraKeys) {
328
423
  const out = /* @__PURE__ */ new Map();
329
424
  const set = (rule) => {
330
425
  const key = toKey(rule.key);
331
- out.set(key, { ...rule, key });
426
+ out.set(key, { ...rule, key, raw: rule.raw ?? rule.key });
332
427
  };
333
428
  for (const key of DEFAULT_REDACT_KEYS) {
334
429
  set({ key, strategy: "full" });
@@ -407,6 +502,7 @@ function createRedactionProfile(profile = "local") {
407
502
  }
408
503
  var Redactor = class {
409
504
  #rules;
505
+ #sensitiveKeys;
410
506
  #detectors;
411
507
  #profile;
412
508
  #replacement;
@@ -419,6 +515,7 @@ var Redactor = class {
419
515
  ...resolved.extraKeys,
420
516
  ...options?.extraKeys ?? []
421
517
  ]);
518
+ this.#sensitiveKeys = this.#rules.map((rule) => rule.raw ?? rule.key);
422
519
  this.#detectors = [
423
520
  ...builtInDetectorsForProfile(this.#profile),
424
521
  ...options?.detectors ?? []
@@ -452,6 +549,14 @@ var Redactor = class {
452
549
  #recordFinding(state, finding) {
453
550
  if (this.#collectFindings) state.findings.push(finding);
454
551
  }
552
+ #detect(value, key, path) {
553
+ for (const detector of this.#detectors) {
554
+ for (const detection of detector.detect({ path, key, value })) {
555
+ if ((detection.action ?? "replace") !== "keep") return { detector, detection };
556
+ }
557
+ }
558
+ return void 0;
559
+ }
455
560
  #redactValue(value, key, path, depth, state) {
456
561
  if (depth > this.#maxDepth) {
457
562
  this.#recordFinding(
@@ -470,6 +575,43 @@ var Redactor = class {
470
575
  return applyRule(rule, value, this.#replacement);
471
576
  }
472
577
  }
578
+ if (typeof value === "string" && looksLikeHttpUrl(value)) {
579
+ const url = redactUrlString(value, {
580
+ sensitiveKeys: this.#sensitiveKeys,
581
+ isSensitiveValue: (candidate) => this.#detect(candidate, key, path) !== void 0,
582
+ replacement: this.#replacement,
583
+ maskPathIds: this.#profile !== "local"
584
+ });
585
+ if (url.value !== value) {
586
+ this.#recordFinding(
587
+ state,
588
+ makeFinding(
589
+ path,
590
+ url.credentialRedacted ? "value.urlCredential" : "value.urlIdentifier",
591
+ "replace",
592
+ "value",
593
+ url.credentialRedacted ? "error" : "warning"
594
+ )
595
+ );
596
+ const residual = this.#detect(
597
+ url.value.split(this.#replacement).join(""),
598
+ key,
599
+ path
600
+ );
601
+ if (residual === void 0) return url.value;
602
+ this.#recordFinding(
603
+ state,
604
+ makeFinding(
605
+ path,
606
+ residual.detector.id,
607
+ "replace",
608
+ residual.detection.matchKind ?? residual.detector.matchKind ?? "custom",
609
+ residual.detection.severity ?? residual.detector.severity ?? "warning"
610
+ )
611
+ );
612
+ return this.#replacement;
613
+ }
614
+ }
473
615
  for (const detector of this.#detectors) {
474
616
  const detections = detector.detect({ path, key, value });
475
617
  for (const detection of detections) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/sensitive-key.ts","../src/key-value-secret.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, or short placeholders.\n */\nexport const KEY_VALUE_SECRET_PATTERN_SOURCE =\n String.raw`\\b(?:api[_-]?key|internal[_-]?token|access[_-]?token|auth[_-]?token|password|secret|token)=([^\\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","import crypto from \"node:crypto\";\nimport { isCredentialSensitiveKey } from \"./sensitive-key.js\";\nimport { valueContainsKeyValueSecret } from \"./key-value-secret.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\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) => isCredentialSensitiveKey(key, [candidate.key]));\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 } 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 #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.#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 #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 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…`) 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-inspect/redact",
3
- "version": "6.31.2",
3
+ "version": "6.31.4",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "description": "Reusable deterministic redaction utilities for local AgentInspect workflows",