openai / openai/codex

Codex Security completion rereads unbounded rollout history before Workbench commit

Open
#42,122 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug CLI performance skills
Dominant language
Rust
Stars
125k
Forks
19.4k
PR merge metrics
PR metrics pending

Description

Summary

A Codex Security diff scan completed analysis and wrote sealed canonical
artifacts, but the Workbench remained running because finalization performed
an unbounded rollout-token usage scan before committing status=complete.

The affected task graph contained 262 rollout JSONL files totaling about
128.0 GB. The completion command ran after the report was sealed, then returned
a generic workbench_db.py complete-scan command failure without reaching the
Workbench completion transaction.

Environment

  • Windows NT 10.0.26200.0
  • Codex CLI 0.147.0
  • Codex Security plugin 0.1.22
  • Bundled Python 3.12.13
  • Scan mode: exact Git revision-range diff

The public plugin changelog currently documents 0.1.20 as the latest public
version; I did not downgrade the installed 0.1.22 plugin.

Observed state split

The completion attempt produced valid local artifacts:

  • report.md
  • findings.json
  • coverage.json
  • sealed scan-manifest.json
  • SARIF export

The manifest had a valid sealedAt timestamp and described the scan as
completed. The Workbench database still reported:

status: running
completed_at: null
seal_manifest_digest: null
cost_json: null

The failed scan was preserved. I did not retry completion, cancel/fail it, or
edit the Workbench database.

Root-cause evidence in plugin 0.1.22

complete_scan_locked() currently performs these steps in this order:

  1. prepare and write/seal the canonical artifacts;
  2. call collect_scan_usage() when no explicit cost JSON exists;
  3. only afterward begin the transaction that records artifacts/findings and
    updates the Workbench scan to status=complete.

collect_scan_usage() recursively discovers the root task and all descendant
tasks, then reads every rollout file from its beginning. It has no wall-time,
total-byte, single-file, or task-count budget.

A metadata-only preflight of the affected graph took under 0.2 seconds and
reported:

threads: 262
rollout files: 262
total bytes: 128,025,586,270
largest file: 5,229,307,791 bytes

No rollout contents are required to detect that this measurement is too large
to run synchronously during completion.

Reproduction

  1. Use a long-lived Codex task with many descendant tasks and multi-gigabyte
    rollout history.
  2. Start a Codex Security diff scan and complete all analysis/reporting phases.
  3. Save the complete semantic draft.
  4. Call completion once.
  5. Observe that canonical artifacts are sealed before rollout usage collection
    finishes.
  6. Observe that the completion command fails or is interrupted while the
    Workbench row remains running with no completion timestamp or usage.

As a control, I repeated the exact scan in a brand-new non-forked task. Its
three rollout files totaled about 8 MB. Both metadata capacity checks passed,
completion succeeded on its first and only call, and Workbench status, seal,
report, SARIF, and usage coverage all became complete.

Expected behavior

  • A valid sealed report should reach an atomic Workbench complete state even
    if usage measurement is too large or unavailable.
  • Usage measurement should be bounded and best-effort. Budget exhaustion should
    record partial or unavailable, not fail scan completion.
  • Completion should commit the canonical result before optional usage
    reconciliation, or use a crash-consistent transaction/state transition.
  • Usage collection should read only scan-owned data from scan-start byte
    offsets rather than replaying complete historical rollouts.
  • A later bounded reconciliation should be able to update usage for an already
    completed scan without rewriting its sealed report.

Suggested regression tests

  1. Complete a scan whose root rollout exceeds a byte budget.
  2. Complete a scan whose descendant graph exceeds a task budget.
  3. Terminate the process after artifact sealing but before usage reconciliation.
  4. Verify the scan remains completed with usage.coverage=unavailable or
    partial.
  5. Verify later usage reconciliation is idempotent and does not alter sealed
    report artifacts.

Related issues

  • #37587 covers a different finalization/schema recovery failure.
  • #24510 covers broader unbounded local-history processing and performance.

No repository contents, rollout contents, task titles, task IDs, absolute local
paths, credentials, user identifiers, or private findings are included here.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the workbench_db.py complete-scan entry point through complete_scan_locked() and collect_scan_usage(), then review the suggested capacity and interruption regression cases. Done means a sealed scan reaches Workbench status=complete even when bounded usage collection is partial or unavailable, and later reconciliation is idempotent without changing sealed report artifacts.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, rust
Domain
cli, database, performance, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.