SpyBara
Go Premium

Documentation 2026-08-07 18:59 UTC to 2026-08-08 03:02 UTC

7 files changed +654 −202. View all changes and history on the product overview
2026
Sat 8 03:02 Fri 7 18:59 Thu 6 23:58 Wed 5 19:00 Tue 4 22:00 Mon 3 23:00 Sun 2 21:00

codex-manual.md +327 −101

Details

3581#### Can an interrupted bulk scan resume3581#### Can an interrupted bulk scan resume

3582 3582 

3583Yes. Run the same bulk-scan command with the original CSV and output directory.3583Yes. Run the same bulk-scan command with the original CSV and output directory.

3584Codex Security skips completed repositories when their recorded scan artifacts3584Codex Security skips completed repositories.

3585remain intact.

3586 3585 

3587Add `--max-attempts 3` to retry temporary repository or scan errors:3586Add `--max-attempts 3` to retry temporary repository or scan errors:

3588 3587 


3593 --max-attempts 33592 --max-attempts 3

3594```3593```

3595 3594 

3595A completed scan with `partial` or `unknown` coverage keeps its results and

3596causes the campaign to exit with code `2`. It isn't retried, even with

3597`--max-attempts`.

3598 

3596#### How can a scan use architecture and security policies3599#### How can a scan use architecture and security policies

3597 3600 

3598Pass architecture documents, threat models, or security policies with3601Pass architecture documents, threat models, or security policies with


3640 3643 

3641#### How do scans distinguish new and known findings3644#### How do scans distinguish new and known findings

3642 3645 

3643Match findings that share a root cause across the two scans:3646Compare findings across the two scans:

3644 

3645```bash

3646npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

3647```

3648 

3649Compare the matched findings:

3650 3647 

3651```bash3648```bash

3652npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID3649npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

3653```3650```

3654 3651 

3655The comparison identifies new, persisting, reopened, resolved, and unknown3652The comparison automatically matches findings by root cause, reuses saved

3653matches, and identifies new, persisting, reopened, resolved, and unknown

3656findings. A finding counts as resolved only when the later scan covers its3654findings. A finding counts as resolved only when the later scan covers its

3657original target and affected path without coverage gaps.3655original target and affected path without coverage gaps.

3658 3656 


3687npx @openai/codex-security scans rerun BASELINE_SCAN_ID3685npx @openai/codex-security scans rerun BASELINE_SCAN_ID

3688```3686```

3689 3687 

3690Match the baseline findings to the new scan:3688Compare the baseline with the new scan:

3691 

3692```bash

3693npx @openai/codex-security scans match BASELINE_SCAN_ID REPEAT_SCAN_ID

3694```

3695 

3696Compare the matched results:

3697 3689 

3698```bash3690```bash

3699npx @openai/codex-security scans compare BASELINE_SCAN_ID REPEAT_SCAN_ID3691npx @openai/codex-security scans compare BASELINE_SCAN_ID REPEAT_SCAN_ID


3712npx @openai/codex-security scans rerun BEFORE_SCAN_ID3704npx @openai/codex-security scans rerun BEFORE_SCAN_ID

3713```3705```

3714 3706 

3715Match the original findings to the new scan:3707Compare the original findings with the new scan:

3716 

3717```bash

3718npx @openai/codex-security scans match BEFORE_SCAN_ID AFTER_SCAN_ID

3719```

3720 

3721Compare the matched findings:

3722 3708 

3723```bash3709```bash

3724npx @openai/codex-security scans compare BEFORE_SCAN_ID AFTER_SCAN_ID3710npx @openai/codex-security scans compare BEFORE_SCAN_ID AFTER_SCAN_ID


3803 3789 

3804#### Check the prerequisites3790#### Check the prerequisites

3805 3791 

3806The CLI requires Node.js 22 or later. Running a scan or exporting findings also3792The CLI requires Node.js 22.13.0 or later. Running a scan or exporting findings

