From 888b96441cb899ce1b7b9eb734832cafadd9de54 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:22:01 +0000 Subject: [PATCH 1/4] Initial plan From 02b1b8418ffa6f63534b5e3dde9b2d3d6a109a53 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:25:17 +0000 Subject: [PATCH 2/4] Fix command injection vulnerability: use spawnSync with env var for tmpFile Co-authored-by: seabearDEV <40605056+seabearDEV@users.noreply.github.com> --- src/commands/entries.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/commands/entries.ts b/src/commands/entries.ts index dcb40b5..b43fbef 100644 --- a/src/commands/entries.ts +++ b/src/commands/entries.ts @@ -4,7 +4,7 @@ import { flattenObject } from '../utils/objectPath'; import { CodexValue } from '../types'; import { displayTree } from '../formatting'; import { color } from '../formatting'; -import { execSync } from 'child_process'; +import { execSync, spawnSync } from 'child_process'; import { ensureDataDirectoryExists } from '../utils/paths'; import { buildKeyToAliasMap, setAlias, removeAliasesForKey, loadAliases, resolveKey, renameAlias, removeAlias } from '../alias'; import { hasConfirm, setConfirm, removeConfirm, removeConfirmForKey } from '../confirm'; @@ -449,7 +449,11 @@ export async function editEntry(key: string, options: { decrypt?: boolean } = {} fsModule.writeFileSync(tmpFile, value, { encoding: 'utf8', mode: 0o600 }); try { - execSync(`${editor} ${tmpFile}`, { stdio: 'inherit' }); + const result = spawnSync('sh', ['-c', `${editor} "$CODEX_TMPFILE"`], { + stdio: 'inherit', + env: { ...process.env, CODEX_TMPFILE: tmpFile }, + }); + if (result.error) throw result.error; const newValue = fsModule.readFileSync(tmpFile, 'utf8'); if (newValue === value) { From 812570ced90e1e39aabcbd022e33002a87fe6889 Mon Sep 17 00:00:00 2001 From: Kory Hoopes Date: Sat, 21 Feb 2026 13:38:48 -0700 Subject: [PATCH 3/4] Update src/commands/entries.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/commands/entries.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/commands/entries.ts b/src/commands/entries.ts index b43fbef..7d08859 100644 --- a/src/commands/entries.ts +++ b/src/commands/entries.ts @@ -454,6 +454,9 @@ export async function editEntry(key: string, options: { decrypt?: boolean } = {} env: { ...process.env, CODEX_TMPFILE: tmpFile }, }); if (result.error) throw result.error; + if (result.status !== 0 && result.status !== null) { + throw new Error(`Editor exited with code ${result.status}`); + } const newValue = fsModule.readFileSync(tmpFile, 'utf8'); if (newValue === value) { From f15d1bb3fecbfa8c45e291ab405ac6b1d440a233 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 20:38:50 +0000 Subject: [PATCH 4/4] Handle Windows shell and check editor exit status in spawnSync Co-authored-by: seabearDEV <40605056+seabearDEV@users.noreply.github.com> --- src/commands/entries.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/commands/entries.ts b/src/commands/entries.ts index 7d08859..fc34c7f 100644 --- a/src/commands/entries.ts +++ b/src/commands/entries.ts @@ -449,7 +449,12 @@ export async function editEntry(key: string, options: { decrypt?: boolean } = {} fsModule.writeFileSync(tmpFile, value, { encoding: 'utf8', mode: 0o600 }); try { - const result = spawnSync('sh', ['-c', `${editor} "$CODEX_TMPFILE"`], { + const isWindows = process.platform === 'win32'; + const shell = isWindows ? 'cmd' : (process.env.SHELL ?? '/bin/sh'); + const shellArgs = isWindows + ? ['/c', `${editor} "%CODEX_TMPFILE%"`] + : ['-c', `${editor} "$CODEX_TMPFILE"`]; + const result = spawnSync(shell, shellArgs, { stdio: 'inherit', env: { ...process.env, CODEX_TMPFILE: tmpFile }, });