From a1c88f3ebe9bba07c7214286e96f780cb2fd6089 Mon Sep 17 00:00:00 2001 From: pashpashpash Date: Mon, 27 Apr 2026 18:55:37 -0400 Subject: [PATCH] fix(codex): hash app-server env values in client keys --- .../codex/src/app-server/config.test.ts | 21 +++++++++++++++++++ extensions/codex/src/app-server/config.ts | 4 +++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/extensions/codex/src/app-server/config.test.ts b/extensions/codex/src/app-server/config.test.ts index aade1d88c88..1fc858cec55 100644 --- a/extensions/codex/src/app-server/config.test.ts +++ b/extensions/codex/src/app-server/config.test.ts @@ -302,6 +302,27 @@ describe("Codex app-server config", () => { expect(second).not.toContain("tok_second"); }); + it("derives distinct shared-client keys for distinct env values without exposing them", () => { + const first = codexAppServerStartOptionsKey({ + transport: "stdio", + command: "codex", + args: ["app-server"], + headers: {}, + env: { OPENAI_API_KEY: "sk-first" }, + }); + const second = codexAppServerStartOptionsKey({ + transport: "stdio", + command: "codex", + args: ["app-server"], + headers: {}, + env: { OPENAI_API_KEY: "sk-second" }, + }); + + expect(first).not.toEqual(second); + expect(first).not.toContain("sk-first"); + expect(second).not.toContain("sk-second"); + }); + it("keeps runtime config keys aligned with manifest schema and UI hints", async () => { const manifest = JSON.parse( await fs.readFile(new URL("../../openclaw.plugin.json", import.meta.url), "utf8"), diff --git a/extensions/codex/src/app-server/config.ts b/extensions/codex/src/app-server/config.ts index 2f643d66720..cd4c002c1f4 100644 --- a/extensions/codex/src/app-server/config.ts +++ b/extensions/codex/src/app-server/config.ts @@ -304,7 +304,9 @@ export function codexAppServerStartOptionsKey( headers: Object.entries(options.headers).toSorted(([left], [right]) => left.localeCompare(right), ), - env: Object.entries(options.env ?? {}).toSorted(([left], [right]) => left.localeCompare(right)), + env: Object.entries(options.env ?? {}) + .toSorted(([left], [right]) => left.localeCompare(right)) + .map(([key, value]) => [key, hashSecretForKey(value)]), clearEnv: [...(options.clearEnv ?? [])].toSorted(), authProfileId: params.authProfileId ?? null, });