Run Codex Security from TypeScript or the command line to find, validate, and fix security vulnerabilities in your code. The package includes the Codex runtime, security plugin, and TypeScript declarations. It uses ES modules.
- Scan repositories, selected paths, or Git changes. Deep scans run parallel discovery workers on repositories and selected paths.
- Validate findings, generate patches, and verify existing fixes.
- Draft security policies and retain threat models.
- Review saved findings, identify duplicates, classify severity, and suggest owners.
- Import GitHub code scanning alerts, export SARIF, JSON, or CSV, and publish findings to Linear or a findings service.
- Automate scans across repositories and project components.
See the CLI reference, findings guide, or online documentation for setup and examples.
Before version 1.0.0, minor releases may change the public API.
Supported runtimes:
- Node.js 22.13.0+ within 22.x, or Node.js 24.x or 26.x, on macOS, Linux, or Windows.
- Python 3.10+ for scans, policy generation, exports, scan history, and saved
findings. Python 3.10 also needs
tomli.
Reading compressed Codex session logs (.jsonl.zst) requires Node.js 22.15.0+
within 22.x, or Node.js 24.x or 26.x. On Node.js 22.13–22.14, compressed sessions
are unavailable when reading saved activity or attaching scan logs to feedback, and
scans whose original session is compressed cannot resume. Plain .jsonl logs
work on all supported runtimes.
LocalPluginBootstrapError identifies local plugin setup failures and extends
PluginBootstrapError, so existing catches keep working. Knowledge-base
preparation errors use ConfigurationError; wrapped diagnostics remain in cause.
Install the CLI globally:
npm install --global @openai/codex-security
cs --versioncs is a short alias for codex-security; both commands run the same CLI.
The installation creates both commands in npm's global executable directory,
which must be on your PATH. If cs already resolves to another tool, use
codex-security instead. If npm stops with an EEXIST error for cs, use
npx @openai/codex-security without a global installation.
Continue with the CLI walkthrough. To run without a global installation,
replace cs in the CLI examples with npx @openai/codex-security.
Install the package locally in your TypeScript project:
npm install @openai/codex-securitySign in with ChatGPT:
cs loginIf you installed only the SDK locally, sign in from your project directory:
npx @openai/codex-security loginIn the following CLI examples, replace cs with npx @openai/codex-security
when using a local SDK installation, including the API-key login example below.
For CI, set OPENAI_API_KEY or CODEX_API_KEY in the scan process's environment.
These keys apply to the current command without replacing your saved login.
To save an API key instead, pass it on stdin:
printenv OPENAI_API_KEY | cs login --with-api-keySDK calls accept auth: "auto" | "chatgpt" | "api-key". The default, "auto",
prefers OPENAI_API_KEY, then CODEX_API_KEY, then stored credentials.
Use "chatgpt" to ignore environment API keys. The CLI uses the same --auth
values and prompts in an interactive terminal when both credential types are available.
Some cybersecurity requests and protected findings require Trusted Access for Cyber approval. See the authentication reference for providers, stored credentials, and Cyber access program selection.
On a remote or headless machine, try login --device-auth if your workspace
allows it. Otherwise, open an SSH tunnel from your local machine:
ssh -L 1455:localhost:1455 user@remote-hostRun cs login in that SSH session, then open its sign-in
URL in your local browser. Keep SSH connected until login finishes.
Bedrock scans use AWS credentials and model access. They do not require
codex-security login or an OpenAI API key. See the
Bedrock guide
for setup, model selection, and verification.
The Security plugin includes $cloud-findings for accounts where Codex Security
Cloud is available. Install the plugin through your configured Codex marketplace,
sign in to Codex with ChatGPT, and complete the Cloud connection interactively in
the intended account and workspace. Installation alone does not authenticate the
connection. Local scans do not require Cloud, and an API key used for scanning
does not replace the Cloud connection.
In Codex desktop or the interactive Codex CLI, ask:
Use $cloud-findings to list findings for example/security-demo in my selected workspace. Inspect the highest-severity finding and its report, and show its recorded assignee, patch links, verification results, and latest scan status. Do not change anything.
After completing connection setup, the same host connection can be used by
codex exec:
codex exec --ephemeral --json -s read-only 'Use $codex-security:cloud-findings to read findings and the latest scan status for example/security-demo in my selected workspace. Inspect one finding and its report. If the workspace or repository is ambiguous, explain the required selection and stop. Do not change anything.'Noninteractive execution needs an existing authenticated connection; it cannot complete first-time sign-in. If authentication expires, the app is unavailable, or workspace policy denies access, complete the reported setup action before retrying. Those failures do not mean the repository has no findings.
Assignment, issue validation, patch checks, periodic fix checks, and finding lifecycle status are separate records. Some finding sources do not provide all of them. The read workflow reports missing data and incomplete evidence pages, and does not describe failed or unfinished scans as clean.
Scan a repository you own or have permission to assess:
import { CodexSecurity } from "@openai/codex-security";
const security = new CodexSecurity();
try {
const result = await security.run("/path/to/repository");
console.log(result.reportPath);
console.log(result.findings.findings);
if (result.hasFindingsAtOrAbove("high")) {
process.exitCode = 1;
}
} finally {
await security.close();
}Omitting outputDir saves results in the private Codex Security state directory.
To choose another location, use a new or empty directory outside the scanned
repository and its enclosing Git worktree. On macOS and Linux, an existing output
directory must be private to you (chmod 700).
| Result | Contents |
|---|---|
findings.findings |
Findings from this scan. |
reportPath |
Path to the Markdown report. |
coverage |
What the scan assessed and any coverage gaps. |
repositoryFindings |
This scan's findings plus earlier open findings, when available. |
sarifPath |
SARIF export path, or null. |
threatModel / threatModelPath |
Saved threat model and document path; either can be null. |
cost |
Estimated model usage cost, or null when unavailable. |
Review coverage alongside findings. A report with no findings does not establish that the repository is secure. Reports and logs can contain source code, vulnerability details, and credentials; review them before sharing.
The SDK does not set your process's exit status. Use hasFindingsAtOrAbove()
as in the example to enforce a severity threshold.
Pass scan settings as the second argument to run(). The following SDK snippets
assume an open CodexSecurity client named security; close it when finished.
const result = await security.run("/path/to/repository", {
target: ["src", "tests"],
knowledgeBasePaths: ["/path/to/architecture.md"],
scanPrompt: "Focus on authentication and authorization.",
outputDir: "/path/outside/repository/results",
maxCostUsd: 5,
});| Option | Use |
|---|---|
target |
Whole repository (default), repository-relative paths, or a DiffTarget. |
mode |
"standard" (default) or "deep". Deep scans support repositories and paths. |
knowledgeBasePaths |
Supporting text, PDF, DOCX files, or directories. |
scanPrompt / scanPromptFile |
Additional scan instructions. Inline text takes precedence. |
validationPrompt / validationPromptFile |
Custom validation instructions for standard scans. |
postScanPrompt / postScanPromptFile |
Follow-up instructions after the scan. |
outputDir |
Results directory; omit to use the state directory. |
archiveExisting |
Move previous results aside before reusing outputDir. |
maxCostUsd |
Stop at an estimated model cost; see cost limits. |
signal |
An AbortSignal to cancel the scan. |
The exported ScanOptions type describes all options and callbacks. For full
CLI behavior, see scan options and output.
import { DiffTarget } from "@openai/codex-security";
const result = await security.run("/path/to/repository", {
target: DiffTarget.refs({ base: "origin/main" }),
});DiffTarget.refs() compares the base with HEAD unless you supply head.
The checkout must be clean, complete, and at that head revision.
Use DiffTarget.workingTree() for staged and unstaged changes relative to HEAD.
Diff targets require standard mode.
Set model and native Codex settings on the client:
const security = new CodexSecurity({
codexOverrides: {
model_reasoning_effort: "high",
analytics: { enabled: false },
},
});Constructor options are codexOverrides, pythonPath, and pluginPath.
The bundled runtime and plugin are used by default. pythonPath overrides the
PYTHON environment variable. To choose a model, set codexOverrides.model.
New and resumed Deep Scans require a current plugin with
directDeepScanEngine: 1, workerProviderSnapshot: 4, and isolated worker
configuration support. Older custom plugins fail before scan execution; update
the plugin or omit pluginPath to use the bundled version. Discovery, reducer,
and resumed workers inherit per-scan provider, authentication, environment, and
executable settings, with their existing read-only permissions. Reading saved
reports does not require these execution capabilities.
The SDK no longer adapts the older node ./mcp/server.mjs MCP entrypoint; use
the current shell or Windows launcher for runtime-root routing.
Custom plugins must support the current workbench protocol for scan comparison
and archival. Update an older custom plugin or omit pluginPath to use the
bundled version. The SDK no longer adapts payloads or archives scan directories
on behalf of older workbench implementations.
Scans use an isolated Codex configuration. See runtime configuration for supported overrides and defaults.
Windows defaults to windows.sandbox = "elevated" to enforce credential read
denials. Explicit windows.sandbox settings remain unchanged; Codex reports
policies unsupported by the selected backend.
Load shared CLI and SDK settings explicitly:
import { CodexSecurity, loadProjectConfig } from "@openai/codex-security";
const { config, options } = await loadProjectConfig("codex-security.yaml");
const security = new CodexSecurity(config);
try {
const result = await security.run("/path/to/repository", options);
if (
options.failureSeverity !== undefined &&
result.hasFindingsAtOrAbove(options.failureSeverity)
) {
process.exitCode = 1;
}
} finally {
await security.close();
}run() does not discover project files. Paths inside a file resolve from that
file's directory; scope paths resolve from the repository. For a typed object,
use resolveProjectConfig(input, directory?). Override loaded options with
{ ...options, maxCostUsd: 5 }.
Project files are trusted configuration and can select model endpoints or start MCP servers. Keep CI scanner configuration outside the checkout being assessed. See the project configuration guide for the schema and precedence rules.
const plan = await security.preflight("/path/to/repository", {
target: ["src"],
maxCostUsd: 5,
});
console.log(plan);preflight() checks local inputs without starting Codex or using the network.
It does not verify credentials, model access, Python, or the plugin. The CLI
equivalent is scan --dry-run.
const result = await security.run("/path/to/repository", {
mode: "deep",
workers: 2,
subagents: 0,
stopAfterNoNew: 3,
stopAfterConsecutiveErrors: 3,
maxDiscoveryRuns: 10,
maxTimeHours: 1.5,
});workers controls concurrent discovery workers; subagents controls delegation
within each worker. Time and run limits apply to discovery. After discovery
stops, the scan combines and returns completed findings. See
deep scan settings for defaults and saved settings.
Use onProgress for scan progress and onCost for cost updates.
Follow scans with onWorkerEvent and onReconnect. onWorkerEvent reports
persisted worker sessions discovered by the SDK's existing session tracker,
independently of model-emitted status markers:
await security.run(repository, {
onWorkerEvent(event) {
console.log(`Worker ${event.worker} observed`);
},
});The callback contains only { kind: "observed", worker: number }. The scan-local
worker number matches onActivity and onSessionEvent; no prompts, raw thread
IDs, or session contents are exposed. Each session is reported once per run,
including nested workers and scan-associated validation or Deep Scan sessions.
On resume, already persisted workers can be reported again. Observation ends
with scan cost tracking, before postScanPrompt.
This works with the bundled Codex version. Persistence and polling can delay
notification, and missing notifications do not prove that delegation was skipped.
An observed session does not establish that a worker just started or that file
review has begun. The callback does not report failed spawn attempts, phase names,
or planned counts, and cannot act as a pre-dispatch gate. Use maxCostUsd or
signal for cancellation. Observer failures go to onObserverError without
stopping the scan.
onWorkerStatus remains available for tool-derived preflight status and
best-effort phase dispatch counts from model-emitted text markers. A missing
dispatch status does not mean delegation was skipped. onSessionEvent receives
saved events with thread IDs and worker numbers and can contain source code or
credentials. Deep scans additionally expose durable independent-review counts
through onDeepProgress: completed, active, and maximum. The maximum is a
configured cap, not a percentage denominator. The optional consolidating flag
reports when results are being combined or the coordinator has finished.
ScanOptions lists all callbacks.
Costs estimate API-equivalent model usage, not your bill or ChatGPT subscription
allowance. Use cost.estimatedUsdRange for reporting. maxCostUsd uses the
short-context estimate; in-flight requests can exceed it. Post-scan prompts run
outside that limit. Matching earlier findings can also make model calls.
See progress and cost for accounting and budget callbacks.
import { writeFile } from "node:fs/promises";
const result = await security.validate({
repositoryPath: "/path/to/repository",
finding: {
title: "Possible SQL injection",
location: "src/query.ts:42",
},
});
console.log(result.disposition, result.report);
await writeFile("/path/to/reports/assessment.md", result.report, "utf8");Pass finding text or a JSON-serializable object, not a file path. Standalone
validation uses source evidence in a read-only, offline session. It does not build
the target, execute application code, run tests or PoCs, or add a scan to history.
The validator returns the assessment without writing report files. The example
saves result.report in an existing directory. outputDir selects the session
directory, not a report destination. Callers that previously read reports from it
must save result.report instead.
Callers needing runtime proof must arrange a separate reproduction step. Standard,
Deep, and diff scan validation keep their existing workflows.
The disposition is reportable, suppressed, not_applicable, or deferred.
reportable can rely on static analysis; deferred means there is insufficient
evidence. Failed or malformed responses reject the promise. outputDir, auth,
and signal are also supported.
To validate GitHub code scanning alerts, first import them with
importGitHubCodeScanningAlerts(). See the
import guide for CLI and SDK examples.
patch() runs the bundled remediation workflow non-interactively against a
workspace that the caller has intentionally made writable:
const security = new CodexSecurity();
try {
const result = await security.patch({
repositoryPath: "/path/to/disposable/workspace",
finding: {
title: "Possible SQL injection",
summary: "User input reaches a raw SQL query.",
locations: [{ path: "src/query.ts", startLine: 42 }],
},
signal,
onActivity(activity) {
console.log(activity.description);
},
onCost(cost) {
console.log(cost.estimatedUsd);
},
});
switch (result.status) {
case "verified":
case "no_change":
console.log(result.verificationReport);
break;
case "blocked":
case "failed":
console.error(result.reason);
break;
}
} finally {
await security.close();
}Pass literal finding text or a JSON-serializable object; strings are never read
as file paths. Sandboxed patch commands may edit only repositoryPath and run
without network access or web search. Patch workspaces are always treated as
untrusted Codex projects, so repository-local Codex configuration and MCP
servers are not loaded. Host-configured tools retain their host permissions.
The method does not create a commit, push, open a pull request, publish findings,
change remote finding state, or add a scan to history.
Callers remain responsible for reviewing and deriving the authoritative diff,
approval, commit creation, and delivery.
The discriminated result reports verified, no_change, blocked, or
failed, plus repository-relative changedFiles, threadId, and estimated
cost when model pricing and usage are available. Verified and no-change
results include verificationReport; blocked and failed results include
reason. Transport, authentication, cancellation, incomplete turns, and
malformed results reject the promise. Failed, blocked, or interrupted operations
can leave partial workspace changes for the caller to inspect or discard.
changedFiles is model-reported metadata, not the authoritative diff.
Patch-risk assessment is not included in this API.
Patch operations reuse constructor configuration and credentials. Pass auth,
safetyIdentifier, model, or reasoningEffort for per-call selection.
onActivity, onSessionEvent, onCost, onReconnect, onAuthentication,
onWarning, and onObserverError use the same observer contracts as scans.
After installing the CLI, sign in if needed:
cs loginFrom your repository, optionally draft a SECURITY.md
that explains what counts as a security issue in your project:
cs policy .The draft is saved outside your repository. Review the diff and notes, edit the
draft, then copy only SECURITY.md to the Policy target shown. Skip this step
to keep your current policy or scan without one.
Then scan the repository:
cs scan .To narrow the scan scope or check the configuration before scanning:
cs scan . --path src --path tests
cs scan . --diff origin/main --json
cs scan . --dry-runUse --help to find commands and <command> --help for options. Scans are
report-only by default. Add --fail-on-severity high to return exit code 1
for high or critical findings; execution and required-output failures return 2.
Scope exclusions and follow-up notes do not change a completed scan's exit code.
The CLI reference covers scan history, reruns, bulk and component scans, custom validation, imports, patching, and integrations.
Use policy to draft a new SECURITY.md or update an existing one. To select a
component:
cs policy . --path services/apiExisting files stay unchanged until you review and copy the draft to the Policy target shown. Scans already use root and component policies; you can keep them without generating new ones.
The SDK provides generatePolicy(), preflightPolicy(), and previewPolicy(). See
policy generation for SDK examples,
policy locations and reporting instructions, headless use, and saved artifacts.
Export saved findings or a threat model without starting another analysis:
cs export --scan SCAN_ID --export-format sarif --output results.sarif
cs export --scan SCAN_ID --artifact threat-model --output threatmodel.mdThe SDK provides exportArtifact() for the same offline operations. See
exports and CI for details. For repository or pull
request scans in GitHub Actions, use the
GitHub Action guide.
Separate examples cover
GitHub Actions with Bedrock
and Azure Pipelines.
Use classify-severity with your own rubric to assess saved findings without
changing their original severity or evidence. The SDK exposes classifySeverity(),
classifyScanSeverity(), and classifyScanDirectorySeverity(). See
severity classification for selection,
checkpointing, and publication behavior.
Use suggest-owners or the SDK's suggestOwners() to suggest contributors based
on CODEOWNERS, source, and Git history. Declared owners take priority over Git
contributors. Suggestions do not assign tickets. See
owner suggestions for input and output examples.
publish scan --to cloud uploads selected findings to Codex Security Cloud.
It requires ChatGPT credentials; inference API keys and AWS credentials do not
grant Cloud access. See Cloud publication
for setup and review steps, or Linear publication
for issue creation.
Saved-scan deduplication uses local SQLite directly:
cs dedupe --scan SCAN_ID --jsonThe findings guide covers local storage, embedding
credentials, deduplication, backups, and independently operated HTTP endpoints.
The local serve command and browser dashboard have been removed. Existing
scans, findings, and duplicate groups remain in the workbench database.
For records stored in your own system, see
SDK records deduplication.
Use the scanner image and Compose files to scan a list of repositories with persistent results and authentication. See containerized bulk scans for setup, or the workflow runner for individual CLI stages in containers.
Codex Security runs with your operating-system permissions. Scan subprocesses can inherit your environment, so start them with only the credentials they need. Local tools running under the same account are trusted.
The scan profile allows reads across the local filesystem and writes to workspace
roots. Execution approvals are reviewed automatically and may grant extra
permissions for an operation. Set codexOverrides.approval_policy: "never"
(or CLI --codex 'approval_policy="never"') to deny permission requests.
Host and network restrictions still apply.
Repository contents, model output, and imported artifacts do not authorize access to other targets, disclosure of credentials, or writes outside approved paths. Keep state and scan artifacts private and outside the repository.
- Online SDK guide
- CLI reference
- Findings guide
- GitHub issues for bugs and feature requests
- Security policy for private vulnerability reporting