From 86734ef93a2f25063371b04f1946eb300548acd4 Mon Sep 17 00:00:00 2001 From: Pavan Kumar Gondhi Date: Mon, 13 Apr 2026 23:47:31 +0530 Subject: [PATCH] fix(config): redact sourceConfig and runtimeConfig alias fields in redactConfigSnapshot [AI] (#66030) * fix: address issue * docs: add changelog entry for PR merge --- CHANGELOG.md | 1 + src/config/redact-snapshot.test.ts | 16 ++++++++++++++++ src/config/redact-snapshot.ts | 10 ++++++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0e271da3e0..fa660242e22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai ### Fixes +- fix(config): redact sourceConfig and runtimeConfig alias fields in redactConfigSnapshot [AI]. (#66030) Thanks @pgondhi987. - Agents/context engines: run opt-in turn maintenance as idle-aware background work so the next foreground turn no longer waits on proactive maintenance. (#65233) thanks @100yenadmin - Plugins/status: report the registered context-engine IDs in `plugins inspect` instead of the owning plugin ID, so non-matching engine IDs and multi-engine plugins are classified correctly. (#58766) thanks @zhuisDEV diff --git a/src/config/redact-snapshot.test.ts b/src/config/redact-snapshot.test.ts index 0205add7190..60cb7e9e4ef 100644 --- a/src/config/redact-snapshot.test.ts +++ b/src/config/redact-snapshot.test.ts @@ -565,9 +565,21 @@ describe("redactConfigSnapshot", () => { }); const result = redactConfigSnapshot(snapshot); const parsed = result.parsed as Record>>; + const sourceConfig = result.sourceConfig as Record< + string, + Record> + >; const resolved = result.resolved as Record>>; + const runtimeConfig = result.runtimeConfig as Record< + string, + Record> + >; expect(parsed.channels.discord.token).toBe(REDACTED_SENTINEL); + expect(sourceConfig.gateway.auth.token).toBe(REDACTED_SENTINEL); expect(resolved.gateway.auth.token).toBe(REDACTED_SENTINEL); + expect(runtimeConfig.channels.discord.token).toBe(REDACTED_SENTINEL); + expect(result.sourceConfig).toBe(result.resolved); + expect(result.runtimeConfig).toBe(result.config); }); it("handles null raw gracefully", () => { @@ -610,7 +622,11 @@ describe("redactConfigSnapshot", () => { const result = redactConfigSnapshot(snapshot); expect(result.raw).toBeNull(); expect(result.parsed).toBeNull(); + expect(result.sourceConfig).toEqual({}); expect(result.resolved).toEqual({}); + expect(result.runtimeConfig).toEqual({}); + expect(result.sourceConfig).toBe(result.resolved); + expect(result.runtimeConfig).toBe(result.config); }); it("handles deeply nested tokens in accounts", () => { diff --git a/src/config/redact-snapshot.ts b/src/config/redact-snapshot.ts index 0fdfca5af5c..8bafcb93455 100644 --- a/src/config/redact-snapshot.ts +++ b/src/config/redact-snapshot.ts @@ -423,12 +423,16 @@ export function redactConfigSnapshot( // properly redacted all sensitive data. Handing out a partially or, worse, // unredacted config string would be bad. // Therefore, the only safe route is to reject handling out broken configs. + const redactedConfig = {} as ConfigFileSnapshot["config"]; + const redactedResolved = {} as ConfigFileSnapshot["resolved"]; return { ...snapshot, - config: {}, + sourceConfig: redactedResolved, + runtimeConfig: redactedConfig, + config: redactedConfig, raw: null, parsed: null, - resolved: {}, + resolved: redactedResolved, }; } // else: snapshot.config must be valid and populated, as that is what @@ -455,6 +459,8 @@ export function redactConfigSnapshot( return { ...snapshot, + sourceConfig: redactedResolved, + runtimeConfig: redactedConfig, config: redactedConfig, raw: redactedRaw, parsed: redactedParsed,