Skip to content

feat: add component scans - #584

Open
ianw-oai wants to merge 11 commits into
mainfrom
codex/component-scans
Open

feat: add component scans#584
ianw-oai wants to merge 11 commits into
mainfrom
codex/component-scans

Conversation

@ianw-oai

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

Copy link
Copy Markdown
Collaborator

Summary

This PR adds scan-components: run separate standard scans for parts of one repository, then combine the results and merge confirmed duplicate findings.

Use this for a large repository when you want to scan components in parallel or retry only the parts that did not finish. The existing scan --path command still runs one scan across all selected paths.

Changes

Choose the components

Repeat --component to give each directory its own standard scan:

npx @openai/codex-security scan-components /path/to/project \
  --component apps/api \
  --component apps/web \
  --output-dir /path/to/results

The command runs up to four component scans at a time. Use --workers 2 to change that number. If you omit the repository, it uses the current directory. The output directory must be empty and outside the repository.

Use --auth chatgpt or --auth api-key to select credentials. The default is --auth auto, as with scan. This choice applies to planning, component scans, and matching. SDK callers use scanOptions.auth.

Let Codex choose the components

Use --auto instead of --component. Add --plan-only to inspect or edit the plan before any scans start:

npx @openai/codex-security scan-components /path/to/project \
  --auto --plan-only \
  --output-dir /path/to/plan

This writes components.json. Each component has a name and one or more repository-relative paths:

{
  "components": [
    { "name": "API", "paths": ["apps/api", "packages/auth"] },
    { "name": "Web", "paths": ["apps/web"] }
  ]
}

Run the saved plan with:

npx @openai/codex-security scan-components /path/to/project \
  --components-file /path/to/plan/components.json \
  --output-dir /path/to/results

Automatic planning uses a local file inventory and follows Git ignore rules. Each automatic path must cover an inventoried file. Explicit component selections keep their existing behavior. Files omitted by the model go into an Other files component. Planning does not change source files. Planning and matching turns disable MCP servers from SDK options and inherited Codex configuration. Select exactly one of --component, --components-file, or --auto.

Watch the scans

One terminal dashboard shows each component's status, file progress, finding count, and estimated cost. Use the arrow keys to select a component, Enter to view its activity, and Esc to return. Other scans continue while you inspect one.

Use --headless for plain status lines. CI and non-interactive runs use plain output automatically.

Read the results

results/
  components.json          Component plan
  component-1/             Normal scan files for the first component
  component-2/             Normal scan files for the second component
  findings.json            Combined findings and their sources
  summary.json             Status and coverage for each component
  report.md                Combined report with links to component reports
  retry-components.json    Created only when components need another scan

After scanning, the existing scans match logic compares findings by root cause. Confirmed duplicates become one group, even if their titles or locations differ. Each group keeps the highest-severity finding and all source scan IDs. Uncertain matches stay separate. Finding counts in the dashboard are preliminary until this step finishes.

If a component fails or has incomplete coverage, the other scans continue. Retry those components with:

npx @openai/codex-security scan-components /path/to/project \
  --components-file /path/to/results/retry-components.json \
  --output-dir /path/to/retry-results

The SDK exposes the same workflow through runComponentScans({ repository, outputDir, components }). Use auto: true instead of components for automatic planning.

Testing

  • Component, comparison, and CLI-auth tests: 74 passed, 3 skipped, 0 failed. These cover automatic versus explicit ignored-file selection, all three auth modes, and missing API keys before planning.
  • Full SDK suite: 1,578 passed, 29 skipped, 0 failed in each run (seeds 12345 and 304638432).
  • Types, formatting, build, and git diff --check: passed.
  • Installed-package check on Node 24: passed, including public imports, NodeNext types, CLI startup, all 111 plugin files, and nested-worker startup.
  • The initial Windows CI run failed in an unchanged release-automation test when its Bash subprocess returned no exit status. Only failed checks were retried; that rerun is pending.

Risk and rollout

Existing scan commands keep their behavior. No database migration or release change is required. Internal model and matching types are not part of the public SDK type declarations.

  • --max-cost limits each component scan. It does not cover automatic planning, duplicate matching, or the whole project.
  • Exit code 2 means a component failed, coverage is incomplete, or duplicate matching did not finish. Available results are still saved.
  • The combined files are a project summary, not a new sealed scan. Use the individual component folders with export and publish.

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 component scans feat: [codex] add component scans Aug 20, 2026
@github-actions github-actions Bot added the enhancement New feature or request label Aug 20, 2026
@ianw-oai ianw-oai changed the title feat: [codex] add component scans feat: add component scans Aug 21, 2026
@ianw-oai
ianw-oai marked this pull request as ready for review August 21, 2026 20:14
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 21, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-21T22:09:27.836942Z 4466b6d Manual request
🔒 Security Review Completed 2026-08-21T20:18:55.208514Z 20e37cf Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@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.

