From 8f8d1fcb52396c42329fe2aaf4ebeb2d8fdde319 Mon Sep 17 00:00:00 2001 From: orca-bug-scan-bot Date: Mon, 11 May 2026 12:09:22 -0700 Subject: [PATCH] fix: address pr-bug-scan validated finding from #1629 C1: readSystemDefaultSnapshot accepts legacy raw auth.json snapshots. C2: skip destructive system-default restore when Orca never materialized runtime credentials. --- .../claude-accounts/runtime-auth-service.ts | 7 +++++++ src/main/codex-accounts/runtime-home-service.ts | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/claude-accounts/runtime-auth-service.ts b/src/main/claude-accounts/runtime-auth-service.ts index 31c7e3104ce..c0c3e9b9852 100644 --- a/src/main/claude-accounts/runtime-auth-service.ts +++ b/src/main/claude-accounts/runtime-auth-service.ts @@ -525,6 +525,13 @@ export class ClaudeRuntimeAuthService { const snapshotPath = this.getSystemDefaultSnapshotPath() if (!existsSync(snapshotPath)) { + // Why: when Orca never materialized runtime credentials + // (lastWrittenCredentialsJson === null) and no snapshot exists, the + // user's system-default credentials are untouched. Deleting them here + // would log out the Claude CLI as a side-effect of a failed rollback. + if (this.lastWrittenCredentialsJson === null) { + return + } rmSync(this.pathResolver.getRuntimePaths().credentialsPath, { force: true }) if (process.platform === 'darwin') { await deleteActiveClaudeKeychainCredentials() diff --git a/src/main/codex-accounts/runtime-home-service.ts b/src/main/codex-accounts/runtime-home-service.ts index 21866294248..07be787e398 100644 --- a/src/main/codex-accounts/runtime-home-service.ts +++ b/src/main/codex-accounts/runtime-home-service.ts @@ -720,17 +720,30 @@ export class CodexRuntimeHomeService { } private readSystemDefaultSnapshot(snapshotPath: string): CodexSystemDefaultSnapshot | null { + let rawContents: string try { - const parsed = JSON.parse(readFileSync(snapshotPath, 'utf-8')) as unknown + rawContents = readFileSync(snapshotPath, 'utf-8') + } catch { + return null + } + try { + const parsed = JSON.parse(rawContents) as unknown if ( parsed && typeof parsed === 'object' && !Array.isArray(parsed) && 'authJson' in parsed && - (typeof parsed.authJson === 'string' || parsed.authJson === null) + (typeof (parsed as { authJson: unknown }).authJson === 'string' || + (parsed as { authJson: unknown }).authJson === null) ) { return parsed as CodexSystemDefaultSnapshot } + // Why: pre-PR snapshots wrote raw auth.json contents verbatim. Treat any + // valid JSON object without an authJson wrapper as the legacy format so + // upgraders do not lose their system-default auth on first deselect. + if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) { + return { authJson: rawContents } + } } catch { return null }