Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
2814739
feat(cloud): publish selected Wiz findings with resumable receipts
codex Oct 8, 2026
b6bb46e
fix(cloud): normalize import readback and recover after resets
codex Oct 8, 2026
01d29ec
fix(cloud): serialize resumable finding publications
codex Oct 8, 2026
e6a2d48
fix(cloud): align import response cursor limits
codex Oct 8, 2026
b5ef54c
fix(cloud): checkpoint completed finding import batches
codex Oct 8, 2026
d27aea0
fix(cloud): retain checkpoints across overlapping retries
codex Oct 8, 2026
30b2e95
fix(cloud): validate imports before approval and simplify persistence
codex Oct 8, 2026
7b132cf
fix(cloud): show import evidence and clean failed writes
codex Oct 8, 2026
f798746
fix(cloud): format malformed import diagnostics
codex Oct 8, 2026
85bd613
fix(cloud): combine import validation and upload recovery
codex Oct 8, 2026
54913d3
fix(cloud): map Wiz container and package metadata
codex Oct 8, 2026
89648f8
fix(cloud): preserve Wiz metadata and match import result IDs
codex Oct 8, 2026
d775fe1
fix(cloud): preserve imported finding metadata and environment bindings
codex Oct 8, 2026
7759a2c
fix(cloud): preserve import scope across environment changes
codex Oct 8, 2026
f293e77
fix(cloud): allow publication processing time and preserve legacy eco…
codex Oct 8, 2026
b50aa71
Match numeric evidence sizes to Cloud validation
codex Oct 8, 2026
b18ed3b
Merge parallel Wiz publication fixes
codex Oct 8, 2026
98242d1
Merge main into Wiz findings publisher
mldangelo-oai Oct 9, 2026
6786d35
fix(cloud): preserve import evidence and report partial uploads
mldangelo-oai Oct 9, 2026
029e014
fix(cloud): isolate deployment routing and support Wiz report exports
mldangelo-oai Oct 9, 2026
1cfdeb4
fix(package): include Cloud endpoint module in archive checks
mldangelo-oai Oct 9, 2026
340e4fd
fix(import): resolve the selected Cloud repository directly
mldangelo-oai Oct 9, 2026
18ab10c
fix(cloud): link imports to the selected deployment
mldangelo-oai Oct 10, 2026
9ebf315
fix(plugin): relay deployment-specific findings links
mldangelo-oai Oct 10, 2026
837f84c
feat(import): map Wiz repository findings
mldangelo-oai Oct 10, 2026
e593fcf
fix(import): preserve normalized evidence and saved retries
mldangelo-oai Oct 10, 2026
bf38913
fix(import): keep secret confidence schema distinct
mldangelo-oai Oct 10, 2026
b749aa9
fix(import): match GitHub repository URL casing
mldangelo-oai Oct 10, 2026
772a636
fix(import): preserve large exports and failure output
mldangelo-oai Oct 10, 2026
5a44d4c
fix(import): derive branch qualifiers from repository URLs
mldangelo-oai Oct 10, 2026
a431663
fix(import): match custom GitHub Enterprise repository URLs
mldangelo-oai Oct 10, 2026
8a9e57a
Merge main and align Deep Scan package fixtures
mldangelo-oai Oct 10, 2026
2cef167
Merge main knowledge-context recovery updates
mldangelo-oai Oct 10, 2026
25453a9
Merge latest findings publisher updates with CI fixes
mldangelo-oai Oct 10, 2026
2e6daad
fix(import): use Wiz inventory platform for repository matching
mldangelo-oai Oct 10, 2026
2fdc1f3
Preserve branch suffixes across GitHub repository case variants
mldangelo-oai Oct 10, 2026
1f94904
Integrate GitHub inventory metadata with reviewed CI fixes
mldangelo-oai Oct 10, 2026
74f2266
Keep publication checkpoints stable across inventory order and locales
mldangelo-oai Oct 10, 2026
77c6208
Preserve staged publication evidence across inventory normalization
mldangelo-oai Oct 10, 2026
e3d9054
Keep migrated publication retries bound to their saved selection
mldangelo-oai Oct 10, 2026
17e9591
fix(import): stabilize outstanding publication identity
mldangelo-oai Oct 10, 2026
cbb9f77
fix(import): preserve inventory qualifiers during replay
mldangelo-oai Oct 10, 2026
0d8bb35
Merge remote-tracking branch 'origin/main' into mdangelo/codex/remain…
mldangelo-oai Oct 11, 2026
7027a6a
refactor(import): share checkpoint reads and timestamp parsing
mldangelo-oai Oct 11, 2026
31100d7
Merge commit '5a7788b54abf6e954d94e27c248d5cb38bea5e07' into mdangelo…
mldangelo-oai Oct 11, 2026
d8307fa
Merge main while preserving import package contracts and worker fixtures
mldangelo-oai Oct 11, 2026
49b8fb2
chore: merge main and resolve integration conflicts
mldangelo-oai Oct 11, 2026
6b18386
fix(imports): select complete repository branch qualifiers
mldangelo-oai Oct 11, 2026
24815ef
test(package): include the external finding schema in archive fixtures
mldangelo-oai Oct 11, 2026
f37e1e8
Merge commit '49b8fb274f4be2c14b2fee1775d1de247e6e8710' into mdangelo…
mldangelo-oai Oct 11, 2026
a561d24
feat: expose normalized external finding publication in the SDK
mldangelo-oai Oct 14, 2026
0eb55e1
feat: import GitHub code-scanning alerts and security advisories to C…
mldangelo-oai Oct 14, 2026
382c682
fix: retain publication dependency types in the installed SDK
mldangelo-oai Oct 14, 2026
88bf568
fix: preserve GitHub source metadata and canonical import evidence
mldangelo-oai Oct 14, 2026
9351529
fix: retain GitHub URL identities and unmodified raw evidence
mldangelo-oai Oct 14, 2026
59949f6
chore: merge updated Wiz publisher into GitHub imports
mldangelo-oai Oct 16, 2026
b457494
Merge updated Wiz adapter parent
mldangelo-oai Oct 17, 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
32 changes: 30 additions & 2 deletions plugins/codex-security/skills/publish-findings/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
---
name: publish-findings
description: Import selected Wiz package vulnerabilities, SAST, repository secrets, and IaC findings to Codex Security Cloud after previewing the destination and evidence. Supports plain or gzip-compressed JSON and normalized JSONL; does not import workload secrets or cloud configuration, run a scan, or assess findings.
description: Import selected Wiz findings, GitHub code-scanning alerts, or GHSA security advisories to Codex Security Cloud after previewing the destination and evidence. Supports saved JSON/JSONL and gzip; does not run a scan, assess applicability, or synchronize triage decisions.
---