runReadOnlyCodex spreads the full scan config into the planning and matching turns. That includes caller-configured mcp_servers. The prompts correctly treat repository inventory and finding text as untrusted and say not to use tools, but read-only sandboxing, disabled shell features, and networkAccessEnabled: false do not remove MCP tools or their external effects. A malicious file name or finding could still steer one of these helper turns into a configured integration.

Please construct a minimal model and provider config for these turns, or explicitly disable every MCP server before starting the thread. Add a test that supplies a configured MCP server and verifies it is unavailable.

Copy link
Copy Markdown
Collaborator Author

@mldangelo-oai Addressed in 3e88c08e.

Planning and matching now disable both MCP servers supplied through SDK options and servers inherited from Codex configuration. The helper uses the pinned CLI to read the effective server list before starting a model turn; it does not connect to those servers. If that check fails, the helper does not start.

The regression checks both sources and verifies that the pinned CLI reports both servers as disabled. Component/comparison tests pass (45 passed, 3 skipped), as do the full SDK suite (1,574 passed, 29 skipped; seed 12345), types, formatting, build, and the installed-package check on Node 24.

This closes the unwanted tool access without relying on a prompt instruction or changing the normal scan configuration.

@mldangelo-oai

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3e88c08e62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/scan-comparison.ts Outdated
Comment thread sdk/typescript/src/component-scan.ts Outdated
Comment thread sdk/typescript/src/cli.ts Outdated

@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.

Re-reviewed 3e88c08e. The original MCP issue is closed: explicit and inherited servers are disabled before planning or matching starts, the check fails closed, and the focused component/comparison run passed locally with 45 passed and 3 platform skips.

The exact-head pass surfaced three remaining issues that hold up in the code paths: read-only helpers ignore the documented CODEX_CLI_PATH for both MCP discovery and the actual SDK turn; observer snapshots shallow-copy receipts but still alias paths, so an optional observer can mutate later scan targets; and headless status output writes model- or repository-influenced names and errors without terminal-safe single-line sanitization. These are separate from the MCP fix but part of the new public workflow, so I am commenting rather than approving.

@mldangelo-oai

Copy link
Copy Markdown
Collaborator

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4466b6d2af

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread sdk/typescript/src/component-plan.ts
Comment thread sdk/typescript/src/component-scan.ts
Comment thread sdk/typescript/src/component-scan.ts

@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.

Re-reviewed exact head a59cdf8. The executable-selection and observer-isolation fixes remain sound, but the follow-up commit reopens the headless status issue: the CLI now interpolates the component name and error directly, and the regression that covered newlines and terminal escapes was removed. Component names accept model or imported-plan text, while safeErrorMessage deliberately preserves non-credential text. On this head, a probe produced a string containing embedded newlines and ESC, so CI and headless output can again forge records or issue terminal control sequences.

Focused component, comparison, and dashboard tests passed locally with 75 passed and 3 platform skips, and types passed. The PR body is also one commit behind in its CI note. Commenting rather than requesting changes.

@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.

I checked the three new findings against exact head a59cdf85. All three hold:

  • The automatic planner can return an existing Git-ignored .env. Normalization accepts it, and the later component scan targets it even though the inventory excluded it.
  • The combined report writes finding.title as Markdown. A synthetic title with a newline and link created a forged bullet with an active link.
  • scan-components --auth chatgpt exits 2, and the SDK component options omit ScanOptions.auth, so component scans cannot select the same credential route as standard scans.

Three focused probes reproduced those behaviors. Along with the reopened terminal-status regression in my previous review, this head is not ready for approval. The direct fixes are to require every automatic path to cover an inventoried file, escape finding titles as plain Markdown text, forward the existing auth selector, and restore terminal-safe status formatting and its test. Commenting rather than requesting changes.

Copy link
Copy Markdown
Collaborator Author

The follow-up in 25079fc is limited to automatic-plan scope and authentication selection. It deliberately preserves the direct terminal status output from a59cdf8 and the existing Markdown report formatting. We are not treating the constructed display-input cases as blockers for this PR.

@ianw-oai
ianw-oai requested a review from mldangelo-oai August 22, 2026 04:02
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