3807requires Python 3.10 or later. For more detail, see [Authentication and3793also requires Python 3.10 or later. For more detail, see [Authentication and

3808prerequisites](https://learn.chatgpt.com/docs/security/cli/reference#authentication-and-prerequisites).3794prerequisites](https://learn.chatgpt.com/docs/security/cli/reference#authentication-and-prerequisites).

3809 3795 

3810#### Set up and verify the CLI3796#### Set up and verify the CLI


3844```3830```

3845 3831 

3846For AWS credentials, see [Amazon Bedrock3832For AWS credentials, see [Amazon Bedrock

3847setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock).3833setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock). For [OpenRouter or

3834Fireworks](https://learn.chatgpt.com/docs/security/cli/reference#use-openrouter-or-fireworks), set the

3835provider's API key and select a model with `--provider` and `--model`.

3848 3836 

3849To use your ChatGPT sign-in when an API key is also set, select it explicitly:3837To use your ChatGPT sign-in when an API key is also set, select it explicitly:

3850 3838 


3887npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR" --dry-run3875npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR" --dry-run

3888```3876```

3889 3877 

3890The dry run checks local inputs without starting Codex, loading credentials,3878The dry run checks local inputs, including any `--knowledge-base` paths,

3891or probing the plugin's Python interpreter.3879without starting Codex, loading credentials, or probing the plugin's Python

3880interpreter.

3892 3881 

3893#### Run your first scan3882#### Run your first scan

3894 3883 


3898npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR"3887npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR"

3899```3888```

3900 3889 

3890Interactive terminals show a live scan dashboard. Add `--headless` to show

3891plain progress lines instead. CI and terminals without an interactive session

3892use plain progress automatically.

3893 

3901By default, the CLI writes scan progress and its completion summary to stderr.3894By default, the CLI writes scan progress and its completion summary to stderr.

3902It doesn't print the full scan result to stdout. A completed scan prints a3895It doesn't print the full scan result to stdout. A completed scan prints a

3903summary like this:3896summary like this:


3992npx @openai/codex-security scan "$REPOSITORY" --mode deep3985npx @openai/codex-security scan "$REPOSITORY" --mode deep

3993```3986```

3994 3987 

3995Deep mode supports repository and path targets, not diff or working-tree scans.3988To control discovery workers, subagents, and when the scan stops:

3989 

3990```bash

3991npx @openai/codex-security scan "$REPOSITORY" \

3992 --mode deep \

3993 --workers 2 \

3994 --subagents 0 \

3995 --stop-after-no-new 3 \

3996 --max-discovery-runs 10

3997```

3998 

3999These options require deep mode, which supports repository and path targets,

4000not diff or working-tree scans. Here, `--workers` controls discovery workers

4001within one scan; `bulk-scan --workers` controls concurrent repository scans.

3996 4002 

3997#### Add architecture and security context4003#### Add architecture and security context

3998 4004 


4006 --knowledge-base /path/to/security-policies4012 --knowledge-base /path/to/security-policies

4007```4013```

4008 4014 

4015#### Add custom scan instructions

4016 

4017Add instructions that focus the scan on your security priorities. Use a

4018second file for a follow-up after a validated scan with complete coverage:

4019 

4020```bash

4021npx @openai/codex-security scan "$REPOSITORY" \

4022 --scan-prompt-file /path/to/scan.md \

4023 --post-scan-prompt-file /path/to/follow-up.md

4024```

4025 

4026The follow-up runs in the same authenticated session. Both options also work

4027with `bulk-scan`; a CSV `prompt` column adds repository-specific instructions.

4028 

4009#### Set a scan budget4029#### Set a scan budget

4010 4030 

4011Use `--max-cost` to stop a scan when its estimated model cost exceeds a limit4031Use `--max-cost` to stop a scan when its estimated model cost exceeds a limit


4015npx @openai/codex-security scan "$REPOSITORY" --max-cost 54035npx @openai/codex-security scan "$REPOSITORY" --max-cost 5

4016```4036```

4017 4037 

4018Requests already in progress can finish above the limit. Codex Security keeps4038Requests already in progress can finish slightly above the limit. If a scan

4019the available results when a scan stops.4039aborts due to the cost limit, partial scan results remain available on disk.

4020 4040 

4021#### Scan changes before each commit4041#### Scan changes before each commit

4022 4042 


4055 --workers 44075 --workers 4

4056```4076```

4057 4077 

4058Run the same command again to resume an existing bulk scan. Completed4078Run the same command again to resume an existing bulk scan. Codex Security

4059repositories with intact result artifacts aren't scanned again. Add4079skips completed repositories. Add `--max-attempts 3` when you want to retry

4060`--max-attempts 3` when you want to retry temporary repository or scan errors.4080temporary repository or scan errors.

4061 4081 

4062For GitHub discovery, CSV preparation, campaign results, and Docker setup, see4082For GitHub discovery, CSV preparation, campaign results, and Docker setup, see

4063[Run bulk security scans](https://learn.chatgpt.com/docs/security/cli/bulk-scans).4083[Run bulk security scans](https://learn.chatgpt.com/docs/security/cli/bulk-scans).


4077 --workers 44097 --workers 4

4078```4098```

4079 4099 

4080The container runs bulk scans without prompts. Use the CLI outside Docker when4100The container runs bulk scans without interactive prompts. Use the CLI outside

4081you want to discover repositories interactively. For private repositories,4101Docker when you want to discover repositories interactively. For private

4082provide `GH_TOKEN` or `GITHUB_TOKEN` through your environment or secret4102repositories, provide `GH_TOKEN` or `GITHUB_TOKEN` through your environment or

4083manager. The [sign-in requirements](#sign-in), including account and repository4103secret manager. The [sign-in requirements](#sign-in), including account and

4084access, also apply to containerized scans.4104repository access, also apply to containerized scans.

4085 4105 

4086#### Revisit a saved scan4106#### Revisit a saved scan

4087 4107 


4113npx @openai/codex-security scans rerun SCAN_ID4133npx @openai/codex-security scans rerun SCAN_ID

4114```4134```

4115 4135 

4116To compare two scans, first match findings that share the same root cause:4136Compare two scans to find new, persisting, reopened, resolved, or unknown

4117 4137findings:

4118```bash

4119npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

4120```

4121 

4122Then check which findings are new, persisting, reopened, resolved, or unknown:

4123 4138 

4124```bash4139```bash

4125npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID4140npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

4126```4141```

4127 4142 

4143The comparison automatically matches findings by root cause and reuses saved

4144matches.

4145 

4128For the bulk-scan CSV format, scan-history filters, and command options, see4146For the bulk-scan CSV format, scan-history filters, and command options, see

4129the [CLI reference](https://learn.chatgpt.com/docs/security/cli/reference).4147the [CLI reference](https://learn.chatgpt.com/docs/security/cli/reference).

4130 4148 


4259 [--provider {openai,openrouter,fireworks,amazon-bedrock}]4277 [--provider {openai,openrouter,fireworks,amazon-bedrock}]

4260 [--path PATH | --diff BASE | --working-tree]4278 [--path PATH | --diff BASE | --working-tree]

4261 [--head HEAD] [--base BASE]4279 [--head HEAD] [--base BASE]

4262 [--knowledge-base PATH]4280 [--knowledge-base PATH] [--scan-prompt-file FILE]

4263 [--mode {standard,deep}] [--model MODEL]4281 [--post-scan-prompt-file FILE]

4282 [--mode {standard,deep}] [--workers N]

4283 [--subagents N] [--stop-after-no-new N]

4284 [--max-discovery-runs N] [--model MODEL]

4264 [--effort {minimal,low,medium,high,xhigh}]4285 [--effort {minimal,low,medium,high,xhigh}]

4265 [--output-dir DIR]4286 [--output-dir DIR]

4266 [--archive-existing]4287 [--archive-existing]

4267 [--plugin-path PATH] [--python PATH]4288 [--plugin-path PATH] [--python PATH]

4268 [--codex KEY=VALUE] [--fail-on-severity LEVEL]4289 [--codex KEY=VALUE] [--fail-on-severity LEVEL]

4269 [--max-cost USD] [--dry-run] [--verbose]4290 [--max-cost USD] [--dry-run] [--headless] [--verbose]

4270 [--json] [--format {toon,json,yaml,jsonl}]4291 [--json] [--format {toon,json,yaml,jsonl}]

4271 [--full-output] [repository]4292 [--full-output] [repository]

4272```4293```


4296To make stored credentials the automatic default, run4317To make stored credentials the automatic default, run

4297`unset OPENAI_API_KEY CODEX_API_KEY`.4318`unset OPENAI_API_KEY CODEX_API_KEY`.

4298 4319 

4320#### Use OpenRouter or Fireworks

4321 

4322Select OpenRouter with its API key and an explicit model:

4323 

4324```bash

4325export OPENROUTER_API_KEY="your-openrouter-api-key"

4326npx @openai/codex-security scan . \

4327 --provider openrouter \

4328 --model anthropic/claude-sonnet-4.5

4329```

4330 

4331Select Fireworks with its API key and an explicit model:

4332 

4333```bash

4334export FIREWORKS_API_KEY="your-fireworks-api-key"

4335npx @openai/codex-security scan . \

4336 --provider fireworks \

4337 --model accounts/fireworks/models/qwen3-235b-a22b

4338```

4339 

4340Both providers also support `bulk-scan`.

4341 

4299#### Use Amazon Bedrock4342#### Use Amazon Bedrock

4300 4343 

4301Select Amazon Bedrock with `--provider amazon-bedrock` and specify an explicit4344Select Amazon Bedrock with `--provider amazon-bedrock` and specify an explicit


4363npx @openai/codex-security scan . --mode deep4406npx @openai/codex-security scan . --mode deep

4364```4407```

4365 4408 

4409#### Configure deep scans

4410 

4411Use these options with `--mode deep` to control discovery concurrency and

4412runtime:

4413 

4414| Argument | Description |

4415| ------------------------ | ----------------------------------------------------------------------- |

4416| `--workers N` | Limit on concurrent discovery workers. Defaults to automatic selection. |

4417| `--subagents N` | Subagents available to each discovery worker. Defaults to `3`. |

4418| `--stop-after-no-new N` | Stop after `N` consecutive runs find no new issues. Defaults to `6`. |

4419| `--max-discovery-runs N` | Limit on total discovery runs. Defaults to `60`. |

4420 

4421`--subagents` accepts zero or a positive integer. The other options require a

4422positive integer. These options aren't available for standard scans.

4423 

4424For example, limit a deep scan to two discovery workers and ten total runs:

4425 

4426```bash

4427npx @openai/codex-security scan . \

4428 --mode deep \

4429 --workers 2 \

4430 --subagents 0 \

4431 --stop-after-no-new 3 \

4432 --max-discovery-runs 10

4433```

4434 

4435Set persistent defaults in `~/.codex/codex-security/config.toml`, or in

4436`$CODEX_HOME/codex-security/config.toml` when you set `CODEX_HOME`:

4437 

4438```toml

4439[deep_scan]

4440workers = 2

4441subagents = 0

4442stop_after_no_new = 3

4443max_discovery_runs = 10

4444```

4445 

4446Command-line options override these defaults. `scan --workers` controls

4447discovery workers within one scan; `bulk-scan --workers` controls concurrent

4448repository scans.

4449 

4366#### Add security context4450#### Add security context

4367 4451 

4368Use `--knowledge-base PATH` to provide architecture documents, threat models,4452Use `--knowledge-base PATH` to provide architecture documents, threat models,


4379skips linked directory entries, and keeps extracted document content4463skips linked directory entries, and keeps extracted document content

4380outside the saved scan results.4464outside the saved scan results.

4381 4465 

4466#### Add scan instructions

4467 

4468To add scan instructions, provide a text or Markdown file with

4469`--scan-prompt-file`. Use `--post-scan-prompt-file` to run follow-up

4470instructions in the same authenticated session after a completed scan with

4471complete coverage:

4472 

4473```bash

4474npx @openai/codex-security scan . \

4475 --scan-prompt-file security-focus.md \

4476 --post-scan-prompt-file follow-up.md

4477```

4478 

4479For example, use the scan prompt to focus on authorization boundaries and ask

4480the follow-up to write a new `post-scan-summary.md` in the scan directory.

4481 

4382#### Set output and policy options4482#### Set output and policy options

4383 4483 

4384Use these options to keep artifacts, preserve earlier results, or create a4484Use these options to keep artifacts, preserve earlier results, or create a


4390| `--archive-existing` | Move existing results to `DIR.previous--` and start with an empty output directory. Requires `--output-dir`. |4490| `--archive-existing` | Move existing results to `DIR.previous--` and start with an empty output directory. Requires `--output-dir`. |

4391| `--fail-on-severity LEVEL` | Return exit `1` when a completed scan reports a finding at or above `critical`, `high`, `medium`, or `low`. |4491| `--fail-on-severity LEVEL` | Return exit `1` when a completed scan reports a finding at or above `critical`, `high`, `medium`, or `low`. |

4392| `--max-cost USD` | Stop a scan when its estimated model cost exceeds the specified USD amount. |4492| `--max-cost USD` | Stop a scan when its estimated model cost exceeds the specified USD amount. |

4393| `--dry-run` | Check the repository, target, output directory, and Codex configuration without starting a scan. |4493| `--dry-run` | Check the repository, target, knowledge base, output directory, and Codex configuration without starting a scan. |

4494| `--headless` | Show plain-text progress instead of the interactive scan dashboard. |

4394| `--verbose` | Print redacted lifecycle, authentication, progress, and cost diagnostics to stderr. |4495| `--verbose` | Print redacted lifecycle, authentication, progress, and cost diagnostics to stderr. |

4395| `--json` | Print manifest, findings, coverage, paths, and turn metadata as one JSON document. |4496| `--json` | Print manifest, findings, coverage, paths, and turn metadata as one JSON document. |

4396| `--format FORMAT` | Print the complete scan result as `toon`, `json`, `yaml`, or `jsonl`. |4497| `--format FORMAT` | Print the complete scan result as `toon`, `json`, `yaml`, or `jsonl`. |

4397| `--full-output` | Print the complete result using the default structured output format. |4498| `--full-output` | Print the complete result using the default structured output format. |

4398 4499 

4399The cost limit is an estimate, not a hard spending cap. Requests already in4500The cost limit is an estimate, not a hard spending cap. Requests already in

4400progress can finish above the limit, and partial scan results remain available.4501progress can finish slightly above the limit. If a scan aborts due to the cost

4502limit, partial scan results remain available on disk.

4401 4503 

4402When you omit `--output-dir`, results persist under4504When you omit `--output-dir`, results persist under

4403`$CODEX_HOME/state/plugins/codex-security/scans/`. `CODEX_HOME`4505`$CODEX_HOME/state/plugins/codex-security/scans/`. `CODEX_HOME`


4434 > /path/outside/repository/codex-security.json4536 > /path/outside/repository/codex-security.json

4435```4537```

4436 4538 

4437A dry run checks local inputs without loading credentials, starting Codex, or4539A dry run checks local inputs, including knowledge-base documents, without

4438probing the plugin's Python interpreter:4540loading credentials, starting Codex, or probing the plugin's Python

4541interpreter:

4439 4542 

4440```bash4543```bash

4441npx @openai/codex-security scan . \4544npx @openai/codex-security scan . \


4452| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |4555| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |

4453| `--auth {auto,chatgpt,api-key}` | Select the scan credentials. The default is `auto`. |4556| `--auth {auto,chatgpt,api-key}` | Select the scan credentials. The default is `auto`. |

4454| `--provider {openai,openrouter,fireworks,amazon-bedrock}` | Select the inference provider. The default is `openai`. |4557| `--provider {openai,openrouter,fireworks,amazon-bedrock}` | Select the inference provider. The default is `openai`. |

4455| `--model MODEL` | Select the model. The default is `gpt-5.6-sol`. Required with `--provider amazon-bedrock`. |4558| `--model MODEL` | Select the model. The default is `gpt-5.6-sol`. Required for OpenRouter, Fireworks, and Amazon Bedrock. |

4456| `--effort {minimal,low,medium,high,xhigh}` | Select the model's reasoning effort. The default is `xhigh`. |4559| `--effort {minimal,low,medium,high,xhigh}` | Select the model's reasoning effort. The default is `xhigh`. |

4457| `--plugin-path PATH` | Use a Codex Security plugin directory or ZIP to override the bundled plugin. |4560| `--plugin-path PATH` | Use a Codex Security plugin directory or ZIP to override the bundled plugin. |

4458| `--python PATH` | Select the Python interpreter for the plugin runtime. |4561| `--python PATH` | Select the Python interpreter for the plugin runtime. |


4503 [--provider {openai,openrouter,fireworks,amazon-bedrock}]4606 [--provider {openai,openrouter,fireworks,amazon-bedrock}]

4504 [--model MODEL]4607 [--model MODEL]

4505 [--effort {minimal,low,medium,high,xhigh}]4608 [--effort {minimal,low,medium,high,xhigh}]

4609 [--knowledge-base PATH]

4610 [--scan-prompt-file FILE]

4611 [--post-scan-prompt-file FILE]

4506 [--max-attempts N] [--plugin-path PATH]4612 [--max-attempts N] [--plugin-path PATH]

4507 [--python PATH] [--codex KEY=VALUE]4613 [--python PATH] [--codex KEY=VALUE]

4508```4614```


4525```4631```

4526 4632 

4527The CSV requires `id`, `repository`, and `revision` columns. Revisions must be4633The CSV requires `id`, `repository`, and `revision` columns. Revisions must be

4528full commit hashes. Optional `scope` and `mode` columns configure individual4634full commit hashes. Optional `scope`, `mode`, and `prompt` columns configure

4529repositories:4635individual repositories:

4530 4636 

4531```csv4637```csv

4532id,repository,revision,scope,mode4638id,repository,revision,scope,mode,prompt

4533service,https://github.com/example/service.git,0123456789abcdef0123456789abcdef01234567,src,standard4639service,https://github.com/example/service.git,0123456789abcdef0123456789abcdef01234567,src,standard,Review authorization boundaries.

4534```4640```

4535 4641 

4536`--workers` limits simultaneous scans and defaults to `4`. `--mode` defaults to4642Use `--knowledge-base PATH` to share security documents across every

4537`standard`, and `--max-attempts` defaults to `1`. Set `--max-attempts` when4643repository. Use `--scan-prompt-file FILE` to add shared scan instructions; the

4538you want to retry a repository after an error. Run the same command again to4644CSV `prompt` column adds repository-specific instructions after that shared

4539resume a bulk scan from its existing output directory. The CLI skips completed4645prompt. `--post-scan-prompt-file FILE` runs follow-up instructions after each

4540repositories only when their recorded result artifacts are still present.4646completed scan with complete coverage.

4647 

4648`--workers` limits simultaneous repository scans and defaults to `4`. `--mode`

4649defaults to `standard`, and `--max-attempts` defaults to `1`. Set

4650`--max-attempts` to retry repository or scan errors. Completed scans with

4651incomplete coverage aren't retried. Their results remain available, and the

4652command returns exit code `2`.

4653 

4654Run the same command again to resume from an existing output directory. The CLI

4655skips completed scans, including scans with incomplete coverage.

4541 4656 

4542For containerized campaigns, see [Run bulk scans in4657For containerized campaigns, see [Run bulk scans in

4543Docker](https://learn.chatgpt.com/docs/security/cli/bulk-scans#run-bulk-scans-in-docker).4658Docker](https://learn.chatgpt.com/docs/security/cli/bulk-scans#run-bulk-scans-in-docker).


4580 4695 

4581#### Match and compare findings4696#### Match and compare findings

4582 4697 

4583Match findings that share the same root cause across two scans:4698Compare two scans to find new, persisting, reopened, resolved, and unknown

4699findings:

4584 4700 

4585```bash4701```bash

4586npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID4702npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

4587```4703```

4588 4704 

4589Compare the matched scans to find new, persisting, reopened, resolved, and4705The comparison automatically matches findings that share the same root cause

4590unknown findings:4706and reuses saved matches. To save matches explicitly, use `scans match`:

4591 4707 

4592```bash4708```bash

4593npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID4709npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

4594```4710```

4595 4711 

4596A finding is unknown when the later scan has incomplete coverage or doesn't4712A finding is unknown when the later scan has incomplete coverage or doesn't


4782without writing the complete scan result to stdout. Request `--json`,4898without writing the complete scan result to stdout. Request `--json`,

4783`--format`, or `--full-output` to send structured scan results to stdout.4899`--format`, or `--full-output` to send structured scan results to stdout.

4784 4900 

4901Interactive terminals show a live dashboard with the current scan phase,

4902reviewed files, activity, token usage, and estimated cost. CI and redirected

4903output use plain-text progress. Add `--headless` to use plain-text progress in

4904an interactive terminal:

4905 

4906```bash

4907npx @openai/codex-security scan . --headless

4908```

4909 

4785#### Verbose diagnostics4910#### Verbose diagnostics

4786 4911 

4787Add `--verbose` to print redacted lifecycle, authentication, progress, and cost4912Add `--verbose` to print redacted lifecycle, authentication, progress, and cost


4901 5026 

4902Set `OPENAI_API_KEY` or `CODEX_API_KEY`, sign in with5027Set `OPENAI_API_KEY` or `CODEX_API_KEY`, sign in with

4903`npx @openai/codex-security login`, or use an existing file-backed Codex5028`npx @openai/codex-security login`, or use an existing file-backed Codex

4904sign-in. For Amazon Bedrock, use a Bedrock API key or the standard AWS5029sign-in. For OpenRouter or Fireworks, set the provider's API key and select a

5030model. For Amazon Bedrock, use a Bedrock API key or the standard AWS

4905credential chain instead.5031credential chain instead.

4906 5032 

4907For credential selection, see [Select scan5033For credential selection, see [Select scan


4909 5035 

4910For CI, keep the API key scoped to the scan step and use a trusted workflow.5036For CI, keep the API key scoped to the scan step and use a trusted workflow.

4911 5037 

4912The CLI requires Node.js 22 or later. Running a scan or exporting findings also5038The CLI requires Node.js 22.13.0 or later. Running a scan or exporting findings

4913requires Python 3.10 or later. Python 3.10 also requires `tomli`. Use `--python`5039also requires Python 3.10 or later. Python 3.10 also requires `tomli`. Use

4914or `PYTHON` to select an interpreter when automatic discovery is unsuitable.5040`--python` or `PYTHON` to select an interpreter when automatic discovery is

5041unsuitable.

4915 5042 

4916Continue with the [CLI quickstart](https://learn.chatgpt.com/docs/security/cli), [bulk-scan5043Continue with the [CLI quickstart](https://learn.chatgpt.com/docs/security/cli), [bulk-scan

4917guide](https://learn.chatgpt.com/docs/security/cli/bulk-scans), [CLI FAQ](https://learn.chatgpt.com/docs/security/cli/faq), [CI5044guide](https://learn.chatgpt.com/docs/security/cli/bulk-scans), [CLI FAQ](https://learn.chatgpt.com/docs/security/cli/faq), [CI


5586findings, coverage details, and paths to scan artifacts. For longer scans, it5713findings, coverage details, and paths to scan artifacts. For longer scans, it

5587supports preflight checks, cost limits, progress callbacks, and cancellation.5714supports preflight checks, cost limits, progress callbacks, and cancellation.

5588 5715 

5589The SDK uses ECMAScript modules (ESM) and runs server-side with Node.js 22 or5716The SDK uses ECMAScript modules (ESM) and runs server-side with Node.js 22.13.0

5590later. Scanning also requires Python 3.10 or later.5717or later. Scanning also requires Python 3.10 or later.

5591 5718 

5592The Codex Security SDK is [publicly available on5719The Codex Security SDK is [publicly available on

5593GitHub](https://github.com/openai/codex-security). Running scans requires5720GitHub](https://github.com/openai/codex-security). Running scans requires


5604```5731```

5605 5732 

5606Before starting a scan, set `OPENAI_API_KEY` or `CODEX_API_KEY`, use an5733Before starting a scan, set `OPENAI_API_KEY` or `CODEX_API_KEY`, use an

5607existing file-backed Codex sign-in, or [configure Amazon5734existing file-backed Codex sign-in, or [configure another

5608Bedrock](#configure-the-runtime-and-credentials) with AWS credentials and5735provider](#configure-the-runtime-and-credentials). Amazon Bedrock uses AWS

5609explicit `model_provider` and `model` overrides.5736credentials; OpenRouter and Fireworks use provider-specific API keys and

5737configuration.

5610 5738 

5611For best results, use an account verified for [Trusted Access for5739For best results, use an account verified for [Trusted Access for

5612Cyber](https://chatgpt.com/cyber). Signing in or providing an API key does not5740Cyber](https://chatgpt.com/cyber). Signing in or providing an API key does not


5646 5774 

5647#### Check inputs with preflight5775#### Check inputs with preflight

5648 5776 

5649Use `preflight` to check a repository, target, mode, output location, and5777Use `preflight` to check a repository, target, mode, knowledge-base documents,

5650Codex configuration before starting a scan:5778output location, and Codex configuration before starting a scan:

5651 5779 

5652```ts5780```ts

5653const plan = await security.preflight("/path/to/repository", {5781const plan = await security.preflight("/path/to/repository", {

5654 target: ["services/billing", "packages/auth"],5782 target: ["services/billing", "packages/auth"],

5783 knowledgeBasePaths: ["/path/to/architecture.md"],

5655 outputDir: "/path/outside/repository/results",5784 outputDir: "/path/outside/repository/results",

5656});5785});

5657 5786 


5752const result = await security.run("/path/to/repository", {5881const result = await security.run("/path/to/repository", {

5753 target: ["services/billing"],5882 target: ["services/billing"],

5754 mode: "deep",5883 mode: "deep",

5884 workers: 2,

5885 subagents: 0,

5886 stopAfterNoNew: 3,

5887 maxDiscoveryRuns: 10,

5755});5888});

5756```5889```

5757 5890 

5758Deep mode supports repository and path targets. Use standard mode for diff and5891Deep mode supports repository and path targets. Use standard mode for diff and

5759working-tree scans.5892working-tree scans. The optional settings control concurrent discovery workers,

5893subagents per worker, consecutive discovery runs without new findings, and the

5894total number of discovery runs. They require `mode: "deep"`.

5760 5895 

5761#### Add a security knowledge base5896#### Add a security knowledge base

5762 5897 


5777The SDK rejects linked input paths, skips linked directory entries, and keeps5912The SDK rejects linked input paths, skips linked directory entries, and keeps

5778extracted document content outside the saved scan results.5913extracted document content outside the saved scan results.

5779 5914 

5915#### Add scan and follow-up instructions

5916 

5917Use `scanPrompt` to focus the scan and `postScanPrompt` to request a follow-up

5918after a completed scan:

5919 

5920```ts

5921const result = await security.run("/path/to/repository", {

5922 scanPrompt: "Focus on tenant isolation and authorization checks.",

5923 postScanPrompt: "Write confirmed findings to post-scan-summary.md.",

5924});

5925```

5926 

5927The follow-up runs in the same authenticated session only after the scan

5928finishes with complete coverage.

5929 

5780#### Set a scan budget5930#### Set a scan budget

5781 5931 

5782Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.5932Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.


5793console.log(result.cost?.estimatedUsd);5943console.log(result.cost?.estimatedUsd);

5794```5944```

5795 5945 

5796The limit is an estimate, not a hard spending cap. Requests already in progress5946The limit estimates spending but isn't a hard cap, so requests already in

5797can finish above it. If the scan exceeds the limit, the SDK throws5947progress can finish slightly above it. If the scan exceeds the limit, the SDK

5798`ScanCostLimitExceededError` and preserves the available results.5948throws `ScanCostLimitExceededError` and preserves the available results.

5799 5949 

5800#### Work with scan results5950#### Work with scan results

5801 5951 


5857 onScanStarted() {6007 onScanStarted() {

5858 console.log("Scan started");6008 console.log("Scan started");

5859 },6009 },

6010 onProgress(progress) {

6011 console.log(progress.phase, progress.filesCompleted, progress.filesTotal);

6012 },

5860 onWorkerStatus(status) {6013 onWorkerStatus(status) {

5861 console.log(status.kind, status);6014 console.log(status.kind, status);

5862 },6015 },


5903lifecycle callbacks:6056lifecycle callbacks:

5904 6057 

5905| Callback | Called when |6058| Callback | Called when |

5906| ----------------------------------- | ------------------------------------------------ |6059| ----------------------------------- | ---------------------------------------------------- |

6060| `onAuthentication(authentication)` | The scan selects its authentication method. |

5907| `onOutputArchived(archiveDir)` | Existing results move to the archive directory. |6061| `onOutputArchived(archiveDir)` | Existing results move to the archive directory. |

5908| `onOutputDirReady(scanDir)` | The private scan directory is ready. |6062| `onOutputDirReady(scanDir)` | The private scan directory is ready. |

5909| `onScanStarted()` | Scan setup completes and execution begins. |6063| `onScanStarted()` | Scan setup completes and execution begins. |

6064| `onTrustedAccessStatus(status)` | Trusted Access status becomes available. |

5910| `onReconnect(attempt, maxAttempts)` | The SDK retries a disconnected scan stream. |6065| `onReconnect(attempt, maxAttempts)` | The SDK retries a disconnected scan stream. |

6066| `onActivity(activity)` | A command, tool, reasoning step, or message updates. |

6067| `onProgress(progress)` | The scan phase or reviewed file count changes. |

5911| `onWorkerStatus(status)` | Worker preflight or dispatch status changes. |6068| `onWorkerStatus(status)` | Worker preflight or dispatch status changes. |

5912| `onCost(cost)` | An updated estimated scan cost is available. |6069| `onCost(cost)` | An updated estimated scan cost is available. |

6070| `onWarning(warning)` | The scan reports a warning. |

5913| `onObserverError(observer, error)` | Another scan lifecycle callback raises an error. |6071| `onObserverError(observer, error)` | Another scan lifecycle callback raises an error. |

5914 6072 

6073Trusted Access status is `granted`, `not_granted`, or `unknown`. Missing or

6074unknown access also triggers `onWarning`.

6075 

5915#### Configure the runtime and credentials6076#### Configure the runtime and credentials

5916 6077 

5917Pass runtime configuration when you need a specific plugin, interpreter, or6078Pass runtime configuration when you need a specific plugin, interpreter, or


5936Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set6097Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set

5937`model_provider` and `model` in `codexOverrides`.6098`model_provider` and `model` in `codexOverrides`.

5938 6099 

6100For OpenRouter or Fireworks, also provide the matching API key and a complete

6101provider configuration in `codexOverrides`. For example, set

6102`OPENROUTER_API_KEY` and configure OpenRouter:

6103 

6104```ts

6105const security = new CodexSecurity({

6106 codexOverrides: {

6107 model: "anthropic/claude-sonnet-4.5",

6108 model_provider: "openrouter",

6109 model_providers: {

6110 openrouter: {

6111 name: "OpenRouter",

6112 base_url: "https://openrouter.ai/api/v1",

6113 env_key: "OPENROUTER_API_KEY",

6114 wire_api: "responses",

6115 },

6116 },

6117 },

6118});

6119```

6120 

6121For Fireworks, change both `openrouter` keys to `fireworks`, set `name` to

6122`Fireworks AI`, set `env_key` to `FIREWORKS_API_KEY`, use

6123`https://api.fireworks.ai/inference/v1` as `base_url`, and select a Fireworks

6124model.

6125 

5939The client also exposes supported authentication methods:6126The client also exposes supported authentication methods:

5940 6127 

5941| Method | Purpose |6128| Method | Purpose |


7020Create a CSV with one row for each repository and pinned revision:7207Create a CSV with one row for each repository and pinned revision:

7021 7208 

7022```csv7209```csv

7023id,repository,revision,scope,mode7210id,repository,revision,scope,mode,prompt

7024payments,https://github.com/example/payments.git,0123456789abcdef0123456789abcdef01234567,services/api,standard7211payments,https://github.com/example/payments.git,0123456789abcdef0123456789abcdef01234567,services/api,standard,Review payment authorization and refunds.

7025identity,https://github.com/example/identity.git,fedcba9876543210fedcba9876543210fedcba98,,deep7212identity,https://github.com/example/identity.git,fedcba9876543210fedcba9876543210fedcba98,,deep,Review session and identity boundaries.

7026```7213```

7027 7214 

7028The CSV supports these columns:7215The CSV supports these columns:


7034| `revision` | Yes | Full 40- or 64-character Git commit SHA. Branch names, tags, and shortened commit hashes aren't supported. |7221| `revision` | Yes | Full 40- or 64-character Git commit SHA. Branch names, tags, and shortened commit hashes aren't supported. |

7035| `scope` | No | A repository-relative directory to scan. Omit the value to scan the full repository. |7222| `scope` | No | A repository-relative directory to scan. Omit the value to scan the full repository. |

7036| `mode` | No | `standard` or `deep`. Omit the value to use the command's selected mode. |7223| `mode` | No | `standard` or `deep`. Omit the value to use the command's selected mode. |

7224| `prompt` | No | Scan instructions specific to this repository. |

7037 7225 

7038To find a local repository's full commit SHA, run:7226To find a local repository's full commit SHA, run:

7039 7227 


7051 --workers 47239 --workers 4

7052```7240```

7053 7241 

7054`--workers` controls the number of concurrent repository scans and defaults to7242`--workers` controls concurrent repository scans and defaults to `4`. It does

7055`4`. Use `--mode deep` to select deep scanning for rows without their own7243not set the number of discovery workers within each deep scan; configure those

7056`mode`. Each CSV row can still choose its own scan mode and repository scope.7244limits through [`[deep_scan]`](/codex/security/cli/reference#configure-deep-scans).

7245Use `--mode deep` to select deep scanning for rows without their own `mode`.

7246Each CSV row can still choose its own scan mode and repository scope.

7057 7247 

7058The CLI checks out each pinned revision, scans the selected target, records the7248The CLI checks out each pinned revision, scans the selected target, records the

7059result, and removes the temporary repository checkout. A repository counts as7249result, and removes the temporary repository checkout. A repository counts as

7060complete only when its scan has complete coverage and all required result7250complete only when its scan has complete coverage and all required result

7061artifacts exist.7251artifacts exist.

7062 7252 

7253#### Share security context and instructions

7254 

7255Add architecture documents, threat models, or security policies to every scan

7256with `--knowledge-base`. Repeat the flag for more files or directories:

7257 

7258```bash

7259npx @openai/codex-security bulk-scan repositories.csv \

7260 --output-dir /path/outside/repositories/security-scans \

7261 --knowledge-base /path/to/architecture.md \

7262 --knowledge-base /path/to/security-policies

7263```

7264 

7265To add shared scan instructions or run a follow-up after each completed scan,

7266provide prompt files:

7267 

7268```bash

7269npx @openai/codex-security bulk-scan repositories.csv \

7270 --output-dir /path/outside/repositories/security-scans \

7271 --scan-prompt-file scan-instructions.md \

7272 --post-scan-prompt-file follow-up.md

7273```

7274 

7275The CLI appends each repository's CSV `prompt` after the shared scan

7276instructions. Follow-up instructions run in the same authenticated session only

7277after a validated scan has complete coverage. Prompt file paths resolve from

7278your current directory.

7279 

7063#### Choose a model and reasoning effort7280#### Choose a model and reasoning effort

7064 7281 

7065Bulk scans use `gpt-5.6-sol` with `xhigh` reasoning effort by default. To7282Bulk scans use `gpt-5.6-sol` with `xhigh` reasoning effort by default. To


7081 7298 

7082Supported effort levels are `minimal`, `low`, `medium`, `high`, and `xhigh`.7299Supported effort levels are `minimal`, `low`, `medium`, `high`, and `xhigh`.

7083 7300 

7301To use OpenRouter or Fireworks, set `OPENROUTER_API_KEY` or `FIREWORKS_API_KEY`,

7302respectively, and specify `--provider` and `--model`. For credentials and

7303examples, see [OpenRouter or Fireworks

7304setup](https://learn.chatgpt.com/docs/security/cli/reference#use-openrouter-or-fireworks) or [Amazon

7305Bedrock setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock).

7306 

7084#### Review campaign results7307#### Review campaign results

7085 7308 

7086The output directory contains the pinned campaign, an append-only results7309The output directory contains the pinned campaign, an append-only results


7106 └── report.md7329 └── report.md

7107```7330```

7108 7331 

7109- `manifest.json` records the repositories, pinned revisions, scopes, and scan7332- `manifest.json` records the repositories, pinned revisions, scopes, scan

7110 modes in the campaign.7333 modes, and shared or repository-specific instructions in the campaign.

7111- `results.jsonl` records each repository attempt, its status, artifact7334- `results.jsonl` records each repository attempt, its status, artifact

7112 directory, and any available cost or error details.7335 directory, and any available cost or error details.

7113- `report.md` provides a readable report for one repository attempt.7336- `report.md` provides a readable report for one repository attempt.


7137 --workers 47360 --workers 4

7138```7361```

7139 7362 

7140The CLI resumes repositories that still need work. It skips a completed7363The CLI resumes unfinished repository scans and skips completed ones. Scans

7141repository only when the corresponding receipt and all required scan artifacts7364with incomplete coverage aren't retried. Their results remain available, and

7142still exist.7365the command exits with code `2`.

7143 7366 

7144Don't change the repository inventory for an existing output directory. The CLI7367Don't change the repository inventory or scan and follow-up instructions for

7145checks the pinned manifest and rejects a different campaign. Use a new output7368an existing output directory. The CLI checks the pinned manifest and rejects a

7146directory when you change repositories, revisions, scopes, or scan modes.7369different campaign. Use a new output directory when you change repositories,

7370revisions, scopes, scan modes, or shared or repository-specific instructions.

7147 7371 

7148#### Retry repository errors7372#### Retry repository errors

7149 7373 


7158```7382```

7159 7383 

7160The default is one attempt per repository. Every attempt receives its own7384The default is one attempt per repository. Every attempt receives its own

7161receipt and artifact directory.7385receipt and artifact directory. Retries cover checkout errors, scan failures,

7386and missing required artifacts. Completed scans with incomplete coverage

7387aren't retried.

7162 7388 

7163Bulk scans use these exit codes:7389Bulk scans use these exit codes:

7164 7390 


7224 7450 

7225The runner needs:7451The runner needs:

7226 7452 

7227- Node.js 22 or later.7453- Node.js 22.13.0 or later.

7228- Python 3.10 or later.7454- Python 3.10 or later.

7229- The published `@openai/codex-security` package, installed outside the7455- The published `@openai/codex-security` package, installed outside the

7230 repository checkout.7456 repository checkout.

security/cli.md +55 −23

Details

14 14 

15## Check the prerequisites15## Check the prerequisites

16 16 

17The CLI requires Node.js 22 or later. Running a scan or exporting findings also17The CLI requires Node.js 22.13.0 or later. Running a scan or exporting findings

18requires Python 3.10 or later. For more detail, see [Authentication and18also requires Python 3.10 or later. For more detail, see [Authentication and

19prerequisites](https://learn.chatgpt.com/docs/security/cli/reference#authentication-and-prerequisites).19prerequisites](https://learn.chatgpt.com/docs/security/cli/reference#authentication-and-prerequisites).

20 20 

21## Set up and verify the CLI21## Set up and verify the CLI


55```55```

56 56 

57For AWS credentials, see [Amazon Bedrock57For AWS credentials, see [Amazon Bedrock

58setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock).58setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock). For [OpenRouter or

59Fireworks](https://learn.chatgpt.com/docs/security/cli/reference#use-openrouter-or-fireworks), set the

60provider's API key and select a model with `--provider` and `--model`.

59 61 

60To use your ChatGPT sign-in when an API key is also set, select it explicitly:62To use your ChatGPT sign-in when an API key is also set, select it explicitly:

61 63 


98npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR" --dry-run100npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR" --dry-run

99```101```

100 102 

101The dry run checks local inputs without starting Codex, loading credentials,103The dry run checks local inputs, including any `--knowledge-base` paths,

102or probing the plugin's Python interpreter.104without starting Codex, loading credentials, or probing the plugin's Python

105interpreter.

103 106 

104## Run your first scan107## Run your first scan

105 108 


109npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR"112npx @openai/codex-security scan "$REPOSITORY" --output-dir "$SCAN_DIR"

110```113```

111 114 

115Interactive terminals show a live scan dashboard. Add `--headless` to show

116plain progress lines instead. CI and terminals without an interactive session

117use plain progress automatically.

118 

112By default, the CLI writes scan progress and its completion summary to stderr.119By default, the CLI writes scan progress and its completion summary to stderr.

113It doesn't print the full scan result to stdout. A completed scan prints a120It doesn't print the full scan result to stdout. A completed scan prints a

114summary like this:121summary like this:


203npx @openai/codex-security scan "$REPOSITORY" --mode deep210npx @openai/codex-security scan "$REPOSITORY" --mode deep

204```211```

205 212 

206Deep mode supports repository and path targets, not diff or working-tree scans.213To control discovery workers, subagents, and when the scan stops:

214 

215```bash

216npx @openai/codex-security scan "$REPOSITORY" \

217 --mode deep \

218 --workers 2 \

219 --subagents 0 \

220 --stop-after-no-new 3 \

221 --max-discovery-runs 10

222```

223 

224These options require deep mode, which supports repository and path targets,

225not diff or working-tree scans. Here, `--workers` controls discovery workers

226within one scan; `bulk-scan --workers` controls concurrent repository scans.

207 227 

208## Add architecture and security context228## Add architecture and security context

209 229 


217 --knowledge-base /path/to/security-policies237 --knowledge-base /path/to/security-policies

218```238```

219 239 

240## Add custom scan instructions

241 

242Add instructions that focus the scan on your security priorities. Use a

243second file for a follow-up after a validated scan with complete coverage:

244 

245```bash

246npx @openai/codex-security scan "$REPOSITORY" \

247 --scan-prompt-file /path/to/scan.md \

248 --post-scan-prompt-file /path/to/follow-up.md

249```

250 

251The follow-up runs in the same authenticated session. Both options also work

252with `bulk-scan`; a CSV `prompt` column adds repository-specific instructions.

253 

220## Set a scan budget254## Set a scan budget

221 255 

222Use `--max-cost` to stop a scan when its estimated model cost exceeds a limit256Use `--max-cost` to stop a scan when its estimated model cost exceeds a limit


226npx @openai/codex-security scan "$REPOSITORY" --max-cost 5260npx @openai/codex-security scan "$REPOSITORY" --max-cost 5

227```261```

228 262 

229Requests already in progress can finish above the limit. Codex Security keeps263Requests already in progress can finish slightly above the limit. If a scan

230the available results when a scan stops.264aborts due to the cost limit, partial scan results remain available on disk.

231 265 

232## Scan changes before each commit266## Scan changes before each commit

233 267 


266 --workers 4300 --workers 4

267```301```

268 302 

269Run the same command again to resume an existing bulk scan. Completed303Run the same command again to resume an existing bulk scan. Codex Security

270repositories with intact result artifacts aren't scanned again. Add304skips completed repositories. Add `--max-attempts 3` when you want to retry

271`--max-attempts 3` when you want to retry temporary repository or scan errors.305temporary repository or scan errors.

272 306 

273For GitHub discovery, CSV preparation, campaign results, and Docker setup, see307For GitHub discovery, CSV preparation, campaign results, and Docker setup, see

274[Run bulk security scans](https://learn.chatgpt.com/docs/security/cli/bulk-scans).308[Run bulk security scans](https://learn.chatgpt.com/docs/security/cli/bulk-scans).


288 --workers 4322 --workers 4

289```323```

290 324 

291The container runs bulk scans without prompts. Use the CLI outside Docker when325The container runs bulk scans without interactive prompts. Use the CLI outside

292you want to discover repositories interactively. For private repositories,326Docker when you want to discover repositories interactively. For private

293provide `GH_TOKEN` or `GITHUB_TOKEN` through your environment or secret327repositories, provide `GH_TOKEN` or `GITHUB_TOKEN` through your environment or

294manager. The [sign-in requirements](#sign-in), including account and repository328secret manager. The [sign-in requirements](#sign-in), including account and

295access, also apply to containerized scans.329repository access, also apply to containerized scans.

296 330 

297## Revisit a saved scan331## Revisit a saved scan

298 332 


324npx @openai/codex-security scans rerun SCAN_ID358npx @openai/codex-security scans rerun SCAN_ID

325```359```

326 360 

327To compare two scans, first match findings that share the same root cause:361Compare two scans to find new, persisting, reopened, resolved, or unknown

328 362findings:

329```bash

330npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

331```

332 

333Then check which findings are new, persisting, reopened, resolved, or unknown:

334 363 

335```bash364```bash

336npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID365npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

337```366```

338 367 

368The comparison automatically matches findings by root cause and reuses saved

369matches.

370 

339For the bulk-scan CSV format, scan-history filters, and command options, see371For the bulk-scan CSV format, scan-history filters, and command options, see

340the [CLI reference](https://learn.chatgpt.com/docs/security/cli/reference).372the [CLI reference](https://learn.chatgpt.com/docs/security/cli/reference).

341 373 

Details

68Create a CSV with one row for each repository and pinned revision:68Create a CSV with one row for each repository and pinned revision:

69 69 

70```csv70```csv

71id,repository,revision,scope,mode71id,repository,revision,scope,mode,prompt

72payments,https://github.com/example/payments.git,0123456789abcdef0123456789abcdef01234567,services/api,standard72payments,https://github.com/example/payments.git,0123456789abcdef0123456789abcdef01234567,services/api,standard,Review payment authorization and refunds.

73identity,https://github.com/example/identity.git,fedcba9876543210fedcba9876543210fedcba98,,deep73identity,https://github.com/example/identity.git,fedcba9876543210fedcba9876543210fedcba98,,deep,Review session and identity boundaries.

74```74```

75 75 

76The CSV supports these columns:76The CSV supports these columns:


82| `revision` | Yes | Full 40- or 64-character Git commit SHA. Branch names, tags, and shortened commit hashes aren't supported. |82| `revision` | Yes | Full 40- or 64-character Git commit SHA. Branch names, tags, and shortened commit hashes aren't supported. |

83| `scope` | No | A repository-relative directory to scan. Omit the value to scan the full repository. |83| `scope` | No | A repository-relative directory to scan. Omit the value to scan the full repository. |

84| `mode` | No | `standard` or `deep`. Omit the value to use the command's selected mode. |84| `mode` | No | `standard` or `deep`. Omit the value to use the command's selected mode. |

85| `prompt` | No | Scan instructions specific to this repository. |

85 86 

86To find a local repository's full commit SHA, run:87To find a local repository's full commit SHA, run:

87 88 


99 --workers 4100 --workers 4

100```101```

101 102 

102`--workers` controls the number of concurrent repository scans and defaults to103`--workers` controls concurrent repository scans and defaults to `4`. It does

103`4`. Use `--mode deep` to select deep scanning for rows without their own104not set the number of discovery workers within each deep scan; configure those

104`mode`. Each CSV row can still choose its own scan mode and repository scope.105limits through [`[deep_scan]`](/codex/security/cli/reference#configure-deep-scans).

106Use `--mode deep` to select deep scanning for rows without their own `mode`.

107Each CSV row can still choose its own scan mode and repository scope.

105 108 

106The CLI checks out each pinned revision, scans the selected target, records the109The CLI checks out each pinned revision, scans the selected target, records the

107result, and removes the temporary repository checkout. A repository counts as110result, and removes the temporary repository checkout. A repository counts as

108complete only when its scan has complete coverage and all required result111complete only when its scan has complete coverage and all required result

109artifacts exist.112artifacts exist.

110 113 

114## Share security context and instructions

115 

116Add architecture documents, threat models, or security policies to every scan

117with `--knowledge-base`. Repeat the flag for more files or directories:

118 

119```bash

120npx @openai/codex-security bulk-scan repositories.csv \

121 --output-dir /path/outside/repositories/security-scans \

122 --knowledge-base /path/to/architecture.md \

123 --knowledge-base /path/to/security-policies

124```

125 

126To add shared scan instructions or run a follow-up after each completed scan,

127provide prompt files:

128 

129```bash

130npx @openai/codex-security bulk-scan repositories.csv \

131 --output-dir /path/outside/repositories/security-scans \

132 --scan-prompt-file scan-instructions.md \

133 --post-scan-prompt-file follow-up.md

134```

135 

136The CLI appends each repository's CSV `prompt` after the shared scan

137instructions. Follow-up instructions run in the same authenticated session only

138after a validated scan has complete coverage. Prompt file paths resolve from

139your current directory.

140 

111## Choose a model and reasoning effort141## Choose a model and reasoning effort

112 142 

113Bulk scans use `gpt-5.6-sol` with `xhigh` reasoning effort by default. To143Bulk scans use `gpt-5.6-sol` with `xhigh` reasoning effort by default. To


129 159 

130Supported effort levels are `minimal`, `low`, `medium`, `high`, and `xhigh`.160Supported effort levels are `minimal`, `low`, `medium`, `high`, and `xhigh`.

131 161 

162To use OpenRouter or Fireworks, set `OPENROUTER_API_KEY` or `FIREWORKS_API_KEY`,

163respectively, and specify `--provider` and `--model`. For credentials and

164examples, see [OpenRouter or Fireworks

165setup](https://learn.chatgpt.com/docs/security/cli/reference#use-openrouter-or-fireworks) or [Amazon

166Bedrock setup](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock).

167 

132## Review campaign results168## Review campaign results

133 169 

134The output directory contains the pinned campaign, an append-only results170The output directory contains the pinned campaign, an append-only results


154 └── report.md190 └── report.md

155```191```

156 192 

157- `manifest.json` records the repositories, pinned revisions, scopes, and scan193- `manifest.json` records the repositories, pinned revisions, scopes, scan

158 modes in the campaign.194 modes, and shared or repository-specific instructions in the campaign.

159- `results.jsonl` records each repository attempt, its status, artifact195- `results.jsonl` records each repository attempt, its status, artifact

160 directory, and any available cost or error details.196 directory, and any available cost or error details.

161- `report.md` provides a readable report for one repository attempt.197- `report.md` provides a readable report for one repository attempt.


185 --workers 4221 --workers 4

186```222```

187 223 

188The CLI resumes repositories that still need work. It skips a completed224The CLI resumes unfinished repository scans and skips completed ones. Scans

189repository only when the corresponding receipt and all required scan artifacts225with incomplete coverage aren't retried. Their results remain available, and

190still exist.226the command exits with code `2`.

191 227 

192Don't change the repository inventory for an existing output directory. The CLI228Don't change the repository inventory or scan and follow-up instructions for

193checks the pinned manifest and rejects a different campaign. Use a new output229an existing output directory. The CLI checks the pinned manifest and rejects a

194directory when you change repositories, revisions, scopes, or scan modes.230different campaign. Use a new output directory when you change repositories,

231revisions, scopes, scan modes, or shared or repository-specific instructions.

195 232 

196## Retry repository errors233## Retry repository errors

197 234 


206```243```

207 244 

208The default is one attempt per repository. Every attempt receives its own245The default is one attempt per repository. Every attempt receives its own

209receipt and artifact directory.246receipt and artifact directory. Retries cover checkout errors, scan failures,

247and missing required artifacts. Completed scans with incomplete coverage

248aren't retried.

210 249 

211Bulk scans use these exit codes:250Bulk scans use these exit codes:

212 251 

Details

24 24 

25The runner needs:25The runner needs:

26 26 

27- Node.js 22 or later.27- Node.js 22.13.0 or later.

28- Python 3.10 or later.28- Python 3.10 or later.

29- The published `@openai/codex-security` package, installed outside the29- The published `@openai/codex-security` package, installed outside the

30 repository checkout.30 repository checkout.

Details

71### Can an interrupted bulk scan resume71### Can an interrupted bulk scan resume

72 72 

73Yes. Run the same bulk-scan command with the original CSV and output directory.73Yes. Run the same bulk-scan command with the original CSV and output directory.

74Codex Security skips completed repositories when their recorded scan artifacts74Codex Security skips completed repositories.

75remain intact.

76 75 

77Add `--max-attempts 3` to retry temporary repository or scan errors:76Add `--max-attempts 3` to retry temporary repository or scan errors:

78 77 


83 --max-attempts 382 --max-attempts 3

84```83```

85 84 

85A completed scan with `partial` or `unknown` coverage keeps its results and

86causes the campaign to exit with code `2`. It isn't retried, even with

87`--max-attempts`.

88 

86### How can a scan use architecture and security policies89### How can a scan use architecture and security policies

87 90 

88Pass architecture documents, threat models, or security policies with91Pass architecture documents, threat models, or security policies with


130 133 

131### How do scans distinguish new and known findings134### How do scans distinguish new and known findings

132 135 

133Match findings that share a root cause across the two scans:136Compare findings across the two scans:

134 

135```bash

136npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

137```

138 

139Compare the matched findings:

140 137 

141```bash138```bash

142npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID139npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

143```140```

144 141 

145The comparison identifies new, persisting, reopened, resolved, and unknown142The comparison automatically matches findings by root cause, reuses saved

143matches, and identifies new, persisting, reopened, resolved, and unknown

146findings. A finding counts as resolved only when the later scan covers its144findings. A finding counts as resolved only when the later scan covers its

147original target and affected path without coverage gaps.145original target and affected path without coverage gaps.

148 146 


177npx @openai/codex-security scans rerun BASELINE_SCAN_ID175npx @openai/codex-security scans rerun BASELINE_SCAN_ID

178```176```

179 177 

180Match the baseline findings to the new scan:178Compare the baseline with the new scan:

181 

182```bash

183npx @openai/codex-security scans match BASELINE_SCAN_ID REPEAT_SCAN_ID

184```

185 

186Compare the matched results:

187 179 

188```bash180```bash

189npx @openai/codex-security scans compare BASELINE_SCAN_ID REPEAT_SCAN_ID181npx @openai/codex-security scans compare BASELINE_SCAN_ID REPEAT_SCAN_ID


202npx @openai/codex-security scans rerun BEFORE_SCAN_ID194npx @openai/codex-security scans rerun BEFORE_SCAN_ID

203```195```

204 196 

205Match the original findings to the new scan:197Compare the original findings with the new scan:

206 

207```bash

208npx @openai/codex-security scans match BEFORE_SCAN_ID AFTER_SCAN_ID

209```

210 

211Compare the matched findings:

212 198 

213```bash199```bash

214npx @openai/codex-security scans compare BEFORE_SCAN_ID AFTER_SCAN_ID200npx @openai/codex-security scans compare BEFORE_SCAN_ID AFTER_SCAN_ID

Details

116 [--provider {openai,openrouter,fireworks,amazon-bedrock}]116 [--provider {openai,openrouter,fireworks,amazon-bedrock}]

117 [--path PATH | --diff BASE | --working-tree]117 [--path PATH | --diff BASE | --working-tree]

118 [--head HEAD] [--base BASE]118 [--head HEAD] [--base BASE]

119 [--knowledge-base PATH]119 [--knowledge-base PATH] [--scan-prompt-file FILE]

120 [--mode {standard,deep}] [--model MODEL]120 [--post-scan-prompt-file FILE]

121 [--mode {standard,deep}] [--workers N]

122 [--subagents N] [--stop-after-no-new N]

123 [--max-discovery-runs N] [--model MODEL]

121 [--effort {minimal,low,medium,high,xhigh}]124 [--effort {minimal,low,medium,high,xhigh}]

122 [--output-dir DIR]125 [--output-dir DIR]

123 [--archive-existing]126 [--archive-existing]

124 [--plugin-path PATH] [--python PATH]127 [--plugin-path PATH] [--python PATH]

125 [--codex KEY=VALUE] [--fail-on-severity LEVEL]128 [--codex KEY=VALUE] [--fail-on-severity LEVEL]

126 [--max-cost USD] [--dry-run] [--verbose]129 [--max-cost USD] [--dry-run] [--headless] [--verbose]

127 [--json] [--format {toon,json,yaml,jsonl}]130 [--json] [--format {toon,json,yaml,jsonl}]

128 [--full-output] [repository]131 [--full-output] [repository]

129```132```


153To make stored credentials the automatic default, run156To make stored credentials the automatic default, run

154`unset OPENAI_API_KEY CODEX_API_KEY`.157`unset OPENAI_API_KEY CODEX_API_KEY`.

155 158 

159### Use OpenRouter or Fireworks

160 

161Select OpenRouter with its API key and an explicit model:

162 

163```bash

164export OPENROUTER_API_KEY="your-openrouter-api-key"

165npx @openai/codex-security scan . \

166 --provider openrouter \

167 --model anthropic/claude-sonnet-4.5

168```

169 

170Select Fireworks with its API key and an explicit model:

171 

172```bash

173export FIREWORKS_API_KEY="your-fireworks-api-key"

174npx @openai/codex-security scan . \

175 --provider fireworks \

176 --model accounts/fireworks/models/qwen3-235b-a22b

177```

178 

179Both providers also support `bulk-scan`.

180 

156### Use Amazon Bedrock181### Use Amazon Bedrock

157 182 

158Select Amazon Bedrock with `--provider amazon-bedrock` and specify an explicit183Select Amazon Bedrock with `--provider amazon-bedrock` and specify an explicit


220npx @openai/codex-security scan . --mode deep245npx @openai/codex-security scan . --mode deep

221```246```

222 247 

248### Configure deep scans

249 

250Use these options with `--mode deep` to control discovery concurrency and

251runtime:

252 

253| Argument | Description |

254| ------------------------ | ----------------------------------------------------------------------- |

255| `--workers N` | Limit on concurrent discovery workers. Defaults to automatic selection. |

256| `--subagents N` | Subagents available to each discovery worker. Defaults to `3`. |

257| `--stop-after-no-new N` | Stop after `N` consecutive runs find no new issues. Defaults to `6`. |

258| `--max-discovery-runs N` | Limit on total discovery runs. Defaults to `60`. |

259 

260`--subagents` accepts zero or a positive integer. The other options require a

261positive integer. These options aren't available for standard scans.

262 

263For example, limit a deep scan to two discovery workers and ten total runs:

264 

265```bash

266npx @openai/codex-security scan . \

267 --mode deep \

268 --workers 2 \

269 --subagents 0 \

270 --stop-after-no-new 3 \

271 --max-discovery-runs 10

272```

273 

274Set persistent defaults in `~/.codex/codex-security/config.toml`, or in

275`$CODEX_HOME/codex-security/config.toml` when you set `CODEX_HOME`:

276 

277```toml

278[deep_scan]

279workers = 2

280subagents = 0

281stop_after_no_new = 3

282max_discovery_runs = 10

283```

284 

285Command-line options override these defaults. `scan --workers` controls

286discovery workers within one scan; `bulk-scan --workers` controls concurrent

287repository scans.

288 

223### Add security context289### Add security context

224 290 

225Use `--knowledge-base PATH` to provide architecture documents, threat models,291Use `--knowledge-base PATH` to provide architecture documents, threat models,


236skips linked directory entries, and keeps extracted document content302skips linked directory entries, and keeps extracted document content

237outside the saved scan results.303outside the saved scan results.

238 304 

305### Add scan instructions

306 

307To add scan instructions, provide a text or Markdown file with

308`--scan-prompt-file`. Use `--post-scan-prompt-file` to run follow-up

309instructions in the same authenticated session after a completed scan with

310complete coverage:

311 

312```bash

313npx @openai/codex-security scan . \

314 --scan-prompt-file security-focus.md \

315 --post-scan-prompt-file follow-up.md

316```

317 

318For example, use the scan prompt to focus on authorization boundaries and ask

319the follow-up to write a new `post-scan-summary.md` in the scan directory.

320 

239### Set output and policy options321### Set output and policy options

240 322 

241Use these options to keep artifacts, preserve earlier results, or create a323Use these options to keep artifacts, preserve earlier results, or create a


247| `--archive-existing` | Move existing results to `DIR.previous-<timestamp>-<id>` and start with an empty output directory. Requires `--output-dir`. |329| `--archive-existing` | Move existing results to `DIR.previous-<timestamp>-<id>` and start with an empty output directory. Requires `--output-dir`. |

248| `--fail-on-severity LEVEL` | Return exit `1` when a completed scan reports a finding at or above `critical`, `high`, `medium`, or `low`. |330| `--fail-on-severity LEVEL` | Return exit `1` when a completed scan reports a finding at or above `critical`, `high`, `medium`, or `low`. |

249| `--max-cost USD` | Stop a scan when its estimated model cost exceeds the specified USD amount. |331| `--max-cost USD` | Stop a scan when its estimated model cost exceeds the specified USD amount. |

250| `--dry-run` | Check the repository, target, output directory, and Codex configuration without starting a scan. |332| `--dry-run` | Check the repository, target, knowledge base, output directory, and Codex configuration without starting a scan. |

333| `--headless` | Show plain-text progress instead of the interactive scan dashboard. |

251| `--verbose` | Print redacted lifecycle, authentication, progress, and cost diagnostics to stderr. |334| `--verbose` | Print redacted lifecycle, authentication, progress, and cost diagnostics to stderr. |

252| `--json` | Print manifest, findings, coverage, paths, and turn metadata as one JSON document. |335| `--json` | Print manifest, findings, coverage, paths, and turn metadata as one JSON document. |

253| `--format FORMAT` | Print the complete scan result as `toon`, `json`, `yaml`, or `jsonl`. |336| `--format FORMAT` | Print the complete scan result as `toon`, `json`, `yaml`, or `jsonl`. |

254| `--full-output` | Print the complete result using the default structured output format. |337| `--full-output` | Print the complete result using the default structured output format. |

255 338 

256The cost limit is an estimate, not a hard spending cap. Requests already in339The cost limit is an estimate, not a hard spending cap. Requests already in

257progress can finish above the limit, and partial scan results remain available.340progress can finish slightly above the limit. If a scan aborts due to the cost

341limit, partial scan results remain available on disk.

258 342 

259When you omit `--output-dir`, results persist under343When you omit `--output-dir`, results persist under

260`$CODEX_HOME/state/plugins/codex-security/scans/<repository>`. `CODEX_HOME`344`$CODEX_HOME/state/plugins/codex-security/scans/<repository>`. `CODEX_HOME`


291 > /path/outside/repository/codex-security.json375 > /path/outside/repository/codex-security.json

292```376```

293 377 

294A dry run checks local inputs without loading credentials, starting Codex, or378A dry run checks local inputs, including knowledge-base documents, without

295probing the plugin's Python interpreter:379loading credentials, starting Codex, or probing the plugin's Python

380interpreter:

296 381 

297```bash382```bash

298npx @openai/codex-security scan . \383npx @openai/codex-security scan . \


309| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |394| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |

310| `--auth {auto,chatgpt,api-key}` | Select the scan credentials. The default is `auto`. |395| `--auth {auto,chatgpt,api-key}` | Select the scan credentials. The default is `auto`. |

311| `--provider {openai,openrouter,fireworks,amazon-bedrock}` | Select the inference provider. The default is `openai`. |396| `--provider {openai,openrouter,fireworks,amazon-bedrock}` | Select the inference provider. The default is `openai`. |

312| `--model MODEL` | Select the model. The default is `gpt-5.6-sol`. Required with `--provider amazon-bedrock`. |397| `--model MODEL` | Select the model. The default is `gpt-5.6-sol`. Required for OpenRouter, Fireworks, and Amazon Bedrock. |

313| `--effort {minimal,low,medium,high,xhigh}` | Select the model's reasoning effort. The default is `xhigh`. |398| `--effort {minimal,low,medium,high,xhigh}` | Select the model's reasoning effort. The default is `xhigh`. |

314| `--plugin-path PATH` | Use a Codex Security plugin directory or ZIP to override the bundled plugin. |399| `--plugin-path PATH` | Use a Codex Security plugin directory or ZIP to override the bundled plugin. |

315| `--python PATH` | Select the Python interpreter for the plugin runtime. |400| `--python PATH` | Select the Python interpreter for the plugin runtime. |


360 [--provider {openai,openrouter,fireworks,amazon-bedrock}]445 [--provider {openai,openrouter,fireworks,amazon-bedrock}]

361 [--model MODEL]446 [--model MODEL]

362 [--effort {minimal,low,medium,high,xhigh}]447 [--effort {minimal,low,medium,high,xhigh}]

448 [--knowledge-base PATH]

449 [--scan-prompt-file FILE]

450 [--post-scan-prompt-file FILE]

363 [--max-attempts N] [--plugin-path PATH]451 [--max-attempts N] [--plugin-path PATH]

364 [--python PATH] [--codex KEY=VALUE]452 [--python PATH] [--codex KEY=VALUE]

365```453```


382```470```

383 471 

384The CSV requires `id`, `repository`, and `revision` columns. Revisions must be472The CSV requires `id`, `repository`, and `revision` columns. Revisions must be

385full commit hashes. Optional `scope` and `mode` columns configure individual473full commit hashes. Optional `scope`, `mode`, and `prompt` columns configure

386repositories:474individual repositories:

387 475 

388```csv476```csv

389id,repository,revision,scope,mode477id,repository,revision,scope,mode,prompt

390service,https://github.com/example/service.git,0123456789abcdef0123456789abcdef01234567,src,standard478service,https://github.com/example/service.git,0123456789abcdef0123456789abcdef01234567,src,standard,Review authorization boundaries.

391```479```

392 480 

393`--workers` limits simultaneous scans and defaults to `4`. `--mode` defaults to481Use `--knowledge-base PATH` to share security documents across every

394`standard`, and `--max-attempts` defaults to `1`. Set `--max-attempts` when482repository. Use `--scan-prompt-file FILE` to add shared scan instructions; the

395you want to retry a repository after an error. Run the same command again to483CSV `prompt` column adds repository-specific instructions after that shared

396resume a bulk scan from its existing output directory. The CLI skips completed484prompt. `--post-scan-prompt-file FILE` runs follow-up instructions after each

397repositories only when their recorded result artifacts are still present.485completed scan with complete coverage.

486 

487`--workers` limits simultaneous repository scans and defaults to `4`. `--mode`

488defaults to `standard`, and `--max-attempts` defaults to `1`. Set

489`--max-attempts` to retry repository or scan errors. Completed scans with

490incomplete coverage aren't retried. Their results remain available, and the

491command returns exit code `2`.

492 

493Run the same command again to resume from an existing output directory. The CLI

494skips completed scans, including scans with incomplete coverage.

398 495 

399For containerized campaigns, see [Run bulk scans in496For containerized campaigns, see [Run bulk scans in

400Docker](https://learn.chatgpt.com/docs/security/cli/bulk-scans#run-bulk-scans-in-docker).497Docker](https://learn.chatgpt.com/docs/security/cli/bulk-scans#run-bulk-scans-in-docker).


437 534 

438### Match and compare findings535### Match and compare findings

439 536 

440Match findings that share the same root cause across two scans:537Compare two scans to find new, persisting, reopened, resolved, and unknown

538findings:

441 539 

442```bash540```bash

443npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID541npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID

444```542```

445 543 

446Compare the matched scans to find new, persisting, reopened, resolved, and544The comparison automatically matches findings that share the same root cause

447unknown findings:545and reuses saved matches. To save matches explicitly, use `scans match`:

448 546 

449```bash547```bash

450npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID548npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID

451```549```

452 550 

453A finding is unknown when the later scan has incomplete coverage or doesn't551A finding is unknown when the later scan has incomplete coverage or doesn't


639without writing the complete scan result to stdout. Request `--json`,737without writing the complete scan result to stdout. Request `--json`,

640`--format`, or `--full-output` to send structured scan results to stdout.738`--format`, or `--full-output` to send structured scan results to stdout.

641 739 

740Interactive terminals show a live dashboard with the current scan phase,

741reviewed files, activity, token usage, and estimated cost. CI and redirected

742output use plain-text progress. Add `--headless` to use plain-text progress in

743an interactive terminal:

744 

745```bash

746npx @openai/codex-security scan . --headless

747```

748 

642### Verbose diagnostics749### Verbose diagnostics

643 750 

644Add `--verbose` to print redacted lifecycle, authentication, progress, and cost751Add `--verbose` to print redacted lifecycle, authentication, progress, and cost


758 865 

759Set `OPENAI_API_KEY` or `CODEX_API_KEY`, sign in with866Set `OPENAI_API_KEY` or `CODEX_API_KEY`, sign in with

760`npx @openai/codex-security login`, or use an existing file-backed Codex867`npx @openai/codex-security login`, or use an existing file-backed Codex

761sign-in. For Amazon Bedrock, use a Bedrock API key or the standard AWS868sign-in. For OpenRouter or Fireworks, set the provider's API key and select a

869model. For Amazon Bedrock, use a Bedrock API key or the standard AWS

762credential chain instead.870credential chain instead.

763 871 

764For credential selection, see [Select scan872For credential selection, see [Select scan


766 874 

767For CI, keep the API key scoped to the scan step and use a trusted workflow.875For CI, keep the API key scoped to the scan step and use a trusted workflow.

768 876 

769The CLI requires Node.js 22 or later. Running a scan or exporting findings also877The CLI requires Node.js 22.13.0 or later. Running a scan or exporting findings

770requires Python 3.10 or later. Python 3.10 also requires `tomli`. Use `--python`878also requires Python 3.10 or later. Python 3.10 also requires `tomli`. Use

771or `PYTHON` to select an interpreter when automatic discovery is unsuitable.879`--python` or `PYTHON` to select an interpreter when automatic discovery is

880unsuitable.

772 881 

773Continue with the [CLI quickstart](https://learn.chatgpt.com/docs/security/cli), [bulk-scan882Continue with the [CLI quickstart](https://learn.chatgpt.com/docs/security/cli), [bulk-scan

774guide](https://learn.chatgpt.com/docs/security/cli/bulk-scans), [CLI FAQ](https://learn.chatgpt.com/docs/security/cli/faq), [CI883guide](https://learn.chatgpt.com/docs/security/cli/bulk-scans), [CLI FAQ](https://learn.chatgpt.com/docs/security/cli/faq), [CI

security/sdk.md +72 −12

Details

7findings, coverage details, and paths to scan artifacts. For longer scans, it7findings, coverage details, and paths to scan artifacts. For longer scans, it

8supports preflight checks, cost limits, progress callbacks, and cancellation.8supports preflight checks, cost limits, progress callbacks, and cancellation.

9 9 

10The SDK uses ECMAScript modules (ESM) and runs server-side with Node.js 22 or10The SDK uses ECMAScript modules (ESM) and runs server-side with Node.js 22.13.0

11later. Scanning also requires Python 3.10 or later.11or later. Scanning also requires Python 3.10 or later.

12 12 

13The Codex Security SDK is [publicly available on13The Codex Security SDK is [publicly available on

14 GitHub](https://github.com/openai/codex-security). Running scans requires14 GitHub](https://github.com/openai/codex-security). Running scans requires


25```25```

26 26 

27Before starting a scan, set `OPENAI_API_KEY` or `CODEX_API_KEY`, use an27Before starting a scan, set `OPENAI_API_KEY` or `CODEX_API_KEY`, use an

28existing file-backed Codex sign-in, or [configure Amazon28existing file-backed Codex sign-in, or [configure another

29Bedrock](#configure-the-runtime-and-credentials) with AWS credentials and29provider](#configure-the-runtime-and-credentials). Amazon Bedrock uses AWS

30explicit `model_provider` and `model` overrides.30credentials; OpenRouter and Fireworks use provider-specific API keys and

31configuration.

31 32 

32For best results, use an account verified for [Trusted Access for33For best results, use an account verified for [Trusted Access for

33Cyber](https://chatgpt.com/cyber). Signing in or providing an API key does not34Cyber](https://chatgpt.com/cyber). Signing in or providing an API key does not


67 68 

68## Check inputs with preflight69## Check inputs with preflight

69 70 

70Use `preflight` to check a repository, target, mode, output location, and71Use `preflight` to check a repository, target, mode, knowledge-base documents,

71Codex configuration before starting a scan:72output location, and Codex configuration before starting a scan:

72 73 

73```ts74```ts

74const plan = await security.preflight("/path/to/repository", {75const plan = await security.preflight("/path/to/repository", {

75 target: ["services/billing", "packages/auth"],76 target: ["services/billing", "packages/auth"],

77 knowledgeBasePaths: ["/path/to/architecture.md"],

76 outputDir: "/path/outside/repository/results",78 outputDir: "/path/outside/repository/results",

77});79});

78 80 


173const result = await security.run("/path/to/repository", {175const result = await security.run("/path/to/repository", {

174 target: ["services/billing"],176 target: ["services/billing"],

175 mode: "deep",177 mode: "deep",

178 workers: 2,

179 subagents: 0,

180 stopAfterNoNew: 3,

181 maxDiscoveryRuns: 10,

176});182});

177```183```

178 184 

179Deep mode supports repository and path targets. Use standard mode for diff and185Deep mode supports repository and path targets. Use standard mode for diff and

180working-tree scans.186working-tree scans. The optional settings control concurrent discovery workers,

187subagents per worker, consecutive discovery runs without new findings, and the

188total number of discovery runs. They require `mode: "deep"`.

181 189 

182### Add a security knowledge base190### Add a security knowledge base

183 191 


198The SDK rejects linked input paths, skips linked directory entries, and keeps206The SDK rejects linked input paths, skips linked directory entries, and keeps

199extracted document content outside the saved scan results.207extracted document content outside the saved scan results.

200 208 

209### Add scan and follow-up instructions

210 

211Use `scanPrompt` to focus the scan and `postScanPrompt` to request a follow-up

212after a completed scan:

213 

214```ts

215const result = await security.run("/path/to/repository", {

216 scanPrompt: "Focus on tenant isolation and authorization checks.",

217 postScanPrompt: "Write confirmed findings to post-scan-summary.md.",

218});

219```

220 

221The follow-up runs in the same authenticated session only after the scan

222finishes with complete coverage.

223 

201### Set a scan budget224### Set a scan budget

202 225 

203Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.226Set `maxCostUsd` to stop a scan when its estimated model cost exceeds a limit.


214console.log(result.cost?.estimatedUsd);237console.log(result.cost?.estimatedUsd);

215```238```

216 239 

217The limit is an estimate, not a hard spending cap. Requests already in progress240The limit estimates spending but isn't a hard cap, so requests already in

218can finish above it. If the scan exceeds the limit, the SDK throws241progress can finish slightly above it. If the scan exceeds the limit, the SDK

219`ScanCostLimitExceededError` and preserves the available results.242throws `ScanCostLimitExceededError` and preserves the available results.

220 243 

221## Work with scan results244## Work with scan results

222 245 


278 onScanStarted() {301 onScanStarted() {

279 console.log("Scan started");302 console.log("Scan started");

280 },303 },

304 onProgress(progress) {

305 console.log(progress.phase, progress.filesCompleted, progress.filesTotal);

306 },

281 onWorkerStatus(status) {307 onWorkerStatus(status) {

282 console.log(status.kind, status);308 console.log(status.kind, status);

283 },309 },


324lifecycle callbacks:350lifecycle callbacks:

325 351 

326| Callback | Called when |352| Callback | Called when |

327| ----------------------------------- | ------------------------------------------------ |353| ----------------------------------- | ---------------------------------------------------- |

354| `onAuthentication(authentication)` | The scan selects its authentication method. |

328| `onOutputArchived(archiveDir)` | Existing results move to the archive directory. |355| `onOutputArchived(archiveDir)` | Existing results move to the archive directory. |

329| `onOutputDirReady(scanDir)` | The private scan directory is ready. |356| `onOutputDirReady(scanDir)` | The private scan directory is ready. |

330| `onScanStarted()` | Scan setup completes and execution begins. |357| `onScanStarted()` | Scan setup completes and execution begins. |

358| `onTrustedAccessStatus(status)` | Trusted Access status becomes available. |

331| `onReconnect(attempt, maxAttempts)` | The SDK retries a disconnected scan stream. |359| `onReconnect(attempt, maxAttempts)` | The SDK retries a disconnected scan stream. |

360| `onActivity(activity)` | A command, tool, reasoning step, or message updates. |

361| `onProgress(progress)` | The scan phase or reviewed file count changes. |

332| `onWorkerStatus(status)` | Worker preflight or dispatch status changes. |362| `onWorkerStatus(status)` | Worker preflight or dispatch status changes. |

333| `onCost(cost)` | An updated estimated scan cost is available. |363| `onCost(cost)` | An updated estimated scan cost is available. |

364| `onWarning(warning)` | The scan reports a warning. |

334| `onObserverError(observer, error)` | Another scan lifecycle callback raises an error. |365| `onObserverError(observer, error)` | Another scan lifecycle callback raises an error. |

335 366 

367Trusted Access status is `granted`, `not_granted`, or `unknown`. Missing or

368unknown access also triggers `onWarning`.

369 

336## Configure the runtime and credentials370## Configure the runtime and credentials

337 371 

338Pass runtime configuration when you need a specific plugin, interpreter, or372Pass runtime configuration when you need a specific plugin, interpreter, or


357Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set391Bedrock](https://learn.chatgpt.com/docs/security/cli/reference#use-amazon-bedrock), set

358`model_provider` and `model` in `codexOverrides`.392`model_provider` and `model` in `codexOverrides`.

359 393 

394For OpenRouter or Fireworks, also provide the matching API key and a complete

395provider configuration in `codexOverrides`. For example, set

396`OPENROUTER_API_KEY` and configure OpenRouter:

397 

398```ts

399const security = new CodexSecurity({

400 codexOverrides: {

401 model: "anthropic/claude-sonnet-4.5",

402 model_provider: "openrouter",

403 model_providers: {

404 openrouter: {

405 name: "OpenRouter",

406 base_url: "https://openrouter.ai/api/v1",

407 env_key: "OPENROUTER_API_KEY",

408 wire_api: "responses",

409 },

410 },

411 },

412});

413```

414 

415For Fireworks, change both `openrouter` keys to `fireworks`, set `name` to

416`Fireworks AI`, set `env_key` to `FIREWORKS_API_KEY`, use

417`https://api.fireworks.ai/inference/v1` as `base_url`, and select a Fireworks

418model.

419 

360The client also exposes supported authentication methods:420The client also exposes supported authentication methods:

361 421 

362| Method | Purpose |422| Method | Purpose |