# Publish external findings

Use the installed `codex-security publish findings` command for both preview and upload. It owns source mapping, Cloud authentication, source versions, and saved request retries. Do not implement another HTTP uploader or put credentials in a command argument.

Cloud destinations currently support connected GitHub and GitHub Enterprise repositories, including custom Enterprise hostnames. Resolve the user's destination to its repository URL or Cloud repository ID; the command accepts either. Confirm that the repository is connected in the intended Cloud account and has an authorized environment. Use the existing file-backed ChatGPT login; explain a missing or incompatible login rather than changing credential storage automatically. Read selected Wiz findings through the user's configured connection or supplied export. Save the actual selected JSON records locally, retaining their IDs and evidence. Finish the requested pagination; if the user selected a subset, save that explicit subset and retain its named collection. The command does not fetch from Wiz or accept CSV, scan events, workload secrets, cloud configuration, or external network exports. The publisher also accepts JSONL records with `source_finding_id` and `evidence` as described in the CLI documentation.
Cloud destinations currently support connected GitHub and GitHub Enterprise repositories, including custom Enterprise hostnames. Resolve the user's destination to its repository URL or Cloud repository ID; the command accepts either. Confirm that the repository is connected in the intended Cloud account and has an authorized environment. Use the existing file-backed ChatGPT login; explain a missing or incompatible login rather than changing credential storage automatically.

## Wiz findings

Read selected Wiz findings through the user's configured connection or supplied export. Save the actual selected JSON records locally, retaining their IDs and evidence. Finish the requested pagination; if the user selected a subset, save that explicit subset and retain its named collection. The command does not fetch from Wiz or accept CSV, scan events, workload secrets, cloud configuration, or external network exports. The publisher also accepts JSONL records with `source_finding_id` and `evidence` as described in the CLI documentation.

