diff --git a/src/oauth/log.ts b/src/oauth/log.ts index 275530e19..2cd710d71 100644 --- a/src/oauth/log.ts +++ b/src/oauth/log.ts @@ -1,5 +1,6 @@ // src/oauth/log.ts import { maskAccountId } from "../lib/privacy"; +import { redactSecretString } from "../lib/redact"; /** Normalize camelCase / snake_case / kebab-case field names before secret checks. */ function normalizeFieldKey(key: string): string { @@ -20,6 +21,7 @@ const FORBIDDEN_NORMALIZED = new Set([ "id_token", "client_secret", "oauth_code", + "code_verifier", "clientsecret", ]); @@ -44,5 +46,5 @@ export function logOAuthEvent( if (value === undefined) continue; parts.push(`${key}=${String(value)}`); } - console.info(parts.join(" ")); + console.info(redactSecretString(parts.join(" "))); } diff --git a/tests/oauth-log.test.ts b/tests/oauth-log.test.ts index 8d88519e7..2bd673839 100644 --- a/tests/oauth-log.test.ts +++ b/tests/oauth-log.test.ts @@ -41,6 +41,7 @@ describe("logOAuthEvent", () => { id_token: "secret-id_token-value", client_secret: "secret-client_secret-value", oauth_code: "secret-oauth_code-value", + code_verifier: "secret-code_verifier-value", "client-secret": "secret-client-secret-value", safe: "visible", }); @@ -64,10 +65,31 @@ describe("logOAuthEvent", () => { "id_token", "client_secret", "oauth_code", + "code_verifier", "client-secret", ]) { expect(line).not.toContain(`${key}=`); } expect(line).not.toContain("secret-"); }); + + test("redacts token-shaped values under otherwise safe field keys", () => { + const lines: string[] = []; + const original = console.info; + console.info = (msg?: unknown) => { lines.push(String(msg)); }; + try { + logOAuthEvent("OAuth request failed", { + provider: "kiro", + diagnostic: "upstream returned Bearer credentialvalue123456", + request: "sk-fixturecredential", + status: 401, + }); + } finally { + console.info = original; + } + + expect(lines).toEqual([ + "[opencodex] OAuth request failed provider=kiro diagnostic=upstream returned Bearer [REDACTED] request=[REDACTED] status=401", + ]); + }); });