diff --git a/src/logging/diagnostic-support-export.test.ts b/src/logging/diagnostic-support-export.test.ts index e5dd9dc2c17..e664567b917 100644 --- a/src/logging/diagnostic-support-export.test.ts +++ b/src/logging/diagnostic-support-export.test.ts @@ -556,7 +556,7 @@ describe("diagnostic support export", () => { const cases = [ [ "connect wss://support-user:support-password@gateway.example/ws?token=short-token&ok=1", - "connect wss://:@gateway.example/ws?token=", + "connect wss://:@gateway.example/ws?token=&ok=1", ], [ "connect https://gateway.example/ws?access-token=short-token", diff --git a/src/logging/redact.test.ts b/src/logging/redact.test.ts index 0d50c1a1442..30ba0da0a8c 100644 --- a/src/logging/redact.test.ts +++ b/src/logging/redact.test.ts @@ -134,6 +134,24 @@ describe("redactSensitiveText", () => { expect(output).toBe(input); }); + it("masks sensitive URL query params while preserving non-sensitive params", () => { + const input = "GET /_matrix/client/v3/sync?access_token=abcdef1234567890ghij&since=123"; + const output = redactSensitiveText(input, { + mode: "tools", + patterns: defaults, + }); + expect(output).toBe("GET /_matrix/client/v3/sync?access_token=abcdef…ghij&since=123"); + }); + + it("treats sensitive URL query param names case-insensitively", () => { + const input = "connect https://gateway.example/ws?Access-Token=short-token&ok=1"; + const output = redactSensitiveText(input, { + mode: "tools", + patterns: defaults, + }); + expect(output).toBe("connect https://gateway.example/ws?Access-Token=***&ok=1"); + }); + it("redacts private key blocks", () => { const input = [ "-----BEGIN PRIVATE KEY-----", diff --git a/src/logging/redact.ts b/src/logging/redact.ts index cc13c2e2c9e..8dc8e303b7a 100644 --- a/src/logging/redact.ts +++ b/src/logging/redact.ts @@ -14,6 +14,9 @@ const DEFAULT_REDACT_PATTERNS: string[] = [ // ENV-style assignments. Keep this case-sensitive so diagnostics like // `Unrecognized key: "llm"` do not lose the actual config key. String.raw`/\b[A-Z0-9_]*(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD)\b\s*[=:]\s*(["']?)([^\s"'\\]+)\1/g`, + // URL query parameters. Keep this separate from ENV-style assignments so + // lower-case URL secrets stay redacted without hiding config-key diagnostics. + String.raw`/[?&](?:access[-_]?token|auth[-_]?token|hook[-_]?token|refresh[-_]?token|api[-_]?key|client[-_]?secret|token|key|secret|password|pass|passwd|auth|signature)=([^&\s"'<>]+)/gi`, // JSON fields. String.raw`"(?:apiKey|token|secret|password|passwd|accessToken|refreshToken)"\s*:\s*"([^"]+)"`, // CLI flags.