From efb42ba8f6adfa5128c4974d43140fd640b826a1 Mon Sep 17 00:00:00 2001 From: kaitranntt Date: Mon, 8 Dec 2025 16:32:08 -0500 Subject: [PATCH] fix(security): improve API key detection patterns to prevent false positives - Change from substring to pattern-based matching for sensitive keys - Prevents ANTHROPIC_MAX_TOKENS from being incorrectly censored - Synchronize backend and UI detection logic for consistency --- src/web-server/routes.ts | 11 +++++++++-- ui/src/components/settings-dialog.tsx | 12 +++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/web-server/routes.ts b/src/web-server/routes.ts index 36e682b3..5b48c420 100644 --- a/src/web-server/routes.ts +++ b/src/web-server/routes.ts @@ -478,10 +478,17 @@ function maskApiKeys(settings: Settings): Settings { if (!settings.env) return settings; const masked = { ...settings, env: { ...settings.env } }; - const sensitiveKeys = ['ANTHROPIC_AUTH_TOKEN', 'API_KEY', 'AUTH_TOKEN']; + // Pattern-based matching for sensitive keys + const sensitivePatterns = [ + /^ANTHROPIC_AUTH_TOKEN$/, // Exact match for Anthropic auth token + /_API_KEY$/, // Keys ending with _API_KEY + /_AUTH_TOKEN$/, // Keys ending with _AUTH_TOKEN + /^API_KEY$/, // Exact match for API_KEY + /^AUTH_TOKEN$/, // Exact match for AUTH_TOKEN + ]; for (const key of Object.keys(masked.env)) { - if (sensitiveKeys.some((sensitive) => key.includes(sensitive))) { + if (sensitivePatterns.some((pattern) => pattern.test(key))) { const value = masked.env[key]; if (value && value.length > 8) { masked.env[key] = diff --git a/ui/src/components/settings-dialog.tsx b/ui/src/components/settings-dialog.tsx index 1e87683c..d4b0f3b9 100644 --- a/ui/src/components/settings-dialog.tsx +++ b/ui/src/components/settings-dialog.tsx @@ -145,7 +145,17 @@ function SettingsDialogContent({ }; const isSensitiveKey = (key: string): boolean => { - return key.includes('TOKEN') || key.includes('KEY') || key.includes('SECRET'); + // Pattern-based matching for sensitive keys (same as backend) + const sensitivePatterns = [ + /^ANTHROPIC_AUTH_TOKEN$/, // Exact match for Anthropic auth token + /_API_KEY$/, // Keys ending with _API_KEY + /_AUTH_TOKEN$/, // Keys ending with _AUTH_TOKEN + /^API_KEY$/, // Exact match for API_KEY + /^AUTH_TOKEN$/, // Exact match for AUTH_TOKEN + /_SECRET$/, // Keys ending with _SECRET + /^SECRET$/, // Exact match for SECRET + ]; + return sensitivePatterns.some((pattern) => pattern.test(key)); }; return (