Summary
When the scan target changes while a scan is running, the scan is completed against the original snapshot and a warning is written to stderr. The warning does not affect the exit code and is not present in --json output. A CI job therefore sees exit 0 and a JSON document that is indistinguishable from a scan of the commit it actually checked out.
Environment
@openai/codex-security 0.1.5 (commit 5625adc159bbbfb4bd85557d83e2805d27379230)
Detail
scan_target_warning produces the message (workbench_target.py L529):
Repository HEAD changed while the scan was running;
results were saved for the original revision.
It is appended to warnings at workbench_db.py L1410-L1412 and nothing else is changed — coverage.completeness stays complete.
The SDK forwards those strings only through the onWarning observer (api.ts L829-L841), and the CLI's observer just writes to stderr (cli.ts L2696-L2699):
onWarning: (warning) => {
errorOutput.write(`codex-security: warning: ${redactedErrorMessage(warning)}\n`);
},
Exit code selection never consults warnings (cli.ts L2783-L2791):
if (incomplete) { // completeness !== "complete"
...
return { exitCode: 2, data: result.toJSON() };
}
return { exitCode: blockingCount > 0 ? 1 : 0, data: result.toJSON() };
and ScanResult.toJSON() has no warnings key at all (result.ts L95-L107):
public toJSON(): Record<string, unknown> {
return { manifest, findings, coverage, scanDir, threadId,
reportPath, artifactsDir, sarifPath, cost, turn };
}
So the drift is discoverable only by scraping stderr for the substring codex-security: warning:.
Summary
When the scan target changes while a scan is running, the scan is completed against the original snapshot and a warning is written to stderr. The warning does not affect the exit code and is not present in
--jsonoutput. A CI job therefore seesexit 0and a JSON document that is indistinguishable from a scan of the commit it actually checked out.Environment
@openai/codex-security0.1.5 (commit5625adc159bbbfb4bd85557d83e2805d27379230)Detail
scan_target_warningproduces the message (workbench_target.pyL529):It is appended to
warningsatworkbench_db.pyL1410-L1412 and nothing else is changed —coverage.completenessstayscomplete.The SDK forwards those strings only through the
onWarningobserver (api.tsL829-L841), and the CLI's observer just writes to stderr (cli.tsL2696-L2699):Exit code selection never consults warnings (
cli.tsL2783-L2791):and
ScanResult.toJSON()has nowarningskey at all (result.tsL95-L107):So the drift is discoverable only by scraping stderr for the substring
codex-security: warning:.