OpenAI Released Its Security CLI: Here’s How You Put It to Scan Your Repo and Cut Your CI
For a month, issue #29878 in openai/codex sat open with an uncomfortable observation attached. Codex CLI is Apache-2.0, the entire project, auditable. But the codex-security plugin it installed on developers’ machines was something else: "license": "Proprietary", straight from the manifest, distributed through OpenAI’s curated marketplace and pointing to a repository nobody outside could open. The complaint wasn’t philosophical. It was that a closed binary was being installed on your system, via an open tool, to read your source code.
That issue is still open. But as of this week, there’s what it asked for: github.com/openai/codex-security, public, Apache-2.0, 98 commits on main, with a CLI, a TypeScript SDK, a Dockerfile and a compose.yaml for bulk scans. OpenAI didn’t announce it first — they said it themselves on X: “we quietly released the open-source Codex Security CLI, but Hacker News found it before we had a chance to share it here.”
The release is moving fast. npm went from 0.1.0 to 0.1.4 in about 55 hours: 0.1.0 and 0.1.1 on July 28th, 0.1.2 and 0.1.3 on the 29th, 0.1.4 in the early hours of the 30th. If you’re reading a tutorial written a day ago, check the version.
Before Installing: Two Requirements and One Restriction
The README is explicit: Node.js 22 or higher, Python 3.10 or higher. The Python part is surprising — it’s an npm package, nobody expects to need an interpreter, but both scanning and findings export go through it. If your first npx dies, that’s usually why.
The third requirement is the one that decides if this is for you. Authentication works two ways: --auth chatgpt, billing against your ChatGPT plan, or --auth api-key, billing against the API. And according to OpenAI’s own help center, Codex Security is still a research preview available for ChatGPT Enterprise, Edu, Business and Pro — so the ChatGPT route is limited by plan tier. If you have a personal Plus account, the practical way is an API key.
It’s worth saying plainly, because it conditions everything that follows: the code is open, the scanner is not free. Every scan is model inference, and someone pays for it.
The First Scan
npm install @openai/codex-security
npx codex-security login
npx codex-security scan .
login takes you through ChatGPT credentials or an API key. scan . runs against the current repository and writes results to a scan directory; history lives in the state directory of the Codex Security workbench, and if that location isn’t writable in your environment — containers, CI runners, laptops with restricted permissions — set CODEX_SECURITY_STATE_DIR pointing to one that is.
What you get back isn’t a grep of suspicious patterns. The repo’s pitch is “finding, validating, and fixing” — and the validating part is the interesting one, because the historical failure mode of automated security tooling isn’t that it misses bugs, it’s that it drowns you in findings that aren’t real.
How to Make It Block Your Commits
npx @openai/codex-security install-hook
This installs a pre-commit hook that scans staged and unstaged changes before each commit, and blocks on high-severity findings or if a scan fails outright. Two details that matter if you’ve ever been burned by hook installers: it respects core.hooksPath and doesn’t replace an existing hook.
Be honest with yourself about latency. A hook that calls a model on every commit doesn’t cost the same as one that runs eslint. Try it for a day before imposing it on the team.
Tracking Findings Between Runs
This is the part that sets it apart from a single-pass scanner. Each scan is saved, and you can reason about the deltas between one and another:
npx @openai/codex-security scans list "$REPOSITORY"
npx @openai/codex-security scans match PREVIOUS_SCAN_ID CURRENT_SCAN_ID
npx @openai/codex-security scans compare PREVIOUS_SCAN_ID CURRENT_SCAN_ID
match links findings that share the same root cause between two scans — the hard problem, because line numbers move and a refactor can make the same bug look completely new. compare reads those saved matches and classifies each finding as new, persisting, reopened, resolved or unknown.
The category worth staring at is “reopened”. It means a vulnerability you’d already fixed came back, which is exactly the kind of regression manual security review never catches and that a stateless scanner reports as if it were new.
The CI Block
This is where the release earns its place. From OpenAI’s own CI guide, the scan step in GitHub Actions:
"$CODEX_SECURITY_BIN" scan . \
--diff "$BASE_REVISION" \
--head "$HEAD_SHA" \
--auth api-key \
--output-dir "$SCAN_DIR" \
--json > "$RUNNER_TEMP/codex-security.json"
Notice --diff and --head: in CI you scan the pull request changes, not the entire repository. That’s what keeps costs manageable.
Then, the severity policy:
--fail-on-severity high
The accepted values are critical, high, medium, low, and a threshold includes that severity and the ones above it. With that, a completed scan containing a finding at that level exits with 1 and your pipeline turns red.
And the SARIF export, which is how findings reach GitHub code scanning or anything that speaks that format:
"$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
--export-format sarif \
--source-root "$GITHUB_WORKSPACE" \
--output "$SARIF_FILE"
The workflow pins a version with --ignore-scripts --no-audit --no-fund inside $RUNNER_TEMP, and maps OPENAI_API_KEY from a repository secret — a scoped credential for CI instead of your personal login. Pin the version. This project shipped five releases in three days.
Scanning Many Repositories at Once
If you’re the person responsible for more than one codebase, there’s the Docker route:
docker compose run --rm codex-security \
bulk-scan /input/repositories.csv \
--output-dir /output \
--workers 4
You pass it a CSV of repositories and it walks through them non-interactively, inside a hardened sandbox for the Codex command. This is the organization-level inventory use case, and it’s where the unanswered question coming up below stops being curiosity and becomes a budget line item.
The Number Nobody’s Publishing
Neither the README nor the help center say how much a scan costs. Not per repository, not token estimation, not even a rough order of magnitude. And with --workers 4 chewing through a CSV of repositories, that’s not a detail — it’s the whole question of whether you can run this weekly or once a quarter.
So measure it before you commit. Run a full scan against a repository whose size you know, check your API usage dashboard immediately before and after, and write down the number. Then run the variant with --diff on a normal pull request and write that down too. Those two numbers are what really determine your CI policy, and today you can only get them by generating them yourself.
That’s also the most useful thing you can publish about this release. Everyone can report that the license changed. Almost nobody is reporting how much a scan costs.
Have you already run a security scanner against your own repositories in CI — and what made you turn it off, false positives or the bill?