Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions docs/scanner-imports/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Preview a scanner report with the CLI, then save the findings in the local
workbench or send a supported report to Codex Security Cloud.

In Codex, ask to import a saved report or fetch selected findings with an
available CLI, API, or MCP connection. You can publish selected findings from
the local workbench in a later session using their stored IDs and versions.
[Walk through acquisition, local import, and publication in Codex](workbench.md)

## Choose your input

| Starting point | Command |
Expand Down
126 changes: 126 additions & 0 deletions docs/scanner-imports/workbench.md

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions evals/workflow-routing/cases.mts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ export const cases = [
"Triage this reported vulnerability against this repository: GET /invoices/:id exposes another user's invoice without checking ownership. Assess the claim; do not fix it.",
skill: "triage-finding",
},
{
id: "acquire-scanner-evidence",
request:
"Fetch the two existing Guardian findings I selected on main and preview importing them into this checkout.",
skill: "publish-findings",
},
{
id: "publish-stored-evidence",
request:
"Publish the high-severity scanner findings from yesterday’s local import to the connected Cloud repository.",
skill: "publish-findings",
},
{
id: "dependency-alert",
request:
Expand Down
41 changes: 41 additions & 0 deletions examples/normalized-import/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Import Trivy and Guardian findings offline

Run this from the repository root with the SDK and plugin built. Set `TMPDIR` to a directory outside any Git worktree. The example uses a saved Trivy report and a recorded Guardian tool response, so it needs no vendor credentials.

```sh
demo=$(mktemp -d "${TMPDIR:-/tmp}/stored-findings.XXXXXXXX")
git init -q "$demo/checkout"
git -C "$demo/checkout" remote add origin https://github.com/example/project
export CODEX_SECURITY_STATE_DIR="$demo/state" DEMO_REPOSITORY="$demo/checkout"
cd sdk/typescript

node bin/codex-security.mjs publish findings ../../examples/normalized-import/trivy-report.json \
--to local --repository "$DEMO_REPOSITORY" --provider trivy \
--source-key example/project/main --trivy-scan-root . --yes --format json

node --input-type=module <<'JS'
import { readFile } from "node:fs/promises";
import {
collectSelectedSemgrepGuardianFindings, normalizeSemgrepFindings,
listLocalExternalImports, prepareNormalizedLocalImport,
} from "@openai/codex-security";

const repository = process.env.DEMO_REPOSITORY;
const json = async name => JSON.parse(await readFile("../../examples/normalized-import/" + name, "utf8"));
const selected = await json("guardian-selection.json");
const capture = await collectSelectedSemgrepGuardianFindings(selected, {
callTool: () => json("guardian-response.json"),
});
const local = await prepareNormalizedLocalImport(
normalizeSemgrepFindings(capture, {}, "local"),
{ repository, provider: "semgrep", sourceKey: selected.sourceKey },
);
console.log(local.preview);
await local.import();
console.table(await listLocalExternalImports({ repository }));
JS
```

The history shows two imports. The Guardian request selected string ID `9007199254740993` from a response containing two findings. A live MCP connection supplies the same collector's `callTool`.

In Codex, open the same checkout with the same workbench state and say **“Preview the high-severity findings from these two imports for publication to my Cloud repository.”** Codex reads the stored versions and shows the source groups and exclusions for review. [User walkthrough](../../docs/scanner-imports/workbench.md) · [SDK selection and publication](../../sdk/typescript/docs/sdk.md#import-external-findings)
185 changes: 23 additions & 162 deletions plugins/codex-security/skills/publish-findings/SKILL.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
interface:
display_name: "Publish Findings"
short_description: "Import vendor findings locally or to Cloud"
default_prompt: "Use $publish-findings to preview selected vendor findings for my repository and import them to my chosen destination."
short_description: "Import and publish stored scanner findings"
default_prompt: "Use $publish-findings to import the selected scanner findings or publish a selection from my local workbench."
policy:
allow_implicit_invocation: true
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ Use native Java, a released CxFlow JAR (1.6.37+), and a trusted SAST-only profil

## Preview and import

Pass the successful helper's printed path as the quoted file argument to `codex-security publish findings` in the next tool call. Use `--provider checkmarx`, the requested destination, verified `--source-repository-url`, a stable product/tenant/project/ref `--source-key`, and `--dry-run --format json`. Review the scope, findings and exclusions. Verify native paths against the checkout before opening source files.
Pass the successful helper's printed path as the quoted file argument to `codex-security publish findings` in the next tool call. Use `--provider checkmarx --to local --repository CHECKOUT`, the verified `--source-repository-url`, a stable product/tenant/project/ref `--source-key`, and `--dry-run --format json`. Review the scope, findings and exclusions. Verify native paths against the checkout before opening source files.

After confirmation, reuse that file and those options for [local import](../SKILL.md#import-locally), [Cloud publication](../SKILL.md#publish-to-cloud) and retries. Remove the helper’s temporary directory after readback unless the operator wants it retained. Keep operator-supplied files. [User guide](https://github.com/openai/codex-security/blob/main/docs/scanner-imports/checkmarx.md)
After confirmation, reuse that file and those options for the [local import](../SKILL.md#import-locally). Use its stored selection for [Cloud publication](../SKILL.md#publish-to-cloud) and retries. Remove the helper’s temporary directory after readback unless the operator wants it retained. Keep operator-supplied files. [User guide](https://github.com/openai/codex-security/blob/main/docs/scanner-imports/checkmarx.md)
10 changes: 10 additions & 0 deletions sdk/typescript/src/cli-help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,16 @@ export function formatCliHelp(text: string, columns = 80): string | undefined {
label: "Live provider",
description: "Choose a collector below.",
},
{
label: "CLI, API, or MCP source",
description:
"Ask Codex to import it using the publish-findings skill.",
},
{
label: "Workbench findings",
description:
"Ask Codex to publish a stored import or selected finding versions.",
},
{
label: "Saved vendor report",
description:
Expand Down
2 changes: 1 addition & 1 deletion sdk/typescript/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4116,7 +4116,7 @@ export async function main(
},
},
],
hint: "Choose your scanner with --provider. Reuse --source-key for later imports from the same source. See the scanner import guide for supported formats, repository setup, and export examples: https://github.com/openai/codex-security/blob/main/docs/scanner-imports/README.md. Gzip files are supported. Use --to local to save unassessed findings without a Cloud login. Use --full-output with --format json or --format jsonl.",
hint: "Choose your scanner with --provider. Reuse --source-key for later imports from the same source. For findings already in the workbench, use the SDK's prepareStoredFindingsPublication. The installed @openai/codex-security package includes the workflow in docs/sdk.md under Import external findings. See the scanner import guide for supported formats, repository setup, and export examples: https://github.com/openai/codex-security/blob/main/docs/scanner-imports/README.md. Gzip files are supported. Use --to local to save unassessed findings without a Cloud login. Use --full-output with --format json or --format jsonl.",
destructive: true,
args: z.object({
file: z
Expand Down
2 changes: 2 additions & 0 deletions sdk/typescript/tests-ts/cli-help.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ describe("CLI help", () => {
const menu = (await help(["import", "--help"])).replace(/\s+/gu, " ");
expect(menu).toContain("publish findings --help");
expect(menu).toContain("scan import --help");
expect(menu).toContain("publish-findings skill");
expect(menu).toContain("publish a stored import");
const vendor = await help(["publish", "findings", "--help"], 60);
const preview = vendor
.split("\n")
Expand Down
Loading