From 516ca693fc1d934b13d1b1ff4cdcd72cc0b99594 Mon Sep 17 00:00:00 2001 From: Altay Date: Mon, 9 Mar 2026 23:20:30 +0300 Subject: [PATCH] Agents: sanitize auth profile console logs --- .../auth-profiles/state-observation.test.ts | 38 +++++++++++++++++++ src/agents/auth-profiles/state-observation.ts | 5 ++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 src/agents/auth-profiles/state-observation.test.ts diff --git a/src/agents/auth-profiles/state-observation.test.ts b/src/agents/auth-profiles/state-observation.test.ts new file mode 100644 index 00000000000..05f2abfff19 --- /dev/null +++ b/src/agents/auth-profiles/state-observation.test.ts @@ -0,0 +1,38 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { resetLogger, setLoggerOverride } from "../../logging/logger.js"; +import { logAuthProfileFailureStateChange } from "./state-observation.js"; + +afterEach(() => { + setLoggerOverride(null); + resetLogger(); +}); + +describe("logAuthProfileFailureStateChange", () => { + it("sanitizes consoleMessage fields before logging", () => { + const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {}); + setLoggerOverride({ level: "silent", consoleLevel: "warn" }); + + logAuthProfileFailureStateChange({ + runId: "run-1\nforged\tentry\rtest", + profileId: "openai:profile-1", + provider: "openai\u001b]8;;https://evil.test\u0007", + reason: "overloaded", + previous: undefined, + next: { + errorCount: 1, + cooldownUntil: 1_700_000_060_000, + failureCounts: { overloaded: 1 }, + }, + now: 1_700_000_000_000, + }); + + const consoleLine = warnSpy.mock.calls[0]?.[0]; + expect(typeof consoleLine).toBe("string"); + expect(consoleLine).toContain("runId=run-1 forged entry test"); + expect(consoleLine).toContain("provider=openai]8;;https://evil.test"); + expect(consoleLine).not.toContain("\n"); + expect(consoleLine).not.toContain("\r"); + expect(consoleLine).not.toContain("\t"); + expect(consoleLine).not.toContain("\u001b"); + }); +}); diff --git a/src/agents/auth-profiles/state-observation.ts b/src/agents/auth-profiles/state-observation.ts index 04cd19047e8..633bdc0031b 100644 --- a/src/agents/auth-profiles/state-observation.ts +++ b/src/agents/auth-profiles/state-observation.ts @@ -1,5 +1,6 @@ import { redactIdentifier } from "../../logging/redact-identifier.js"; import { createSubsystemLogger } from "../../logging/subsystem.js"; +import { sanitizeForConsole } from "../pi-embedded-error-observation.js"; import type { AuthProfileFailureReason, ProfileUsageStats } from "./types.js"; const observationLog = createSubsystemLogger("agent/embedded"); @@ -30,6 +31,8 @@ export function logAuthProfileFailureStateChange(params: { previousCooldownUntil > params.now && previousCooldownUntil === params.next.cooldownUntil; const safeProfileId = redactIdentifier(params.profileId, { len: 12 }); + const safeRunId = sanitizeForConsole(params.runId) ?? "-"; + const safeProvider = sanitizeForConsole(params.provider) ?? "-"; observationLog.warn("auth profile failure state updated", { event: "auth_profile_failure_state_updated", @@ -50,7 +53,7 @@ export function logAuthProfileFailureStateChange(params: { disabledReason: params.next.disabledReason, failureCounts: params.next.failureCounts, consoleMessage: - `auth profile failure state updated: runId=${params.runId ?? "-"} profile=${safeProfileId} provider=${params.provider} ` + + `auth profile failure state updated: runId=${safeRunId} profile=${safeProfileId} provider=${safeProvider} ` + `reason=${params.reason} window=${windowType} reused=${String(windowReused)}`, }); }