How to Use Codex Security (OpenAI's Open-Source Vulnerability Scanner CLI)

Read time: ~8 minutes. TL;DR — scan a repo in three commands:

npm install @openai/codex-security
npx codex-security login
npx codex-security scan .

Requires Node.js 22+ and Python 3.10+. Scans are report-only by default — add --fail-on-severity high to gate CI.

Key facts:

  • @openai/codex-security — OpenAI’s Apache-2.0 CLI + TypeScript SDK for finding, validating, and fixing vulnerabilities. 5,259 stars and still shipping daily (repo created July 13, 2026).
  • Default model: gpt-5.6-sol at extra-high reasoning effort — switch with --model gpt-5.6-terra and --effort.
  • Exit codes are meaningful: 1 = policy violation, 2 = incomplete coverage or runtime error — so a failure can’t be mistaken for a pass.
  • Outputs JSON, CSV, or SARIF (<scan-dir>/exports/results.sarif).

Sourcing note: every command, flag, option, and default below is quoted from the official openai/codex-security repo — the root README and the 28 KB SDK README (sdk/typescript/README.md) — fetched July 30, 2026. Star count from the GitHub API the same day. Links at the bottom.

OpenAI quietly shipped something builders will actually use: an open-source security scanner driven by Codex. It reads your repo, finds vulnerabilities, validates them, proposes patches, and can fail your CI build. It’s Apache-2.0, went from 3,376 to 5,259 stars in a day, and is still being pushed to daily. Here’s how to run it properly.


1. Install and first scan

Requirements: Node.js 22 or later, Python 3.10 or later, and access to Codex Security.

npm install @openai/codex-security
npx codex-security login
npx codex-security scan .

Check what you’ve got:

npx @openai/codex-security --version
npx @openai/codex-security info --json   # package, bundled plugin, Codex runtime,
                                         # default model, reasoning effort, first-scan command

Scan history lives in the Codex Security workbench state directory. If that directory isn’t writable, point CODEX_SECURITY_STATE_DIR at a writable location outside the repository.


2. Authentication: two paths

You can authenticate with either a ChatGPT sign-in or an API key:

# interactive sign-in
npx codex-security login
npx @openai/codex-security login --device-auth        # device-code flow

# store an API key from stdin (never as a shell argument)
printenv OPENAI_API_KEY | npx @openai/codex-security login --with-api-key

For CI, set OPENAI_API_KEY instead of signing in.

The precedence rule that trips people up: if both a ChatGPT sign-in and an API key are present, an interactive scan asks which to use — but JSON output, dry runs, and CI never prompt and keep automatic API-key precedence. Force it explicitly:

npx @openai/codex-security scan . --auth chatgpt   # ignores OPENAI_API_KEY / CODEX_API_KEY
npx @openai/codex-security scan . --auth api-key   # requires one of those env vars

To make your ChatGPT sign-in the automatic default, clear the keys:

unset OPENAI_API_KEY CODEX_API_KEY

3. Scope the scan: --path, --diff, --working-tree

Scanning a whole repo every time is slow and expensive. Scope it:

FlagScans
--path PATHOne or more specific paths
--diff origin/mainCommitted changes against a ref
--working-treeStaged and unstaged changes
(none)The whole repository

--diff is the one you want in pull-request CI — review what changed, not the world.

Add domain context to reduce false positives:

npx @openai/codex-security scan . \
  --knowledge-base ./docs/security-policy.md \
  --knowledge-base ./docs/threat-model/

Repeat --knowledge-base freely; directories are searched recursively for Markdown, text, PDF, and Word (.docx) files. Architecture docs, security policies, and threat models all count.


4. Deep mode, models, and cost control

Standard vs deep: --mode deep runs the deep engine; deep scans support repository and path targets.

Model and effort — the defaults are aggressive, which matters for your bill:

Scans use gpt-5.6-sol with extra-high reasoning effort by default.

npx @openai/codex-security scan . \
  --model gpt-5.6-terra \
  --effort medium

--effort accepts minimal|low|medium|high|xhigh. Other Codex settings go through repeatable --codex KEY=VALUE (e.g. --codex 'model_reasoning_effort="high"') — but don’t pass both --model and a conflicting --codex override.

Cap the spend. The SDK exposes maxCostUsd — “stop after the estimated model cost exceeds a positive USD amount.” On a large repo with gpt-5.6-sol at xhigh effort, set this before you run your first full scan.

Preview without spending anything:

npx @openai/codex-security scan . --dry-run

A dry run reports the effective model and reasoning effort (including --codex overrides) without starting Codex or touching the network.


5. The pre-commit hook

npx @openai/codex-security install-hook

This scans staged and unstaged changes before each commit. Per the docs it respects core.hooksPath, does not replace an existing hook, and blocks high-severity findings or failed scans. Change the bar with --fail-on-severity.

This is the highest-leverage setup for solo devs: you catch issues before they’re even committed, and you only pay to scan the diff.


6. CI: the recipe, and the exit code that matters

Scans are report-only by default. In CI you want a policy:

SCAN_ROOT="$(mktemp -d)"
npx @openai/codex-security scan . \
  --diff origin/main \
  --output-dir "$SCAN_ROOT/results" \
  --json \
  --fail-on-severity high > "$SCAN_ROOT/findings.json"

Now the important detail most wrappers get wrong:

  • Exit 1 = the completed scan contains a finding at or above your severity threshold.
  • Exit 2 = incomplete coverage, or a CLI/runtime error — explicitly separated “so they cannot be mistaken for a passing policy.”

That distinction is the whole point: a scan that didn’t finish must not look like a clean build. If your CI only checks exit != 0, you’re fine; if it special-cases exit == 1, make sure 2 still fails the job. Incomplete scans still write the available result to stdout plus a coverage warning to stderr — even in report-only mode.

Two more CI rules from the docs:

  • Write machine-readable output outside the checked-out repository (as the mktemp -d above does). The output directory must be outside the scanned directory and any enclosing Git worktree.
  • On macOS/Linux, an existing output directory must be private to the current user (chmod 700).
  • Re-running into a used directory? Add --archive-existing — it moves old results to <output-dir>.previous-<timestamp>-<id> and starts fresh (pair with --dry-run to preview).
  • Set CI in the environment to disable interactive update notices.

SARIF for code scanning: when SARIF is produced it lands at <scan-dir>/exports/results.sarif — feed that to GitHub code scanning or your SAST dashboard. export also creates CSV/JSON/SARIF from a completed, sealed scan.


7. The TypeScript SDK

If you’d rather drive it from code:

import { CodexSecurity } from "@openai/codex-security";

const security = new CodexSecurity();
const result = await security.run(".");

console.log(result.reportPath);
await security.close();

Scan options passed to security.run(repository, options) mirror the CLI — the ones worth knowing:

OptionWhat it does
auth"auto" / "chatgpt" / "api-key"
targetRepository, repo-relative paths, committed diff, or working-tree diff
mode"standard" or "deep"
knowledgeBasePathsArchitecture docs, security policies, threat models
outputDirArtifact directory outside the enclosing Git worktree
maxCostUsdStop past an estimated USD cost
failureSeverityRecord a finding-severity policy in the saved scan recipe
archiveExistingArchive prior results before scanning
signalCancel with an AbortSignal

Client-level config includes pluginPath (custom plugin dir/ZIP), pythonPath (interpreter selection, consulted before PYTHON), and codexOverrides (deep-merge into the isolated Codex configuration). There are also scan-lifecycle callbacks and onReconnect for observing long scans.


8. Managing scans over time

npx @openai/codex-security scans list      # scans for the current repository
npx @openai/codex-security bulk-scan --help  # many repos, incl. CSV input for CI

bulk-scan accepts a CSV with a required id column to run an existing repository list — useful if you’re sweeping an org rather than one repo. Reruns can be linked to a parent via parentScanId, and expectedPluginVersion pins the original plugin version when replaying a scan (so results stay comparable).


9. Honest caveats

  • The defaults are expensive. gpt-5.6-sol at xhigh effort across a large repo is the premium setting. Start with --diff, a --dry-run, and maxCostUsd.
  • It’s moving fast. The repo was created July 13, 2026 and was pushed to the morning this guide was written. Pin your version and re-read scan --help after upgrades.
  • --json isn’t universal: validate, patch, login, and logout reject --json (they don’t produce structured CLI output), and CSV exports can’t go to stdout while JSON is requested.
  • An AI scanner is a triage tool, not a proof. It finds and validates candidates; you still review patches before merging.

The takeaway

@openai/codex-security turns Codex into a repo scanner you can actually wire in: npm installloginscan . (Node 22+, Python 3.10+), scoped with --diff origin/main for PRs or install-hook for pre-commit. Control the bill with --model gpt-5.6-terra, --effort, maxCostUsd, and a --dry-run first — the default is gpt-5.6-sol at xhigh. In CI, write output outside the repo, apply --fail-on-severity high, and remember exit 1 = policy violation while exit 2 = incomplete/error, so an unfinished scan never reads as a green build. Export SARIF from <scan-dir>/exports/results.sarif for code scanning.

For other terminal-agent tooling, see the Grok Build CLI handbook and Claude Code as a daily driver.

Sources

  • openai/codex-security — GitHub — Apache-2.0 CLI + TypeScript SDK; quick start (npm install @openai/codex-security, login, scan .); Node.js 22+ / Python 3.10+; --auth chatgpt|api-key; CODEX_SECURITY_STATE_DIR; SDK usage (new CodexSecurity(), security.run("."), result.reportPath, close())
  • sdk/typescript/README.md — SDK/scan option tables (auth, target, mode, knowledgeBasePaths, outputDir, archiveExisting, maxCostUsd, failureSeverity, parentScanId, expectedPluginVersion, signal; pluginPath, pythonPath, codexOverrides); login --device-auth / --with-api-key; --path / --diff / --working-tree; --mode deep; default gpt-5.6-sol at extra-high effort with --model / --effort minimal|low|medium|high|xhigh / --codex KEY=VALUE; --dry-run; install-hook behavior (core.hooksPath, won’t replace existing hook, blocks high severity); report-only default and --fail-on-severity; exit 1 = policy violation, exit 2 = incomplete coverage / runtime error; CI recipe with mktemp -d, --output-dir, --json; chmod 700 requirement; --archive-existing; SARIF at <scan-dir>/exports/results.sarif; --json rejected by validate/patch/login/logout; scans list; bulk-scan CSV with required id; CI env var
  • Codex Security CLI reference — learn.chatgpt.com — official CLI documentation
  • Star count (5,259) from the GitHub API on July 30, 2026; repo created July 13, 2026 and actively pushed. Flags and defaults verified against the repo the same day — re-check scan --help after upgrading, as the project is moving quickly.