openai / openai/codex-security

multiscan resume skips corrupted artifacts without validating the scan contract

Open
#30 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area:bulk-scan area:reports bug priority:p1
Dominant language
TypeScript
Stars
10.8k
Forks
801
Avg merge
1d 8h
Merged PRs (30d)
257

Description

Summary

When a completed multiscan campaign is resumed, the supervisor checks only whether four required artifact paths exist and are regular files. It does not parse the JSON documents, validate their schemas, or verify the sealed artifact digests.

As a result, a corrupted artifact bundle is still counted as completed and skipped instead of being rescanned.

Affected version and environment

  • Released package: @openai/codex-security@0.1.1
  • Originally reproduced at commit e94d6bef9797a192febfde89a26ec7f831bc09b2
  • Confirmed still present on current main at f22d4a36f26d16287bcdfd707b369116e02a08c3
  • Microsoft Windows NT 10.0.19045.0
  • Node.js 24.18.0

Steps to reproduce

I used a source-level test harness modeled on tests-ts/multiscan.test.ts, so the reproduction does not require an API call:

  1. Create a temporary local Git repository and commit one file.
  2. Create a one-row inventory CSV containing the repository path and full commit SHA.
  3. Provide a test createSecurity() client whose run() method increments a counter, writes the four required artifact files, and returns complete coverage.
  4. Run runMultiscan() once and confirm that the security client was called once.
  5. Replace the completed attempt's scan-manifest.json with invalid JSON while leaving all four files present:
{broken json
  1. Run runMultiscan() again with the same inventory and output directory.

Observed result:

{
  "first": {
    "completed": 1,
    "failed": 0,
    "skipped": 0
  },
  "second": {
    "completed": 1,
    "failed": 0,
    "skipped": 1
  },
  "securityRunCalls": 1,
  "corruptedArtifactPreserved": true
}

Expected behavior

The resumed campaign should validate the completed artifact bundle. If the contract or seal is invalid, the task should be treated as pending and a new attempt should be created.

Actual behavior

The task is reported as completed and skipped solely because the four paths remain regular files. The corrupted bundle is preserved as the latest successful result.

Impact

Interrupted writes, manual edits, filesystem corruption, or incomplete artifact restoration can leave a bundle that is unusable or no longer sealed. Subsequent bulk scans can still report the repository as completed without repairing or rerunning it.

Relevant code

Suggested direction

Possible approaches:

  1. Reuse the existing contract/seal validation before accepting a completed receipt.
  2. Alternatively, record artifact digests in the receipt and verify them during resume.
  3. If validation fails, preserve the old attempt for inspection and create a new attempt rather than overwriting it.
  4. Add regression cases for malformed JSON, schema-invalid JSON, and a changed sealed artifact.

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 in sdk/typescript/src/multiscan.ts at the resume decision and artifact existence check, then read the helper in sdk/typescript/tests-ts/multiscan.test.ts. Run the multiscan tests and add regression coverage for malformed JSON, schema-invalid artifacts, and changed sealed artifacts. Done means invalid bundles are treated as pending, preserved for inspection, and rescanned.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.