From 8f9da3ed4ce297d9692e24a043383ed766e595bb Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Wed, 15 Jul 2026 13:52:46 -0700 Subject: [PATCH] fix(codex): restore trust config permissions on rollback --- .../codex/codex-trust-config-rollback.test.ts | 16 ++++++++++++++++ src/main/codex/codex-trust-config-rollback.ts | 13 ++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/codex/codex-trust-config-rollback.test.ts b/src/main/codex/codex-trust-config-rollback.test.ts index ae53cfaaadb..4d4658f3543 100644 --- a/src/main/codex/codex-trust-config-rollback.test.ts +++ b/src/main/codex/codex-trust-config-rollback.test.ts @@ -51,4 +51,20 @@ describe('Codex trust config rollback', () => { expect(statSync(configPath).mode & 0o777).toBe(0o640) } }) + + it.skipIf(process.platform === 'win32')( + 'restores the captured mode when the contents already match', + () => { + const configPath = tempConfigPath() + writeFileSync(configPath, '[hooks]\n') + chmodSync(configPath, 0o640) + const snapshot = captureCodexTrustConfig(configPath) + chmodSync(configPath, 0o600) + + restoreCodexTrustConfig(configPath, snapshot) + + expect(readFileSync(configPath, 'utf8')).toBe('[hooks]\n') + expect(statSync(configPath).mode & 0o777).toBe(0o640) + } + ) }) diff --git a/src/main/codex/codex-trust-config-rollback.ts b/src/main/codex/codex-trust-config-rollback.ts index 74cea0d425a..6ed05f3766d 100644 --- a/src/main/codex/codex-trust-config-rollback.ts +++ b/src/main/codex/codex-trust-config-rollback.ts @@ -1,4 +1,12 @@ -import { closeSync, fstatSync, openSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs' +import { + chmodSync, + closeSync, + fstatSync, + openSync, + readFileSync, + unlinkSync, + writeFileSync +} from 'node:fs' import { randomUUID } from 'node:crypto' import { renameFileWithWindowsRetry } from '../codex-accounts/fs-utils' @@ -45,6 +53,9 @@ export function restoreCodexTrustConfig( } try { if (readFileSync(tomlPath).equals(snapshot.contents)) { + // Why: the RPC may change permissions without changing bytes; rollback + // restores the complete captured file state, not only its contents. + chmodSync(tomlPath, snapshot.mode) return } } catch (error) {