Skip to content

feat(cli): add interactive finding review, patching, and optional PRs - #461

Draft
ianw-oai wants to merge 4 commits into
dev/ianw/show-patch-tasks-in-codexfrom
dev/ianw/interactive-scan-patching
Draft

feat(cli): add interactive finding review, patching, and optional PRs#461
ianw-oai wants to merge 4 commits into
dev/ianw/show-patch-tasks-in-codexfrom
dev/ianw/interactive-scan-patching

Conversation

@ianw-oai

@ianw-oai ianw-oai commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

After a security scan finishes, choose which findings to fix, generate and check the fixes, and optionally open a GitHub pull request. The same flow also works without prompts and with findings from earlier scans.

Built on #477. Each selected finding runs in its own saved Codex task, which appears in the Codex desktop app.

Changes

Review findings after a scan

npx @openai/codex-security scan .

The scan prints its usual findings, then asks whether to review and patch them. Scans with no findings do not ask.

 CODEX SECURITY  example-app                         3/3 selected · low and above

 ╭─ FINDINGS ─────────────────────────────╮ ╭─ DETAILS ─────────────────────────╮
 │ › [✓] CRITICAL SQL injection in search │ │ SQL injection in account search   │
 │   [✓] HIGH Missing admin authentication│ │                                   │
 │   [✓] MEDIUM Stack trace in response   │ │ SUMMARY                           │
 │                                        │ │ Search input enters a SQL query.  │
 │                                        │ │                                   │
 │                                        │ │ SEVERITY        ● Critical        │
 │                                        │ │ CONFIDENCE      ● High            │
 ╰────────────────────────────────────────╯ ╰───────────────────────────────────╯

 ╭─ PATCH INSTRUCTIONS ──────────────────────────────────────────────── i edit ─╮
 │ Add instructions for this finding.                                          │
 ╰──────────────────────────────────────────────────────────────────────────────╯

 [ ] Create GitHub pull request after patching                  (r toggle)
 ↑↓ browse · Tab details · Space select · 1–4 severity · Enter patch

Choose a severity, select individual findings, inspect the surrounding code, and give the patch instructions for each finding:

 CODEX SECURITY  example-app                        2/3 selected · high and above

 ╭─ FINDINGS ─────────────────────────────╮ ╭─ DETAILS ─────────────────────────╮
 │ › [✓] CRITICAL SQL injection in search │ │ src/accounts.ts:7–8               │
 │   [✓] HIGH Missing admin authentication│ │   5 │ const user = requireUser(); │
 │   [ ] MEDIUM Stack trace in response   │ │   6 │ const term = query.search;  │
 │                                        │ │ › 7 │ const sql = `...${term}`;   │
 │                                        │ │ › 8 │ return database.query(sql); │
 ╰────────────────────────────────────────╯ ╰───────────────────────────────────╯

 ╭─ PATCH INSTRUCTIONS ────────────────────────────────────────────────────────╮
 │ Use the shared parameterized query helper.                                   │
 ╰──────────────────────────────────────────────────────────────────────────────╯

 [✓] Create GitHub pull request after patching

After you press Enter, each selected finding gets its own Codex task. Tasks run one at a time in the same checkout, and a failed finding does not stop the remaining tasks.

Patch automatically

# Fix all confirmed findings without opening the review screen.
npx @openai/codex-security scan . --headless --patch

# Fix only high and critical findings, without opening the review screen.
npx @openai/codex-security scan . --headless --patch --patch-severity high

Patch findings from an earlier scan

npx @openai/codex-security patch occ_EXAMPLE
npx @openai/codex-security patch --scan latest --severity high
npx @openai/codex-security patch --scan SCAN_ID --severity high --json

Open a pull request after verified fixes

npx @openai/codex-security scan . --patch --patch-severity high --create-pr
npx @openai/codex-security patch --scan latest --severity high --create-pr

Only verified fixes are committed. Existing staged changes are left alone.

Testing

  • 352 tests passed, including interactive review, separate saved Codex tasks, automatic patching, saved findings, authentication, and a real local Git push.
  • pnpm run types
  • pnpm run format
  • pnpm run build
  • pnpm run check:package ../../dist/openai-codex-security-0.1.12.tgz

Risk and rollout

Patching and pull request creation are optional. Incomplete scans are not patched. Saved Codex tasks can contain finding details. Code shown in the review stays inside the scanned repository, and existing authentication and failure behavior are preserved.

