Skip to content

scan --diff always fails to save: scan.target.snapshotDigest: expected a non-empty string #299

Description

@pfilbin90

Summary

Every scan --diff run fails at the save step with:

Could not save the Codex Security scan: scan.target.snapshotDigest: expected a non-empty string

The scan itself completes successfully — the agent reviews the diff, builds a threat model, and writes scan-manifest.json, findings.json, and coverage.json. Only the final save is rejected, so the entire scan is discarded and the CLI exits 2.

The cause appears to be a schema mismatch inside the tool: for target.kind: "git_diff" the plugin writes a target block with no snapshotDigest field, but the save-side validator requires one.

Repository scans (no --diff) are unaffected and save normally.

Reproduction

Minimal, self-contained — a one-file repository with two commits:

mkdir -p /tmp/probe && cd /tmp/probe
git init -q && git config user.email a@b.c && git config user.name p
echo base > app.txt && git add -A && git commit -qm base
echo changed > app.txt && git add -A && git commit -qm change

npx --yes @openai/codex-security@0.1.7 scan . \
  --auth chatgpt \
  --model gpt-5.6-luna \
  --effort high \
  --max-cost 0.50 \
  --diff HEAD~1 \
  --output-dir /tmp/out \
  --verbose

Result:

[07:04] Running scan: building threat model (committed changes) | Files: 1/1
codex-security: debug: scan.failed classification="unknown" partial_output=true
Could not save the Codex Security scan: scan.target.snapshotDigest: expected a non-empty string
Partial output was kept at /tmp/out.

Removing --diff from the same command makes it succeed and print Scan complete.

Evidence

The preserved scan-manifest.json shows status: "completed" with all required artifacts present, and a target block with no snapshotDigest:

{
  "documentType": "codex-security.scan-manifest",
  "schemaVersion": "1.0",
  "scan": {
    "status": "completed",
    "producer": { "name": "codex-security-plugin", "version": "0.1.15" },
    "target": {
      "kind": "git_diff",
      "targetId": "target_sha256_ce9ecd19952d3cad45e46f75d207a5e82504efa390915e0e6c1e4bffea06e5cc",
      "displayName": "probe2",
      "baseRevision": "ac0c1def281595d9aeedf404af43602841724901",
      "headRevision": "975a26fc600c85942a1f9d648b902602d7f138e9"
    }
  }
}

findings.json, coverage.json, threat_model.md and the full artifacts/ tree are all written. On a real 12-file diff the same run produced three well-formed medium-severity findings before being discarded by the same error.

Affected versions

Version --diff repository scan
0.1.7 fails succeeds
0.1.6 fails not retested

Not a regression in 0.1.7 — 0.1.6 fails identically.

Impact

--diff is the natural mode for CI, where the point is scanning a pull request's changes rather than the whole tree. Falling back to a full repository scan is not a practical workaround: on a 3,600-file repository the diff scan of 12 files already took 27 minutes, so scanning everything per PR is out of reach.

Because the scan runs to completion before failing, each attempt costs full time and tokens and returns nothing.

Environment

  • @openai/codex-security 0.1.7 and 0.1.6, bundled plugin 0.1.15
  • codex 0.144.6, codex-sdk 0.144.6
  • Node 22, Ubuntu 24.04 container, x86-64
  • Auth: --auth chatgpt
  • Reproduced identically on a self-hosted GitHub Actions runner and in a bare docker run

Possibly related

In a container, the scan agent's sandbox cannot initialize, and the agent reports internally: "the terminal wrapper is unavailable in this host because its sandbox namespace cannot initialize". It then silently proceeds without a shell and fails much earlier with Scan agent did not create required draft artifacts: scan-manifest.json, findings.json, coverage.json.

Running the container with --security-opt seccomp=unconfined resolves that and lets the agent work normally. It may be worth surfacing a clearer diagnostic for that case, since the current message points at the scan directory rather than at sandbox initialization.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions