fix(cliproxy): redact token-like oauth trace snippets

This commit is contained in:
Kai (Tam Nhu) Tran
2026-05-22 11:11:06 -04:00
committed by Tam Nhu Tran
parent e7fed040ee
commit a526eb469a
4 changed files with 43 additions and 7 deletions
@@ -51,6 +51,25 @@ describe('redactString', () => {
test('empty input passthrough', () => {
expect(redactString('')).toBe('');
});
test('redacts JSON-style token payloads in plain strings', () => {
const out = redactString('{"access_token":"AT_SECRET","refresh_token":"RT_SECRET"}');
expect(out).not.toContain('AT_SECRET');
expect(out).not.toContain('RT_SECRET');
expect(out).toContain(REDACTED_PLACEHOLDER);
});
test('redacts line-leading key/value formats', () => {
const out = redactString(
'access_token=AT_SECRET refresh_token=RT_SECRET client_secret: CS_SECRET'
);
expect(out).not.toContain('AT_SECRET');
expect(out).not.toContain('RT_SECRET');
expect(out).not.toContain('CS_SECRET');
expect(out).toContain(`access_token=${REDACTED_PLACEHOLDER}`);
expect(out).toContain(`refresh_token=${REDACTED_PLACEHOLDER}`);
expect(out).toContain(`client_secret=${REDACTED_PLACEHOLDER}`);
});
});
describe('redactUrl', () => {
+20 -1
View File
@@ -40,12 +40,31 @@ const QUERY_PARAM_REGEX = new RegExp(
const BEARER_REGEX = /Bearer\s+[A-Za-z0-9._\-~+/=]+/gi;
const KV_SEPARATORS = String.raw`(?:=|:)`;
const VALUE_FRAGMENT = String.raw`[^\s,;\]}\"']+`;
const STRING_KV_KEYS = SENSITIVE_QUERY_KEYS.filter((key) => key !== 'authorization');
const SENSITIVE_KEY_GROUP = `(${STRING_KV_KEYS.join('|')})`;
const LEADING_KV_REGEX = new RegExp(
String.raw`(^|\s)${SENSITIVE_KEY_GROUP}\s*${KV_SEPARATORS}\s*${VALUE_FRAGMENT}`,
'gi'
);
const QUOTED_JSON_KV_REGEX = new RegExp(
String.raw`([\"'])${SENSITIVE_KEY_GROUP}\1\s*:\s*([\"'])[^\\]*?\3`,
'gi'
);
/** Redact sensitive query-param values inside any string. Idempotent. */
export function redactString(s: string): string {
if (!s) return s;
return s
.replace(QUERY_PARAM_REGEX, (_full, key) => `${key}=${REDACTED}`)
.replace(BEARER_REGEX, `Bearer ${REDACTED}`);
.replace(BEARER_REGEX, `Bearer ${REDACTED}`)
.replace(
QUOTED_JSON_KV_REGEX,
(_full, quoteKey, key, quoteVal) =>
`${quoteKey}${key}${quoteKey}:${quoteVal}${REDACTED}${quoteVal}`
)
.replace(LEADING_KV_REGEX, (_full, prefix, key) => `${prefix}${key}=${REDACTED}`);
}
/** Redact a parsed URL by name; returns redacted href or original on parse error. */
+2 -3
View File
@@ -524,9 +524,8 @@ export async function preflightCheck(provider: CLIProxyProvider): Promise<Prefli
return { proceed: true, accountId: defaultAccount?.id || '' };
}
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } = await import(
'../accounts/account-safety'
);
const { pauseAccountForQuotaCooldown, restoreExpiredQuotaPauses } =
await import('../accounts/account-safety');
restoreExpiredQuotaPauses();
const config = loadOrCreateUnifiedConfig();
@@ -112,9 +112,8 @@ export async function runImageAnalysisCheck(results: HealthCheck): Promise<void>
* Fix image analysis configuration issues
*/
export async function fixImageAnalysisConfig(): Promise<boolean> {
const { updateConfig, loadOrCreateUnifiedConfig } = await import(
'../../config/config-loader-facade'
);
const { updateConfig, loadOrCreateUnifiedConfig } =
await import('../../config/config-loader-facade');
const config = loadOrCreateUnifiedConfig();
let fixed = false;