|
1 | 1 | # Codex Security |
2 | 2 |
|
3 | | -Codex Security is an open-source CLI and TypeScript SDK for finding, validating, |
4 | | -and reviewing security issues in code you own or have permission to assess. |
| 3 | +`@openai/codex-security` is a CLI and TypeScript SDK for finding, validating, and fixing security vulnerabilities in your code. Scan repositories, review changes, track findings over time, and run security checks in CI. |
5 | 4 |
|
6 | | -> [!NOTE] |
7 | | -> This package follows semantic versioning. Its public API may change between |
8 | | -> minor versions before `1.0.0`. |
| 5 | +**[Documentation](http://learn.chatgpt.com/docs/security/cli)** |
9 | 6 |
|
10 | | -## Requirements |
| 7 | +## Quick start |
11 | 8 |
|
12 | | -The SDK and CLI support macOS, Linux, and Windows and require Node.js 22 or |
13 | | -later. Scanning and exporting findings also require Python 3.10 or later. If |
14 | | -you use Python 3.10, install the `tomli` package. Python is not needed to |
15 | | -install the package or run `--help` and `--version`. |
16 | | - |
17 | | -Sign in with your OpenAI account or provide an OpenAI API key before running a |
18 | | -scan. Scan only repositories you own or have explicit permission to assess. |
19 | | - |
20 | | -## Install and scan |
| 9 | +Requires Node.js 22 or later, Python 3.10 or later, and access to Codex Security. |
21 | 10 |
|
22 | 11 | ```bash |
23 | 12 | npm install @openai/codex-security |
24 | 13 | npx codex-security login |
25 | | -npx codex-security scan /path/to/repo |
26 | | -``` |
27 | | - |
28 | | -Run `npx codex-security --help` to see all commands and |
29 | | -`npx codex-security scan --help` for scan options. |
30 | | - |
31 | | -On a remote or headless machine, use `npx codex-security login --device-auth`. |
32 | | -For CI and other unattended scans, set `OPENAI_API_KEY` or `CODEX_API_KEY` using |
33 | | -your shell, CI secret, or secret manager. |
34 | | - |
35 | | -On Windows, set an API key in PowerShell with: |
36 | | - |
37 | | -```powershell |
38 | | -$env:OPENAI_API_KEY = "<your-api-key>" |
39 | | -npx codex-security scan C:\code\repository |
40 | | -``` |
41 | | - |
42 | | -To store an API key, pass it on stdin: |
43 | | - |
44 | | -```bash |
45 | | -printenv OPENAI_API_KEY | npx codex-security login --with-api-key |
| 14 | +npx codex-security scan . |
46 | 15 | ``` |
47 | 16 |
|
48 | | -Use `npx codex-security login status` to check the stored sign-in and |
49 | | -`npx codex-security logout` to remove it. Codex Security reuses an existing |
50 | | -file-based Codex sign-in. If Codex stores credentials in the system keyring, |
51 | | -run `npx codex-security login` once before scanning. |
52 | | - |
53 | | -An environment API key takes precedence over a stored sign-in. Unset both |
54 | | -`OPENAI_API_KEY` and `CODEX_API_KEY` to use your ChatGPT sign-in. The login |
55 | | -status command reports the effective credential source without printing its |
56 | | -value, including when no stored sign-in exists. |
57 | | - |
58 | | -Scan a subset of a repository or write machine-readable results: |
59 | | - |
60 | | -```bash |
61 | | -npx codex-security scan /path/to/repo --model gpt-5.6-terra |
62 | | -npx codex-security scan /path/to/repo --path src --path tests |
63 | | -npx codex-security scan /path/to/repo --knowledge-base /path/to/threat-models --knowledge-base /path/to/architecture.pdf |
64 | | -npx codex-security scan /path/to/repo --diff origin/main --json |
65 | | -npx codex-security scan /path/to/repo --output-dir /path/outside/repo/results |
66 | | -npx codex-security scan /path/to/repo --output-dir /path/outside/repo/results --archive-existing |
67 | | -npx codex-security scan /path/to/repo --dry-run |
68 | | -npx codex-security scan /path/to/repo --fail-on-severity high |
69 | | -npx codex-security install-hook |
70 | | -npx codex-security bulk-scan |
71 | | -npx codex-security bulk-scan repositories.csv --output-dir /path/outside/repositories/security-scans |
72 | | -npx codex-security scans list /path/to/repo |
73 | | -npx codex-security scans list --scan-root /path/outside/repo/results |
74 | | -npx codex-security scans show SCAN_ID |
75 | | -npx codex-security scans rerun SCAN_ID |
76 | | -npx codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID |
77 | | -npx codex-security scans match --all |
78 | | -npx codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID |
79 | | -npx codex-security export /path/outside/repo/results --export-format sarif --output /path/outside/repo/results.sarif |
80 | | -npx codex-security export /path/outside/repo/results --export-format csv --output /path/outside/repo/findings.csv |
81 | | -npx codex-security export /path/outside/repo/results --export-format json --output /path/outside/repo/findings.json |
82 | | -npx codex-security validate /path/outside/repo/findings.json "Possible SQL injection in src/query.ts:42" |
83 | | -npx codex-security patch /path/outside/repo/findings.json "Missing authorization check in src/routes.ts:18" |
84 | | -``` |
85 | | - |
86 | | -`install-hook` scans staged and unstaged changes before each commit. It respects |
87 | | -`core.hooksPath`, does not replace an existing hook, and blocks high-severity |
88 | | -findings or failed scans. Set `--fail-on-severity` to change the threshold. |
89 | | - |
90 | | -Use `npx codex-security --version` for the CLI version and |
91 | | -`npx codex-security info --json` for package, plugin, and runtime versions, |
92 | | -the default model and reasoning effort, and the next scan command. Add |
93 | | -`--dry-run` to inspect the effective model and reasoning effort without |
94 | | -initializing Codex or contacting the network. |
95 | | - |
96 | | -The output directory must be outside the scanned directory and any enclosing Git |
97 | | -worktree. On macOS and Linux, an existing output directory must be private to |
98 | | -the current user (`chmod 700`). Scan artifacts can contain source excerpts, |
99 | | -vulnerability details, and reproduction steps. Keep them out of repositories, |
100 | | -public issue reports, and shared locations. |
101 | | - |
102 | | -When SARIF is produced, it is written to |
103 | | -`<scan-dir>/exports/results.sarif`. Use `npx codex-security scan --help` for all |
104 | | -target, output, and runtime options. |
105 | | - |
106 | | -Repeat `--knowledge-base PATH` for multiple files or directories. Directories are |
107 | | -searched recursively for Markdown, text, PDF, and Word (`.docx`) files. |
108 | | - |
109 | | -Sign in with `gh auth login`, then run `npx codex-security bulk-scan` to discover |
110 | | -GitHub repositories pushed in the last 90 days. Archived |
111 | | -repositories and forks are excluded. Search the repository list, select the |
112 | | -repositories to scan, and confirm before scanning. |
113 | | -Private checkouts reuse your GitHub CLI sign-in without changing your global Git |
114 | | -configuration. For automation or an existing repository list, pass a CSV |
115 | | -containing `id`, `repository`, and full immutable `revision` columns and specify |
116 | | -`--output-dir`. Use `npx codex-security bulk-scan --help` for all options. |
| 17 | +For CI, set `OPENAI_API_KEY` instead of signing in. |
117 | 18 |
|
118 | | -The CLI uses [Incur](https://github.com/wevm/incur) for agent-friendly discovery |
119 | | -and structured output. Use `--llms` for the command manifest, |
120 | | -`scan --schema --format json` for a command schema, register an MCP server with |
121 | | -`mcp add`, sync agent skills with `skills add`, and use |
122 | | -`completions bash|zsh|fish` for shell |
123 | | -completions. Scan results support `--format toon|json|yaml|jsonl` and |
124 | | -`--full-output`. |
125 | | -Use `info --json` for SDK and bundled-plugin metadata. MCP exposes only this |
126 | | -read-only metadata command; scans, authentication, exports, validation, and |
127 | | -patching remain CLI-only because the MCP transport cannot cancel active scans. |
128 | | - |
129 | | -If the output directory already contains results, add `--archive-existing`. |
130 | | -The CLI moves them to `<output-dir>.previous-<timestamp>-<id>` and starts the |
131 | | -scan in a new, empty directory at the original path. Add `--dry-run` to see |
132 | | -the destination without moving files. |
133 | | - |
134 | | -Scans are report-only by default. Use `--fail-on-severity` in CI to exit 1 when |
135 | | -a completed scan contains a finding at or above the selected severity. |
136 | | -Incomplete coverage and CLI/runtime errors exit 2. Incomplete scans still write |
137 | | -the available human or JSON result to stdout and a coverage warning to stderr, |
138 | | -including in report-only mode. |
139 | | - |
140 | | -For CI, save machine-readable output outside the checked-out repository and |
141 | | -apply a severity policy. Incomplete coverage and runtime errors still exit |
142 | | -nonzero: |
143 | | - |
144 | | -```bash |
145 | | -SCAN_ROOT="$(mktemp -d)" |
146 | | -npx codex-security scan . \ |
147 | | - --diff origin/main \ |
148 | | - --output-dir "$SCAN_ROOT/results" \ |
149 | | - --json \ |
150 | | - --fail-on-severity high > "$SCAN_ROOT/findings.json" |
151 | | -``` |
152 | | - |
153 | | -JSON scans remain noninteractive, including when stderr is a terminal. Commands |
154 | | -that run Codex interactively (`validate`, `patch`, `login`, and `logout`) reject |
155 | | -`--json`. Write CSV exports to a file when JSON output is selected. |
156 | | - |
157 | | -Scans use `gpt-5.6-sol` with extra-high reasoning effort by default. Switch |
158 | | -models with `--model`. Use `--codex` for other Codex settings: |
159 | | - |
160 | | -```bash |
161 | | -npx codex-security scan . --model gpt-5.6-terra --codex 'model_reasoning_effort="high"' |
162 | | -``` |
163 | | - |
164 | | -Scans report their requested paths and actual ranking, file-review, validation, |
165 | | -and attack-path phases. Completion shows finding severity, coverage, elapsed |
166 | | -time, available token and worker counts, the results directory, and the next |
167 | | -useful command. Progress remains on stderr; JSON results remain on stdout. |
168 | | - |
169 | | -## Use the TypeScript SDK |
170 | | - |
171 | | -Create a client, choose a private output directory outside the repository, and |
172 | | -close the client after the scan: |
| 19 | +## TypeScript SDK |
173 | 20 |
|
174 | 21 | ```ts |
175 | 22 | import { CodexSecurity } from "@openai/codex-security"; |
176 | 23 |
|
177 | 24 | const security = new CodexSecurity(); |
| 25 | +const result = await security.run("."); |
178 | 26 |
|
179 | | -try { |
180 | | - const result = await security.run("/path/to/repository", { |
181 | | - outputDir: "/path/outside/repository/results", |
182 | | - }); |
183 | | - |
184 | | - console.log(result.reportPath); |
185 | | - console.log(result.findings.findings.length); |
186 | | -} finally { |
187 | | - await security.close(); |
188 | | -} |
| 27 | +console.log(result.reportPath); |
| 28 | +await security.close(); |
189 | 29 | ``` |
190 | 30 |
|
191 | | -The SDK also supports path and diff targets, preflight, progress callbacks, |
192 | | -cancellation, security knowledge bases, and typed scan results. |
193 | | - |
194 | | -## Run bulk scans in Docker |
195 | | - |
196 | | -The included Docker image runs noninteractive bulk scans from a supplied CSV on |
197 | | -a Linux Docker host. The included `compose.yaml` configures the image, |
198 | | -persistent files, and a hardened Codex command sandbox. |
199 | | - |
200 | | -<details> |
201 | | -<summary>Configure a Docker bulk scan</summary> |
202 | | - |
203 | | -Create a `repositories.csv` with one full, immutable Git commit per repository: |
204 | | - |
205 | | -```csv |
206 | | -id,repository,revision |
207 | | -payments,https://github.com/example/payments.git,0123456789abcdef0123456789abcdef01234567 |
208 | | -``` |
209 | | - |
210 | | -Create private, persistent result and authentication directories, and let the |
211 | | -container write files as your current user: |
212 | | - |
213 | | -```bash |
214 | | -mkdir -p results state |
215 | | -chmod 700 results state |
216 | | -export CODEX_SECURITY_USER="$(id -u):$(id -g)" |
217 | | -docker compose build codex-security |
218 | | -``` |
219 | | - |
220 | | -For a one-time sign-in from a remote or headless Docker host, run: |
221 | | - |
222 | | -```bash |
223 | | -docker compose run --rm codex-security login --device-auth |
224 | | -``` |
225 | | - |
226 | | -Open the displayed verification URL in your browser and enter the one-time |
227 | | -code. The login remains in `state/` after the container exits. |
228 | | - |
229 | | -Alternatively, provide `OPENAI_API_KEY` or `CODEX_API_KEY` through your host |
230 | | -environment or secret manager. For private repositories, provide `GH_TOKEN` or |
231 | | -`GITHUB_TOKEN` the same way. Compose passes only the named, configured |
232 | | -credentials to the container. |
233 | | - |
234 | | -Start a resumable, four-worker scan with the default command: |
235 | | - |
236 | | -```bash |
237 | | -docker compose run --rm codex-security |
238 | | -``` |
239 | | - |
240 | | -Full-repository scans can take tens of minutes per repository at the default |
241 | | -extra-high reasoning setting. Run large campaigns as asynchronous batch jobs |
242 | | -and keep the results and authentication directories mounted throughout the run. |
243 | | - |
244 | | -Completed reports, per-repository findings, and the scan manifest appear in |
245 | | -`results/` on the host. The workbench state for that campaign remains in |
246 | | -`results/.codex-security-state/`; the reusable Codex login remains separately in |
247 | | -`state/`. This allows a new results directory to start a separate campaign with |
248 | | -the same login without colliding with an earlier scan. Rerun the same command |
249 | | -with the original CSV and the same `results/` and `state/` directories to resume |
250 | | -an interrupted scan. |
251 | | - |
252 | | -To choose a different number of parallel workers or retry failed repositories, |
253 | | -override the default scan command: |
254 | | - |
255 | | -```bash |
256 | | -docker compose run --rm codex-security \ |
257 | | - bulk-scan /input/repositories.csv \ |
258 | | - --output-dir /output \ |
259 | | - --workers 8 \ |
260 | | - --max-attempts 2 |
261 | | -``` |
262 | | - |
263 | | -Set `CODEX_SECURITY_CSV`, `CODEX_SECURITY_RESULTS`, or `CODEX_SECURITY_STATE` |
264 | | -to use existing files or directories outside the Compose project. Set |
265 | | -`CODEX_SECURITY_IMAGE` to use an approved, already-built image. Set |
266 | | -`CODEX_SECURITY_GIT_HOST` when accessing GitHub Enterprise Server. Keep |
267 | | -credentials, repository lists, and results out of the image and Git; the |
268 | | -included ignore files exclude them from image builds and commits. |
269 | | -All CSV files, including custom-named repository inventories, are excluded from |
270 | | -the Docker build context. Compose mounts the selected CSV at runtime instead. |
271 | | - |
272 | | -The included Compose configuration drops all Linux capabilities, prevents new |
273 | | -privileges, runs as a nonroot user, and applies the supplied default-deny |
274 | | -seccomp profile. Codex Security runs each scan command in a separate |
275 | | -unprivileged Linux sandbox. Docker's default seccomp profile blocks the user and |
276 | | -mount namespaces required by that sandbox; the supplied profile permits only |
277 | | -the needed namespace operations. The Linux host must allow unprivileged user |
278 | | -namespaces. Some Docker Desktop virtual machines additionally restrict nested |
279 | | -mount namespaces, so use a Linux host for production scans. |
280 | | - |
281 | | -For environments without Docker Compose, the equivalent lower-level invocation |
282 | | -is: |
283 | | - |
284 | | -```bash |
285 | | -docker run --rm --init \ |
286 | | - --user "$(id -u):$(id -g)" \ |
287 | | - --cap-drop ALL \ |
288 | | - --security-opt no-new-privileges \ |
289 | | - --security-opt "seccomp=$PWD/docker/codex-security-seccomp.json" \ |
290 | | - --env OPENAI_API_KEY \ |
291 | | - --env CODEX_API_KEY \ |
292 | | - --env GH_TOKEN \ |
293 | | - --env GITHUB_TOKEN \ |
294 | | - --env CODEX_SECURITY_GIT_HOST \ |
295 | | - --mount "type=bind,source=$PWD/repositories.csv,target=/input/repositories.csv,readonly" \ |
296 | | - --mount "type=bind,source=$PWD/results,target=/output" \ |
297 | | - --mount "type=bind,source=$PWD/state,target=/state" \ |
298 | | - codex-security:local \ |
299 | | - bulk-scan /input/repositories.csv \ |
300 | | - --output-dir /output |
301 | | -``` |
302 | | - |
303 | | -The image configures a noninteractive Git credential helper for `github.com` |
304 | | -when a GitHub token is supplied. The token works with both HTTPS repository |
305 | | -URLs and `git@github.com:` repository URLs without mounting an SSH agent. The |
306 | | -image never places that token in a repository URL, writes it to image layers, |
307 | | -or sends it to another Git host. Set `CODEX_SECURITY_GIT_HOST` to the hostname |
308 | | -of a GitHub Enterprise Server instance when needed. |
309 | | - |
310 | | -Use `--workers` to control concurrent repository scans and `--max-attempts` to |
311 | | -retry failures. The command returns a nonzero status when any repository fails. |
312 | | - |
313 | | -</details> |
314 | | - |
315 | | -## Scan history and reruns |
316 | | - |
317 | | -`npx codex-security scans list` lists scans for the current repository. Pass a |
318 | | -repository path to inspect another checkout, `--scan-root DIR` to filter by |
319 | | -scan artifact directory. `scans show SCAN_ID` includes saved configuration, |
320 | | -findings, and coverage. |
321 | | - |
322 | | -History is saved in the existing Codex Security workbench database under |
323 | | -`$CODEX_HOME/state/plugins/codex-security`. Set `CODEX_SECURITY_STATE_DIR` to |
324 | | -choose a different location. |
325 | | - |
326 | | -`scans rerun SCAN_ID` repeats the same configuration against the current |
327 | | -checkout. `scans match BEFORE_SCAN_ID AFTER_SCAN_ID` links findings with the |
328 | | -same root cause; `scans match --all` includes every available completed scan |
329 | | -of the current repository, including other worktrees and clones. Use `--force` |
330 | | -to recompute saved matches. |
331 | | - |
332 | | -`scans compare BEFORE_SCAN_ID AFTER_SCAN_ID` reads saved matches and identifies |
333 | | -new, persisting, reopened, resolved, or unknown findings. Missing findings remain |
334 | | -unknown when coverage is incomplete or their original location was not reviewed. |
335 | | - |
336 | | -Use `export` to create CSV, JSON, or SARIF from a completed, sealed scan without |
337 | | -starting Codex or loading credentials. JSON preserves the sealed findings |
338 | | -document. CSV uses the portable findings columns, marks findings as open, and |
339 | | -does not include local workbench triage state. The exporter validates the seal |
340 | | -before writing, accepts `--output -` for stdout, and can use |
341 | | -`--source-root /path/to/repo` with SARIF to add source-line fingerprints. Run |
342 | | -`npx codex-security export --help` for all export options. |
343 | | - |
344 | | -Use `validate` to run the bundled validation skill on candidate findings and |
345 | | -`patch` to run the bundled fix-finding skill on security issues. Each positional |
346 | | -input can be either a file, whose contents are read into the request, or literal |
347 | | -text. Both commands operate on the current directory. |
348 | | - |
349 | | -Canonical scan documents are limited to 16 MiB for the manifest, 128 MiB for |
350 | | -findings, and 32 MiB for coverage. Oversized scans are rejected before sealing. |
351 | | - |
352 | | -Exit codes are `0` for a completed report-only scan or a passing policy, `1` |
353 | | -for a completed policy violation, `2` for invalid input, incomplete coverage, or |
354 | | -a runtime/export error, `130` for interruption, and `143` for termination. |
355 | | - |
356 | | -Use `--dry-run` or `await security.preflight(...)` to validate local scan |
357 | | -inputs and report the selected credential source without initializing Codex, |
358 | | -loading credentials, or starting a scan. Dry runs do not inspect the plugin, |
359 | | -probe Python, or contact the network; their authentication metadata is not |
360 | | -verified. |
361 | | - |
362 | | -## Documentation, support, and security |
363 | | - |
364 | | -- [Codex Security overview](https://developers.openai.com/codex/security) |
365 | | -- [CLI quickstart and reference](https://developers.openai.com/codex/security/cli) |
366 | | -- [TypeScript SDK guide](https://developers.openai.com/codex/security/sdk) |
367 | | -- [GitHub issues](https://github.com/openai/codex-security/issues) for bugs and |
368 | | - feature requests |
369 | | -- [Security policy](SECURITY.md) for private vulnerability reporting and safe |
370 | | - operation |
371 | | -- [Contribution guidelines](CONTRIBUTING.md) |
372 | | - |
373 | | -This project is licensed under the [Apache-2.0 License](LICENSE). |
| 31 | +For installation, authentication, scan options, and CI setup, see the [official documentation](http://learn.chatgpt.com/docs/security/cli). |
0 commit comments