From 442099d9b2e9fc69fb4f09cd03481badbf652398 Mon Sep 17 00:00:00 2001 From: lin-hongkuan Date: Tue, 30 Jun 2026 02:15:55 +0800 Subject: [PATCH] fix(auth): strip controls from masked API keys (#96445) * fix(auth): strip controls from masked API keys * test(auth): cover DEL and C1 masked key controls * chore: retrigger PR checks --------- Co-authored-by: lin-hongkuan (cherry picked from commit 2906d6c38f12f64c842b5c36572685041b8bbd39) --- src/utils/mask-api-key.test.ts | 7 +++++++ src/utils/mask-api-key.ts | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/utils/mask-api-key.test.ts b/src/utils/mask-api-key.test.ts index 6d0a35d331bc..5ea859f7d2ef 100644 --- a/src/utils/mask-api-key.test.ts +++ b/src/utils/mask-api-key.test.ts @@ -18,4 +18,11 @@ describe("maskApiKey", () => { it("masks long values with first and last 8 chars", () => { expect(maskApiKey("1234567890abcdefghijklmnop")).toBe("12345678...ijklmnop"); // pragma: allowlist secret }); + + it("strips control characters before masking diagnostic output", () => { + expect(maskApiKey("abcd\nefghijklmnop")).toBe("ab...op"); + expect(maskApiKey("abcd\u0000efghijklmnop")).toBe("ab...op"); + expect(maskApiKey("abcd\u007f\u0085efghijklmnop")).toBe("ab...op"); + expect(maskApiKey("\u0000\n")).toBe("missing"); + }); }); diff --git a/src/utils/mask-api-key.ts b/src/utils/mask-api-key.ts index 69ff0e201d43..b3e495f62b72 100644 --- a/src/utils/mask-api-key.ts +++ b/src/utils/mask-api-key.ts @@ -1,6 +1,6 @@ /** Masks credential-like values for diagnostics while preserving enough prefix/suffix to identify them. */ export const maskApiKey = (value: string): string => { - const trimmed = value.trim(); + const trimmed = stripControlCharacters(value).trim(); if (!trimmed) { return "missing"; } @@ -12,3 +12,15 @@ export const maskApiKey = (value: string): string => { } return `${trimmed.slice(0, 8)}...${trimmed.slice(-8)}`; }; + +function stripControlCharacters(value: string): string { + let out = ""; + for (const char of value) { + const code = char.charCodeAt(0); + const isControl = (code >= 0x00 && code <= 0x1f) || (code >= 0x7f && code <= 0x9f); + if (!isControl) { + out += char; + } + } + return out; +}