Public disclosure review

  • No customer, partner, prospect, or user identities, data, or identifying details are included.
  • No credentials, personal data, private source, scan findings, or nonpublic links or tickets are included.
  • I reviewed the branch name, title, description, commits, changes, comments, logs, screenshots, attachments, and links for public disclosure.

@ianw-oai ianw-oai changed the title [codex] Add interactive and automated security finding patches feat(cli): add interactive and automated finding patching Aug 15, 2026
@github-actions github-actions Bot added the enhancement New feature or request label Aug 15, 2026
@ianw-oai
ianw-oai force-pushed the dev/ianw/interactive-scan-patching branch from 6ab52c3 to 93e9967 Compare August 16, 2026 03:41
@ianw-oai ianw-oai changed the title feat(cli): add interactive and automated finding patching feat(cli): scan, review, patch, and create pull requests Aug 16, 2026
@ianw-oai ianw-oai changed the title feat(cli): scan, review, patch, and create pull requests feat(cli): add interactive finding review, patching, and optional PRs Aug 16, 2026

@mldangelo-oai mldangelo-oai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking QA notes on draft 93e99673. The saved-finding patch flow, selection and cancellation UI, and successful local Git publication path worked with synthetic fixtures. The full local suite passed 1,316 tests with 11 skipped. Git used a local remote, and PR creation used a test double, so this was not a live GitHub PR test.

I'd split the work at the patch result: return one structured result for saved findings, literal issues, and Linear input, then let a separate publication step consume it. The saved-finding-only --create-pr path does not yet join up with #475 and #477.

Two concrete Windows follow-ups: use platform-resolved paths in the new tests, and add *.tsx text eol=lf to .gitattributes. The new TUI file passes formatting with LF and fails with CRLF. The current Windows checks still fail. I left the recovery and simplification suggestions inline.

Comment thread sdk/typescript/src/cli.ts
Comment on lines +3467 to +3471
await run("git", ["push", "--set-upstream", "origin", branch]);
const url = await run("gh", [
"pr",
"create",
"--head",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: if PR creation fails after the push, the branch and commit already exist. A retry then hits git switch -c with the same branch name and fails. I reproduced this with a local remote and a failing PR-service test double. Could publication retain the branch and commit, then resume at the missing push or PR step without rerunning the model? A regression where push succeeds, PR creation fails, and a retry succeeds would cover it.

Comment thread sdk/typescript/src/cli.ts
Comment on lines +705 to +711
const findingPatchSchema = z.object({
occurrenceId: z.string(),
status: z.enum(["verified", "no_change", "blocked", "failed"]),
files: z.array(z.string()),
verification: z.string().optional(),
reason: z.string().optional(),
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking simplification: could literal issues, Linear issues, and saved findings share this result boundary? One typed result with the source ID, task ID, outcome, changed files, and verification would let JSON output and publication use the same code. I'd adapt the skill's outcome vocabulary once here instead of keeping a saved-finding-only parser and separate success rules. That would also distinguish a completed model turn that reports blocked from an issue that was fixed.

Comment on lines +123 to +125
expect(invocation[invocation.indexOf("--cd") + 1]).toBe(
"/current/other/repository",
);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking: these expectations use POSIX absolute paths, while the implementation resolves paths for the host platform. The Windows jobs fail on this family of assertions. Could we define the fixture roots once with node:path's resolve and join, then reuse them in setup and expectations? The later CODEX_HOME, patch-editor repository, and saved-repository assertions need the same treatment.

Comment on lines +77 to +81
function detailLines(
value: unknown,
indent = "",
evidence?: ReadonlyMap<string, FindingCodeEvidence>,
): string[] {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking scope suggestion: could we reuse the existing finding presentation for expanded details and keep this UI focused on selection, severity, and short instructions? It worked at 80x24, but one synthetic finding produced 70 detail lines. Reusing the detail view and handing longer conversations to the saved task would reduce the rendering and keyboard state this feature has to maintain.

@ianw-oai
ianw-oai force-pushed the dev/ianw/interactive-scan-patching branch from 93e9967 to 648adac Compare August 16, 2026 06:38
@ianw-oai
ianw-oai changed the base branch from main to dev/ianw/show-patch-tasks-in-codex August 16, 2026 06:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants