Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
0691542
Preserve source-backed threat models across scan workflows
mldangelo-oai Aug 16, 2026
997b2f3
Keep architecture mapping separate from audit coverage
mldangelo-oai Aug 16, 2026
8591310
Carry saved threat models through Workbench diff completion
mldangelo-oai Aug 16, 2026
ea48c54
Keep generated resource evidence safe and source-aware
mldangelo-oai Aug 16, 2026
10c7252
Keep scan-specific threat models out of the shared cache
mldangelo-oai Aug 16, 2026
50d7914
Preserve per-scan model bodies without cache metadata
mldangelo-oai Aug 16, 2026
39fd860
feat(cli): generate and review SECURITY.md
mldangelo-oai Aug 17, 2026
0074827
fix(cli): keep policy generation scoped and reviewable
mldangelo-oai Aug 17, 2026
f27e4cd
fix(cli): preserve policy evidence during generation
mldangelo-oai Aug 17, 2026
be2fb8f
fix(cli): preserve policy updates and cancellation
mldangelo-oai Aug 17, 2026
78c9325
fix(cli): retain previous policy files after updates
mldangelo-oai Aug 17, 2026
82c1cbe
fix(cli): bind policy drafts to their source guidance
mldangelo-oai Aug 17, 2026
1f36f9d
fix(cli): handle linked policies during preflight
mldangelo-oai Aug 17, 2026
2fd78b1
fix(cli): honor policy output options
mldangelo-oai Aug 17, 2026
53553bd
fix(cli): report policy failures in full output
mldangelo-oai Aug 17, 2026
233d2d5
fix(cli): preserve policy scope and user choices
mldangelo-oai Aug 17, 2026
b1de4d9
fix(cli): distinguish command names from option values
mldangelo-oai Aug 17, 2026
7f9b827
fix(ci): make policy checks portable
mldangelo-oai Aug 17, 2026
7c5b18d
fix(cli): keep component policy changes in scope
mldangelo-oai Aug 17, 2026
b1233a9
fix(cli): preserve the selected policy scope
mldangelo-oai Aug 17, 2026
63e50f8
fix(cli): protect reporting policies and clarify output errors
mldangelo-oai Aug 17, 2026
3ecd6c0
fix(cli): validate the complete policy checkout
mldangelo-oai Aug 17, 2026
2f89060
fix(cli): keep policy targets in Git worktrees
mldangelo-oai Aug 17, 2026
fe4d54d
fix(cli): protect enclosing policy checkouts
mldangelo-oai Aug 17, 2026
584d9df
fix(cli): keep policy Python lookup scoped
mldangelo-oai Aug 17, 2026
5c0acd8
fix(cli): normalize reporting policy directory casing
mldangelo-oai Aug 17, 2026
f960069
refactor(cli): simplify policy setup and validation
mldangelo-oai Aug 17, 2026
53878f3
Merge remote-tracking branch 'origin/main' into mdangelo/codex/securi…
mldangelo-oai Aug 17, 2026
2294046
refactor(cli): check policy write scope when applying
mldangelo-oai Aug 17, 2026
10d2f06
merge: record extracted policy draft base
mldangelo-oai Aug 17, 2026
b129153
refactor(cli): separate policy drafting from application
mldangelo-oai Aug 17, 2026
5370aa5
Merge commit '60acf79eccc08e94d31b14837e76f665a1c85cb6' into mdangelo…
mldangelo-oai Aug 17, 2026
1875401
fix(cli): preserve policy scope and retry verification
mldangelo-oai Aug 17, 2026
ed9bf1b
merge: carry policy preview fixes into application
mldangelo-oai Aug 17, 2026
f95270c
fix(cli): bind policy application to validated inputs
mldangelo-oai Aug 17, 2026
4174bb9
merge: carry policy input and output fixes into application
mldangelo-oai Aug 17, 2026
ab36a6a
merge: update policy application to the corrected draft layer
mldangelo-oai Aug 17, 2026
fc6f0a2
fix(cli): preserve policy boundaries on alias and copy failures
mldangelo-oai Aug 17, 2026
c0c1b96
Merge policy draft path checks
mldangelo-oai Aug 17, 2026
ff9b205
Merge current main and shared command helpers
mldangelo-oai Aug 17, 2026
b3bbf46
fix(cli): support policy writes without Windows hard links
mldangelo-oai Aug 17, 2026
c4d0e42
Merge policy input validation fixes
mldangelo-oai Aug 17, 2026
9b598f5
Merge read-only drafting cleanup
mldangelo-oai Aug 17, 2026
e95ada3
Merge verified policy drafting fixes
mldangelo-oai Aug 18, 2026
74b0292
fix(cli): simplify policy plugin setup and errors
mldangelo-oai Aug 18, 2026
bfbd1d7
Merge verified policy evidence fixes
mldangelo-oai Aug 18, 2026
983bb2e
fix(policy): preserve retry verification status
mldangelo-oai Aug 18, 2026
bfd731c
Merge branch 'mdangelo/codex/security-policy-drafts' into mdangelo/co…
mldangelo-oai Aug 18, 2026
6123c84
test(cli): use the fixture Python for policy retries
mldangelo-oai Aug 18, 2026
8ecde8c
fix(policy): preserve read-only mode for new files
mldangelo-oai Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

FROM node:22-bookworm-slim@sha256:6c74791e557ce11fc957704f6d4fe134a7bc8d6f5ca4403205b2966bd488f6b3 AS package

RUN apt-get update \
&& apt-get install --no-install-recommends --yes python3 \
&& rm -rf /var/lib/apt/lists/*

WORKDIR /build/sdk/typescript

COPY sdk/typescript/package.json sdk/typescript/pnpm-lock.yaml ./
Expand Down
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,20 @@ npx @openai/codex-security policy . --headless --output-dir /path/outside/reposi

The command reads the source, describes the system, builds a detailed threat
model, and drafts a short `SECURITY.md`. In a terminal, it asks about important
facts the code cannot establish and shows the proposed diff. It does not change
repository files. Review the saved policy and check for other policy files that
link to the target before copying it. Later scans read the root and nested
`SECURITY.md` files.
facts the code cannot establish, shows the proposed diff, and asks before
writing. Later scans read the approved root and nested `SECURITY.md` files.

To review a saved draft, edit its `SECURITY.md`, then run:

```bash
npx @openai/codex-security policy . --apply /path/outside/repository/policy --write
```

Use the same repository and `--path` as generation. Applying does not call the
model. It checks that the original and inherited policies are unchanged, keeps
the write inside the approved scope, and verifies the result. Updates retain the
previous file at the reported recovery path. Keep it until other writers have
closed it and any edits are reconciled.

Drafts are stored outside the repository and any enclosing Git checkout. The
same private directory contains `project-spec.md`, `THREAT_MODEL.md`, and review
Expand Down
82 changes: 63 additions & 19 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,9 @@ Trusted Access for Cyber. To apply or check your access, visit

## Generate a security policy

`policy` drafts a `SECURITY.md` for owner review. It uses the same Codex runtime,
authentication, model settings, and security guidance as scans, but does not
look for vulnerabilities or create a scan record. Codex can read files but
`policy` drafts or updates a `SECURITY.md` for owner review. It uses the same
Codex runtime, authentication, model settings, and security guidance as scans,
but does not look for vulnerabilities or create a scan record. Codex can read files but
cannot write them. Network access, web search, apps, and MCP servers are disabled.
The SDK saves the responses in a private directory outside the checkout.

Expand All @@ -227,57 +227,90 @@ that would spread a component policy to a wider scope.
Generation has three stages: describe the system, build a detailed threat model,
and draft the policy. In a terminal, the command asks about important facts the
source cannot establish, then shows the exact diff and decisions that need
review. If both a ChatGPT sign-in and an API key are available, it asks which to
use. Set `--auth chatgpt` or `--auth api-key` to choose explicitly.
review. It asks before writing to the repository. If both a ChatGPT sign-in and
an API key are available, it asks which to use. Set `--auth chatgpt` or
`--auth api-key` to choose explicitly.

### Review the draft
### Review and apply a saved draft

The command never changes repository files. Review the saved `SECURITY.md`
before copying it to the reported target path. Check whether another policy,
such as `.github/SECURITY.md` or `docs/SECURITY.md`, links to that target; a
manual copy can change the linked policy too. Preserve existing reporting
Review the saved `SECURITY.md` before applying it. Preserve existing reporting
instructions and obtain owner approval for exclusions, accepted risks, and
severity decisions. Later scans read the approved policy.

Preview checks that the selected policy and its parent policies have not
changed. Other source files are not frozen; generate a new draft if relevant
source or neighboring policy files change.

Use `--headless` or an explicit output format to skip questions. Unanswered
questions remain in the review notes. Drafts default to the Codex Security state
directory; `--output-dir` selects an empty directory outside every enclosing
Git checkout and its Git metadata.
Use `--headless` or an explicit output format to skip questions and write
prompts. Unanswered questions remain in the review notes. Drafts default to the
Codex Security state directory; `--output-dir` selects an empty directory
outside every enclosing Git checkout and its Git metadata.

```bash
npx @openai/codex-security policy . --path services/api \
--headless --output-dir /path/outside/repository/api-policy --json

# Review or edit the saved SECURITY.md.
npx @openai/codex-security policy . --path services/api \
--apply /path/outside/repository/api-policy --write
```

`--apply` loads the saved draft without starting Codex. Omit `--write` to review
and confirm interactively. `--write` requires `--apply`; it cannot write an
unseen model response. The repository and component must match the draft.
Before writing, the command checks that the original policy and inherited
guidance have not changed. It also rejects links that would change another
component's guidance or a separate reporting policy in `.github` or `docs`.
Fix those links before applying. It writes the reviewed bytes, verifies that
the policy resolver can read them, and does not stage, commit, or publish them.
If a write succeeded but verification failed, fix the reported problem and
retry the same saved draft with `--write`. An exact-content retry verifies the
installed policy without replacing it. Keep any previously reported recovery
file until concurrent edits have been reconciled.

Updates keep the previous file so a late save through an open editor handle is
not lost. The command moves it into the private artifact directory when possible;
otherwise it stays beside the target as `.SECURITY.md.*.previous`. The CLI prints
the path and returns `recoveryPath` in JSON. Keep that file until other writers
have closed it and any edits are reconciled. A `recovery_required` result means
the replacement needs manual reconciliation. A `written_unverified` result means
the new policy was written but verification failed. Inspect the reported paths
before retrying. Once a write commits, SDK cancellation does not skip the
remaining checks. A terminal interrupt or process failure can still leave a
`written_unverified` result. A later Ctrl-C or SIGTERM forces the CLI to stop.

Save edited drafts as UTF-8. If generation used a custom `--plugin-path`, select
it again when applying a saved draft. Saved metadata cannot choose executable
plugin code. Both plugin directories and ZIP files are supported.

The artifact directory contains:

| File | Purpose |
| ---------------------- | --------------------------------------------------------- |
| `SECURITY.md` | Editable policy draft. |
| `THREAT_MODEL.md` | Detailed threat model with source references. |
| `project-spec.md` | System description and security boundaries. |
| `previous-SECURITY.md` | Original policy used for the diff. |
| `previous-SECURITY.md` | Original policy used for the diff and overwrite checks. |
| `policy-draft.json` | Target, policy hashes, revision, model, and review notes. |

An update may also retain `recovery-SECURITY-*.md` files.

Keep detailed models and intermediate files private until they have been
reviewed for disclosure. Generation does not imply owner approval or confirm
that a threat scenario is a vulnerability.

`--format md` writes the draft to stdout. `--json` returns paths, review notes,
status, and estimated cost. Global filters and token options work with these
formats. Progress goes to stderr. `--full-output` reports failures with
`ok: false`. `--max-cost` applies to the whole generation. If a stage cannot
`ok: false`. Plain `--json` retains recovery status and paths when a write
needs attention. `--max-cost` applies to the whole generation. If a stage cannot
inspect required source evidence, generation stops and preserves completed
documents. Fix the reported problem and use a new output directory to retry.

### Generate a policy from TypeScript

```ts
import { CodexSecurity } from "@openai/codex-security";
import { CodexSecurity, applySecurityPolicy } from "@openai/codex-security";

const security = new CodexSecurity();
try {
Expand All @@ -289,6 +322,8 @@ try {

console.log(await security.previewPolicy(draft));
// Open draft.draftPath in an editor to review the saved policy.
// Obtain approval for this exact draft before calling:
// await applySecurityPolicy(draft, { pythonPath: security.config.pythonPath });
} finally {
await security.close();
}
Expand All @@ -298,11 +333,20 @@ try {
`previewPolicy()` uses the client's Python setting and makes terminal control
characters visible. The standalone `securityPolicyDiff()` returns a raw diff
for files or other non-terminal uses; pass an interpreter explicitly if needed.
`generatePolicy()` accepts `auth`, `path`, `knowledgeBasePaths`, `outputDir`,
`maxCostUsd`, `signal`, and progress and cost callbacks. An optional
`generatePolicy()` never edits the repository. It accepts `auth`, `path`,
`knowledgeBasePaths`, `outputDir`, `maxCostUsd`, `signal`, and progress and cost
callbacks. An optional
`answerQuestions` callback receives each group of up to three owner questions
and a cancellation signal. Without it, the questions remain unresolved.

Use `loadSecurityPolicyDraft(repository, artifactDirectory, { path })` to load
an edited draft. `applySecurityPolicy()` returns `{ status, targetPath, recoveryPath }`;
`status` is `written` or `unchanged`.
`recoveryPath` is `null` when no existing file was replaced. Pass `{ pluginPath }`
when applying a saved custom-plugin draft. `SecurityPolicyVerificationError` and
`SecurityPolicyRecoveryError` identify files that need inspection or
reconciliation.

## CLI

```bash
Expand Down
Loading
Loading