Use a stable Wiz tenant/finding namespace as `--source-key`. A project filter is selection context, not a new identity. Confirm the selected assets or builds belong to the destination repository; do not infer a scanner branch or revision from the current checkout. Do not publish vendor credentials, unrelated records, or local assessments as original scanner evidence.

Expand All @@ -17,6 +21,30 @@ For SAST, repository secrets, and IaC, retain the explicit `data.sastFindings.no

Keep raw source records unchanged in `source_data`. New raw occurrence IDs are prefixed `sast:`, `secret:`, or `iac:`; existing package IDs are unchanged. For CSV report conversion, use a reviewed mapping of the actual header names into the documented normalized JSONL profile, set `evidence.details.kind` and the verified `details.repository.url`, and use the same prefixed occurrence ID. The command does not parse CSV directly. Select source paths and line numbers explicitly in secret reports; the standard metadata query lacks them. Preserve rule/CWE, range/snippet, detector validation, and IaC comparison fields in the typed details described in the CLI docs. Preserve empty comparison strings. Do not invent missing IDs, severity, revisions, or locations, retrieve credential values, test credentials, or apply suggested fixes. Vendor status, AI verdict, secret validation, introduced commits, and logical IaC resources are evidence, not Codex assessment or proof of runtime deployment.

## GitHub alerts and advisories

Keep code-scanning alerts and GHSA advisories as separate source families. Read code-scanning alerts with the existing `codex-security import github OWNER/REPO --format json` command. It defaults to open alerts on the default branch; use `--github-alert NUMBER` repeatedly for exact alerts or `--github-ref REF` for a selected ref. Save the complete output without field or token filters. The mapper retains the selected instance's ref, revision, detection state, rule, scanner, location and original evidence. Typed source status honors an alert-wide dismissal; otherwise it uses the selected instance's open/fixed state. Dismissal is not a Codex assessment. Missing security severity remains `unknown`; do not turn SARIF error/warning/note into vulnerability ratings.

Read advisories with `codex-security import github-advisories OWNER/REPO --format json`. It defaults to published repository advisories. `--github-advisory GHSA-xxxx-xxxx-xxxx` selects exact repository advisory IDs and may include private drafts only when the user selects them. To list private repository advisories, require the user's explicit state selection using `--github-state draft|triage|closed`. Do not combine a nondefault state with exact IDs. For public database records, use `--github-advisory-source global` with one or more explicit `--github-advisory` IDs; never enumerate or mirror the global database. Both readers are read-only and use the user's GitHub CLI authentication and `GH_HOST` when configured. Stop on a read failure instead of publishing an incomplete selection.

Publish the saved reader output with `--provider github`. Use a stable namespace such as `HOST/OWNER/REPO/code-scanning` or `HOST/OWNER/REPO/security-advisories` as `--source-key`, with separate keys for the two families. Code-scanning identities include the ref; GHSA records retain their advisory identity. Code-scanning and repository advisories must match the selected Cloud repository. Global advisory evidence omits source-repository provenance; the explicit Cloud destination selects where to investigate it. Preserve affected package ranges and patched versions without claiming an installed vulnerable dependency or inventing source locations. The original GHSA/CVE IDs remain evidence, not cross-provider source identities. GitHub dismissal, resolution and advisory withdrawal are not Codex assessments. Do not write back to GitHub or include Dependabot alerts without a separately supported ingestion path.

```sh
codex-security import github example/project --format json > /path/to/alerts.json
codex-security publish findings /path/to/alerts.json \
--to cloud --repository https://github.com/example/project --provider github \
--source-key github.com/example/project/code-scanning --dry-run --format json

