Summary
scans rerun calls runScan without forwarding the output format, so it always runs with interactive = true. With --json or --format jsonl it can therefore block on the interactive credential-selection prompt that the scan command explicitly suppresses in the same situation.
The rerun path omits the fourth argument, taking the interactive = true default:
|
const outcome = await runScan(scanArguments, errorOutput, dependencies); |
while scan computes it from the requested format:
|
format !== "json" && format !== "jsonl", |
interactive is what gates the account-selection prompt and the TTY progress rendering.
Affected version and environment
- Released package:
@openai/codex-security@0.1.1
- Confirmed on current
main at f22d4a36f26d16287bcdfd707b369116e02a08c3
- macOS 26.5.2 (build 25F84)
- Node.js v24.5.0
- Bun 1.3.14
Steps to reproduce
Preconditions matching the prompt's guard: stderr is a TTY, an environment API key is set, a stored ChatGPT sign-in exists, and no explicit --auth was passed.
Driving the real main() with the existing tests-ts/cli-fixtures.ts harness and an injected scanAuthenticationPrompt that records whether it was called:
const deps = {
...dependencies({ environment: { OPENAI_API_KEY: "SYNTHETIC_NOT_A_REAL_KEY" }, onWorkbench: () => ({ recipe }) }),
hasStoredChatGPTSignIn: async () => true,
scanAuthenticationPrompt: {
isInteractive: () => true,
select: async () => { prompted = true; return "chatgpt"; },
},
};
await main(["scan", ".", "--json"], out, errTTY, deps);
await main(["scans", "rerun", "scan-original", "--json"], out, errTTY, deps);
Observed result:
$ codex-security scan . --json
interactive credential prompt shown: false
$ codex-security scans rerun scan-original --json
interactive credential prompt shown: true
stderr contained: Both a ChatGPT sign-in and an API key from OPENAI_API_KEY are available.
Expected behavior
scans rerun should honour the same rule as scan: JSON and JSONL output never prompt. tests-ts/cli-authentication.test.ts already pins this for scan ("never prompts during automation"); the equivalent guarantee is missing for rerun.
Actual behavior
scans rerun <id> --json prompts for a credential choice and writes the prompt banner to stderr. In an automated context that keeps a pty attached, the command blocks waiting for input that will never arrive.
Impact
scans rerun is the documented way to re-check a fixed vulnerability, which makes it a natural fit for automation. A wrapper that runs it with --json and a pty can hang indefinitely rather than failing fast.
Related
The same missing plumbing means scans rerun <id> --format md is accepted, while scan --format md is rejected up front as unsupported. Forwarding the format to runScan would address both.
Suggested direction
Pass the computed interactivity through from the rerun command, mirroring the scan call site.
Summary
scans reruncallsrunScanwithout forwarding the output format, so it always runs withinteractive = true. With--jsonor--format jsonlit can therefore block on the interactive credential-selection prompt that thescancommand explicitly suppresses in the same situation.The rerun path omits the fourth argument, taking the
interactive = truedefault:codex-security/sdk/typescript/src/cli.ts
Line 730 in f22d4a3
while
scancomputes it from the requested format:codex-security/sdk/typescript/src/cli.ts
Line 989 in f22d4a3
interactiveis what gates the account-selection prompt and the TTY progress rendering.Affected version and environment
@openai/codex-security@0.1.1mainatf22d4a36f26d16287bcdfd707b369116e02a08c3Steps to reproduce
Preconditions matching the prompt's guard: stderr is a TTY, an environment API key is set, a stored ChatGPT sign-in exists, and no explicit
--authwas passed.Driving the real
main()with the existingtests-ts/cli-fixtures.tsharness and an injectedscanAuthenticationPromptthat records whether it was called:Observed result:
Expected behavior
scans rerunshould honour the same rule asscan: JSON and JSONL output never prompt.tests-ts/cli-authentication.test.tsalready pins this forscan("never prompts during automation"); the equivalent guarantee is missing forrerun.Actual behavior
scans rerun <id> --jsonprompts for a credential choice and writes the prompt banner to stderr. In an automated context that keeps a pty attached, the command blocks waiting for input that will never arrive.Impact
scans rerunis the documented way to re-check a fixed vulnerability, which makes it a natural fit for automation. A wrapper that runs it with--jsonand a pty can hang indefinitely rather than failing fast.Related
The same missing plumbing means
scans rerun <id> --format mdis accepted, whilescan --format mdis rejected up front as unsupported. Forwarding the format torunScanwould address both.Suggested direction
Pass the computed interactivity through from the rerun command, mirroring the
scancall site.