Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,17 @@ Codex Security is a thin wrapper around Codex and its security plugin.
only after checking that it is public. If you cannot confirm its visibility,
leave it out.

## Avoid speculative defenses

- Do not add sanitization, redaction, validation, or fallback logic for
hypothetical problems. State the concrete failure it fixes.
- When extending an existing command, preserve its output behavior. Do not
introduce a new sanitization policy for names, paths, or status messages.
- Keep existing credential, unsafe-path, and scan-integrity protections.
Do not extend them to unrelated values without a demonstrated need.
- Do not invent a restriction and then add tests whose only purpose is to
enforce that restriction.

## Public CLI changes

Treat commands, arguments, flags, accepted values, public environment
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ Deep-scan discovery stops after 96 hours by default. Set `--max-time-hours` to
any positive number of hours, including fractional hours, up to 96. Completed
findings are preserved and returned when the limit is reached.

For a monorepo, run separate standard scans and combine their results by root
cause:

```bash
npx @openai/codex-security scan-components . \
--component apps/api --component apps/web \
--output-dir /path/outside/repository/results
```

Use `--auto` to let Codex choose the components, or `--auto --plan-only` to
review the split first. See [component scans](sdk/typescript/README.md#scan-project-components)
for reusable plans, combined reports, and coverage details.

To use another inference provider, set its API key and select a model:

```bash
Expand Down
76 changes: 76 additions & 0 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ Use `security.preflight()` to validate local inputs, `onWorkerStatus` and
`onReconnect` to observe long-running scans, and an `AbortSignal` to cancel a
scan.

For separate standard scans under one project, the SDK also exports
`runComponentScans({ repository, outputDir, components })`. Each component has
a `name` and `paths` array. Use `auto: true` instead of `components` for
model-assisted planning, and `planOnly: true` to save the plan without scanning.

Successful results include open repository findings in `repositoryFindings`,
when available; `findings` remains the current scan. Matching earlier findings
can make one additional model call, including with a scan cost limit.
Expand Down Expand Up @@ -249,6 +254,8 @@ npx @openai/codex-security scan /path/to/repository --patch --patch-severity hig
npx @openai/codex-security scan /path/to/repository --model gpt-5.6-terra
npx @openai/codex-security scan /path/to/repository --model gpt-5.6-terra --effort high
npx @openai/codex-security scan /path/to/repository --path src --path tests
npx @openai/codex-security scan-components /path/to/repository --component apps/api --component apps/web --output-dir /path/outside/repository/results
npx @openai/codex-security scan-components /path/to/repository --auto --output-dir /path/outside/repository/results
npx @openai/codex-security scan /path/to/repository --knowledge-base /path/to/threat-models --knowledge-base /path/to/architecture.pdf
npx @openai/codex-security scan /path/to/repository --scan-prompt-file scan.md --post-scan-prompt-file follow-up.md
npx @openai/codex-security scan /path/to/repository --diff origin/main --json
Expand Down Expand Up @@ -328,6 +335,75 @@ Repeat `--knowledge-base PATH` for multiple files or directories; `bulk-scan`
shares them with every repository. Directories are searched recursively for
Markdown, text, PDF, and Word (`.docx`) files.

### Scan project components

`scan --path` runs one scan across the selected paths. Use `scan-components`
to run a separate standard scan for each component of one local project:

```bash
npx @openai/codex-security scan-components /path/to/project \
--component apps/api --component apps/web --component packages/shared \
--workers 4 --output-dir /path/outside/project/results
```

Use `--auth chatgpt` or `--auth api-key` to select credentials for planning,
component scans, and matching. The default is `--auth auto`, as with `scan`.
The SDK accepts the same choice through `scanOptions.auth`.

Use `--auto` instead of `--component` to let Codex propose the split. To review
or edit it first, save a plan, then run that plan into a new output directory:

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

A component can contain several repository-relative paths:

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

Automatic planning uses a local file inventory. In Git repositories it follows
Git's ignore rules. Each automatic path must cover at least one inventoried file.
Explicit `--component` and `--components-file` selections keep their existing behavior.
Inventoried files omitted by the model are added to an
`Other files` component. No source files are changed during planning.

In an interactive terminal, one dashboard shows all components and their scan
progress. Use the arrow keys to select a component, Enter to view its activity,
and Esc to return. Other scans continue while you inspect one. Finding counts
are preliminary until cross-component matching finishes. Use `--headless` for
plain status lines; CI and redirected output use those automatically.
Failed or incomplete components are also saved in `retry-components.json`.
Pass that file to `--components-file` with a new output directory to retry them.

Each component keeps its normal scan artifacts under `component-N/`.
The combined `findings.json` uses the same root-cause matcher as `scans match`.
It merges high-confidence matches even when their titles, locations, or
fingerprints differ. Each group keeps its highest-severity finding and all
original scan and occurrence IDs. Match reasons and uncertain pairs are saved;
uncertain findings stay separate. `summary.json` records scan coverage and
whether matching finished. `report.md` links to the component reports.
These combined files are a project summary, not a new sealed scan. Use the
individual scan folders with `export` and `publish`.

The output directory must be empty and outside the project. Failed components
do not stop the others. The command saves the available results and exits with
code `2` if a component fails, coverage is incomplete, or cross-component
matching fails. `--max-cost` applies to each component scan, not planning,
cross-component matching, or the whole project. `--model` and `--effort` also
apply to matching. `--knowledge-base`,
`--scan-prompt-file`, and `--post-scan-prompt-file` work as they do for bulk scans.

### Configure deep scans

For `scan --mode deep`, `--workers` limits concurrent discovery workers,
Expand Down
2 changes: 2 additions & 0 deletions sdk/typescript/scripts/check-package.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ const distFiles = new Set(
"bulk-scan-discovery",
"cli",
"codex-prompt",
"component-plan",
"component-scan",
"config",
"contract",
"cost",
Expand Down
16 changes: 16 additions & 0 deletions sdk/typescript/scripts/fixtures/package-consumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import {
CodexSecurity,
DiffTarget,
estimateScanCost,
planComponents,
runComponentScans,
type ComponentScanOptions,
type Finding,
type ScanCost,
type ScanOptions,
Expand Down Expand Up @@ -52,3 +55,16 @@ export async function validate(

// @ts-expect-error The dependency-injection constructor is internal.
new CodexSecurity({}, undefined as never, undefined as never);

export async function scanComponents(repository: string, outputDir: string) {
const plan = await planComponents(repository);
const options: ComponentScanOptions = {
repository,
outputDir,
components: plan.components,
};
return await runComponentScans(options);
}

// @ts-expect-error The model client is an internal test dependency.
planComponents("synthetic-repository", { codex: {} });
3 changes: 2 additions & 1 deletion sdk/typescript/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3095,7 +3095,8 @@ async function runtimeScanAuthentication(
return authentication;
}

function selectedScanEnvironment(
/** @internal */
export function selectedScanEnvironment(
environment: ProcessEnvironment,
auth: ScanAuthMode = "auto",
modelProvider?: unknown,
Expand Down
Loading
Loading