Codex Security: recoverable finalization schema error permanently fails completed scan
Summary
A Codex Security diff scan completed discovery, validation, attack-path analysis, and canonical draft generation, but finalization rejected an empty scan.target.snapshotDigest. After repairing the digest in a fresh turn, completion could not be retried because the first validation error had already moved the scan into the terminal failed state.
This makes a recoverable metadata/schema error permanently prevent sealing an otherwise completed long-running scan.
Environment
- Codex desktop on Windows with Ubuntu/WSL 2
- Codex Security plugin:
0.1.17when the scan began;0.1.18subsequently installed - Scan mode: Git revision-range/diff scan
- Exact base and head revisions were available throughout
- Repository checkout remained unchanged
Private scan identifiers and unsealed artifacts can be provided privately if needed.
Reproduction
- Start a Codex Security diff scan over an exact base/head revision range.
- Complete all review receipts and the validation and attack-path phases.
- Author the canonical unsealed draft artifacts.
- Call scan completion.
- Completion fails with:
````
scan.target.snapshotDigest: expected a non-empty string
- In a fresh turn, populate the correct deterministic snapshot digest and verify the canonical artifacts.
- Call completion once more.
- Completion fails with:
````
Only a running scan can be completed.
The first finalization validation error has already marked the scan failed, and the exposed workflow has no supported failed → running recovery transition.
Expected behavior
One or more of the following:
- Populate and validate
snapshotDigestbefore attempting terminal finalization. - Treat canonical artifact/schema validation errors as recoverable and leave the scan running.
- Make finalization transactional so a validation failure does not persist terminal state.
- Provide an audited recovery/reopen operation for scans whose artifacts are repaired after a finalization error.
Actual behavior
The expensive analytical phases and valid draft artifacts remain available, but the scan cannot be sealed or displayed as completed. The only supported alternative appears to be rerunning the entire scan.
Additional context
The installed 0.1.18 package documents snapshotDigest as required for Git diff targets, but includes no recovery procedure for this terminal state. The public Codex Security changelog currently stops at 0.1.17.
No repository contents, finding details, local paths, scan identifiers, or sensitive artifacts are included in this issue.
2 Comments
Additional 0.1.18 root-cause evidence: this is not limited to a stale draft from 0.1.17. I reproduced the same terminal failure on three distinct 0.1.18 Git diff scans (both
commitandrange). In the packaged workbench,require_diff_targetcomputes and returnscontentDigestonly forworking_tree; thecommitandrangebranches return only kind/base/head.workbench_completion_bindinglikewise writessnapshotDigestonly when the target kind isworking_tree, while the final report schema requires a non-emptyscan.target.snapshotDigestfor everygit_diff. That leaves a required identity field to model-authored artifact text, which is brittle and can place a digest in narrative context without populating the structured target field. The finalizer then calls the terminal failure transition on the resulting contract error.\n\nA durable upstream fix should (1) compute and persist a workbench-owned digest for commit/range targets from the exact resolved base/head Git diff, (2) inject and independently verify that digest during finalization instead of asking the model to reproduce it, and (3) keep contract/schema assembly errors inrunningso the same scan can correct and retry. No private repository data or scan identifiers are needed to reproduce this control-flow mismatch.Independent reproduction on Linux / VS Code Web with the Codex Security 0.1.18 runtime.
Environment:
range019f43ac-20b8-7ad1-965b-3b2e6460255dObserved:
3/3 report_artifacts, with preflight complete.complete_codex_security_scanreturned:``
``Codex Security scan completion failed.
scan.target.snapshotDigest: expected a non-empty string
status: failed, the samefailureMessage, and no report.running:``
``Only a running scan can be completed.
Inspection of the packaged 0.1.18 runtime matches the root cause described above: a
rangetarget is persisted as kind/base/head without a workbench-owned content digest; the completion binding does not injectsnapshotDigestfor that target kind; the final report contract requires it forgit_diff; and the contract failure is persisted as terminalfailed.This independently confirms two defects still present in 0.1.18 and shows they are not Windows-specific:
rangediff targets.Expected behavior:
No repository contents, local paths, revisions, scan IDs, artifacts, request IDs, or account data are included.
Follow-up: byte-identical
working_treeworkaround succeedsI completed the same review with Codex Security 0.1.18 by changing only the target representation:
working_treeand that workbench-ownedcontentDigest.The replacement scan then behaved correctly:
scan.target.snapshotDigestautomatically;report.mdwas generated.The original
rangescan remained terminallyfailedand could not be repaired or resumed.This isolates the defect further: identical reviewed bytes succeed through the
working_treemetadata path and fail through therangemetadata path. The content and canonical findings are not the cause. The difference is that the working-tree path computes, persists, and injects its content digest, while the range path does not.The workaround is not a practical recovery mechanism because it requires a replacement scan and re-execution of the scan workflow. It does, however, provide a deterministic regression test for an upstream fix: equivalent
rangeandworking_treetargets should both receive workbench-owned snapshot identity and should both finalize successfully.