codex-security import github-advisories example/project \
--github-advisory-source global --github-advisory GHSA-2345-6789-cfgh \
--format json > /path/to/advisories.json
codex-security publish findings /path/to/advisories.json \
--to cloud --repository https://github.com/example/project --provider github \
--source-key github.com/example/project/security-advisories --dry-run --format json
```

## Review and publish

For staging or another Cloud deployment, set `CODEX_SECURITY_CLOUD_BASE_URL` to its API root before both preview and upload. If the Cloud page or user supplies its app URL, also set `CODEX_SECURITY_CLOUD_WEB_URL` to that full URL so the command can return a repository Findings link. The UI setting does not change API routing or authentication. Use that deployment's login and an isolated state directory for tests. Verify `cloudApiUrl` and any `cloudUrl` in the preview against the intended deployment; the former is the API endpoint and the latter is the UI link. Saved retries are separated by deployment. The native scan setting `CODEX_SECURITY_CLOUD_PUBLISH_URL` does not route vendor imports. Never fall back to production when staging is unavailable.

```sh
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
interface:
display_name: "Publish Findings"
short_description: "Preview and publish vendor findings to Cloud"
default_prompt: "Use $publish-findings to preview selected Wiz findings for my Cloud repository."
default_prompt: "Use $publish-findings to preview selected Wiz findings, GitHub code-scanning alerts, or GHSA advisories for my Cloud repository."
policy:
allow_implicit_invocation: true
9 changes: 9 additions & 0 deletions sdk/typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,15 @@ grant Cloud access. See [Cloud publication](docs/cli.md#publish-findings-to-clou
for setup and review steps, or [Linear publication](docs/cli.md#publish-completed-scans-to-linear)
for issue creation.

The SDK also exposes `prepareExternalPublication(file, options)` for saved Wiz or GitHub
imports and `prepareNormalizedExternalPublication(findings, options)` for
normalized external evidence. Both resolve the Cloud repository and return a
`preview` plus a separate `publish()` operation. Inspect the preview before
calling `publish()`. Imported evidence remains not assessed by Codex, and saved
requests and receipts support retries after interruption. GitHub code-scanning
alerts and GHSA advisories have [separate readers and mappings](docs/cli.md#import-github-findings-to-cloud);
advisory imports preserve affected ranges without claiming an installed dependency.

## Findings storage and deduplication

Saved-scan deduplication uses local SQLite directly:
Expand Down
100 changes: 100 additions & 0 deletions sdk/typescript/docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -1733,6 +1733,106 @@ record absolute Node/CLI paths. If those change, back up and remove the verified
generated hook, then reinstall with the same threshold. Restore the backup if
installation fails. The installer respects `core.hooksPath`.

## Import GitHub findings to Cloud

Save code-scanning alerts with the existing read-only importer, then inspect the
Cloud publication preview:

```bash
codex-security import github example/project --format json > /path/outside/repository/alerts.json
codex-security publish findings /path/outside/repository/alerts.json \
--to cloud --provider github --repository https://github.com/example/project \
--source-key github.com/example/project/code-scanning --dry-run --format json
```

After reviewing the destination, source, exclusions and evidence, repeat the
publication command without `--dry-run` and confirm it, or add `--yes` for a
previously reviewed input. Authentication, batching, saved receipts, partial
results and interrupted-upload recovery follow the [Wiz publication flow](#import-wiz-findings).
JSON, JSONL and gzip are supported. Save complete import output without field or
token filters.

Use a stable source key for the GitHub host, repository and finding family.
Code-scanning identities also include the selected ref, so an import from another
branch cannot replace an existing branch's evidence. GitHub's source state and
full original alert stay attached to the source report. An alert-wide dismissal
applies to every branch; otherwise the selected instance supplies the open/fixed
state. Dismissal or a fixed state does not create a Codex assessment. Alerts without
a security severity are reported as `unknown`; SARIF error/warning/note levels are not vulnerability ratings.

The SDK offers the same preview and publication boundary:

```ts
import {
importGitHubCodeScanningAlerts,
normalizeGitHubCodeScanningAlerts,
prepareNormalizedExternalPublication,
} from "@openai/codex-security";

const alerts = await importGitHubCodeScanningAlerts({
repository: "example/project",
});
const prepared = await prepareNormalizedExternalPublication(
normalizeGitHubCodeScanningAlerts(alerts),
{
provider: "github",
repository: "https://github.com/example/project",
sourceKey: "github.com/example/project/code-scanning",
},
);
console.log(prepared.preview);
// After reviewing the preview:
const receipt = await prepared.publish();
```

### Import GHSA advisories separately

Repository advisories describe disclosures maintained by a repository. Global
advisories describe affected software in GitHub's public advisory database; they
do not establish that your repository installs that software.

```bash
# Read only published advisories for this repository.
codex-security import github-advisories example/project --format json > /path/outside/repository/advisories.json

# Select individual public database records without enumerating the database.
codex-security import github-advisories example/project \
--github-advisory-source global --github-advisory GHSA-2345-6789-cfgh \
--format json > /path/outside/repository/advisories.json

codex-security publish findings /path/outside/repository/advisories.json \
--to cloud --provider github --repository https://github.com/example/project \
--source-key github.com/example/project/security-advisories --dry-run --format json
```

`--github-advisory-source` defaults to `repository`. Repeat `--github-advisory`
to select exact IDs from that API, regardless of advisory state. Repository
lists default to `--github-state published`; `draft`, `triage`, and `closed`
require explicit selection. A nondefault state cannot be combined with exact
IDs. Global selection requires at least one ID and never lists the advisory
database. Both readers use `GH_HOST` and GitHub CLI authentication by default;
the SDK also accepts `githubHost` and `githubToken`.

Review the saved evidence before publication, including any selected private
advisories. Import failure returns no partial selection. Publication reports
invalid records as exclusions and retains acknowledged receipts if a later
batch or readback fails.

Advisory evidence retains GHSA/CVE IDs, affected version ranges, available
patched versions, source status and original JSON. It does not infer an installed
version or source location. Global advisories omit a source repository; the
explicit Cloud destination binds the import for investigation. Repository
advisories retain and check their source repository. Withdrawal remains vendor
state, and all imported evidence remains not assessed by Codex. Use a separate
source key from code-scanning alerts; shared advisory IDs do not combine source
records from different providers.

In the SDK, call `importGitHubAdvisories()` and `normalizeGitHubAdvisories()`
with `prepareNormalizedExternalPublication()` as shown above. The former defaults
to `{ source: "repository", state: "published" }`; use
`{ source: "global", advisoryIds: ["GHSA-2345-6789-cfgh"] }` for selected database
records. Both forms require `repository: "OWNER/REPO"` as source or target context.

## Import alerts from the CLI

```bash
Expand Down
70 changes: 64 additions & 6 deletions sdk/typescript/schemas/external-findings.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@
"additionalProperties": false,
"properties": {
"provider": {
"enum": ["wiz", "endor", "snyk"],
"enum": ["wiz", "endor", "snyk", "github"],
"title": "Provider",
"type": "string"
},
Expand All @@ -393,6 +393,20 @@
"title": "ImportSource",
"type": "object"
},
"ImportedAdvisoryContext": {
"additionalProperties": false,
"description": "Where the advisory was read; applicability is assessed separately.",
"properties": {
"source": {
"enum": ["repository", "global"],
"title": "Source",
"type": "string"
}
},
"required": ["source"],
"title": "ImportedAdvisoryContext",
"type": "object"
},
"ImportedAssessment": {
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -506,12 +520,29 @@
"description": "Typed repository evidence; vendor state is not a Codex assessment.",
"properties": {
"kind": {
"enum": ["sast", "secret", "iac"],
"enum": ["sast", "secret", "iac", "advisory"],
"title": "Kind",
"type": "string"
},
"repository": {
"$ref": "#/$defs/ImportedRepositoryReference"
"anyOf": [
{
"$ref": "#/$defs/ImportedRepositoryReference"
},
{
"type": "null"
}
]
},
"advisory": {
"anyOf": [
{
"$ref": "#/$defs/ImportedAdvisoryContext"
},
{
"type": "null"
}
]
},
"source_status": {
"anyOf": [
Expand Down Expand Up @@ -637,7 +668,7 @@
"title": "File Url"
}
},
"required": ["kind", "repository"],
"required": ["kind"],
"title": "ImportedFindingDetails",
"type": "object"
},
Expand All @@ -651,7 +682,14 @@
"type": "string"
},
"severity": {
"enum": ["critical", "high", "medium", "low", "informational"],
"enum": [
"critical",
"high",
"medium",
"low",
"informational",
"unknown"
],
"title": "Severity",
"type": "string"
},
Expand Down Expand Up @@ -910,6 +948,19 @@
"default": null,
"title": "Installed Version"
},
"vulnerable_version_range": {
"anyOf": [
{
"maxLength": 512,
"minLength": 1,
"type": "string"
},
{
"type": "null"
}
],
"title": "Vulnerable Version Range"
},
"manifest_path": {
"anyOf": [
{
Expand Down Expand Up @@ -1285,7 +1336,14 @@
"type": "string"
},
"severity": {
"enum": ["critical", "high", "medium", "low", "informational"],
"enum": [
"critical",
"high",
"medium",
"low",
"informational",
"unknown"
],
"title": "Severity",
"type": "string"
},
Expand Down
Loading
Loading