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
4 changes: 4 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

Examples and templates for using Codex Security:

- [GitHub Actions with Amazon Bedrock](github-actions/README.md): a copyable
workflow for PR-diff and full-repository scans with AWS OIDC authentication,
SARIF uploads, and downloadable reports.

- [Findings CSV template](findings.csv): a header-only template for
`codex-security publish scan --to cloud --csv PATH`. Copy it, add one finding
per row, and validate the file before publishing:
Expand Down
94 changes: 94 additions & 0 deletions examples/github-actions/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# GitHub Actions with Amazon Bedrock

The [workflow](codex-security.yml) scans PR changes or, on manual and scheduled
runs, the full repository. It uses short-lived AWS credentials and uploads
completed findings to GitHub Code Scanning as SARIF. It does not install a GitHub
App or post PR comments.

## Setup

1. Configure [GitHub OIDC in AWS](https://github.com/aws-actions/configure-aws-credentials#oidc-recommended)
and create a role that can invoke your approved Bedrock model or inference
profile, including streaming invocation when required. Restrict its trust
policy to your repository and the `sts.amazonaws.com` audience. Without a
GitHub environment, the subjects are:
- PRs: `repo:OWNER/REPOSITORY:pull_request`.
- Manual and scheduled runs on `main`: `repo:OWNER/REPOSITORY:ref:refs/heads/main`.
Replace `main` with your default branch; allow other branches only if you
intend to run manual scans there.
2. Add these repository variables under **Settings → Secrets and variables →
Actions → Variables**:

| Variable | Value |
| ------------------ | ---------------------------------------------- |
| `AWS_ROLE_ARN` | ARN of the role created above |
| `AWS_REGION` | Region where the role can invoke the model |
| `BEDROCK_MODEL_ID` | Approved model or inference-profile identifier |

Bedrock model access must already be enabled. No long-lived AWS access key or
OpenAI API key is needed.

3. Confirm [GitHub Code Scanning and SARIF upload](https://docs.github.com/en/code-security/how-tos/find-and-fix-code-vulnerabilities/integrate-with-existing-tools/upload-sarif-file)
are available. Private repositories need the appropriate GitHub Code Security
entitlement. For downloadable reports only, remove the SARIF upload step and
the `security-events: write` and `actions: read` permissions.
4. Copy `codex-security.yml` into the target repository's `.github/workflows/`
directory, review it, and merge it into the default branch. This example does
not enable scanning until copied.
5. In **Actions → Codex Security (Amazon Bedrock) → Run workflow**, run a baseline
on the default branch, then open a same-repository test PR. Check coverage,
alert locations, deduplication, and fixed-alert behavior in the destination
repository before relying on the integration.

## Configuration

PR scans compare GitHub's default PR merge checkout against the event's immutable
base SHA. Draft, fork, and Dependabot-triggered PRs are skipped; newer runs cancel
older ones. Uncomment the schedule for weekly full scans after setup works.
Scans consume Bedrock inference usage.

The workflow uses standard mode with high reasoning effort. See
[scan options](../../sdk/typescript/README.md#scan-options-and-output) and
[Bedrock configuration](../../sdk/typescript/README.md#authentication) for details.

Actions are pinned to commit SHAs, and CLI and runtime versions are pinned in the
workflow. Node.js uses the active LTS line.
Review and test updates before changing pins. The job and AWS session each last
at most one hour; for longer scans, adjust both and the IAM role's session limit.

## Results

Findings are report-only by default. Set `FAIL_ON_SEVERITY: "high"` to fail on
high or critical findings, then make the check required in your repository rules
if it should block merging.

| CLI exit code | Workflow result |
| ------------- | ----------------------------------------------------------------------- |
| `0` | Completed scan; export and upload SARIF |
| `1` | Severity-policy violation; upload SARIF and keep the job failed |
| Other nonzero | Failed or incomplete scan; fail the job without uploading partial SARIF |

For exit `2`, inspect the logs, result JSON, and coverage report: missing coverage
is not a clean security result. Full and diff scans use separate SARIF categories
so a diff does not replace the full-repository baseline.

Reports are saved as seven-day artifacts even after a scan or SARIF upload fails
(cancelled jobs may not save them). Only result JSON, report, coverage, findings,
and SARIF files are uploaded—not authentication state or raw agent transcripts.
Reports can contain sensitive source snippets and vulnerability details; review
repository access and retention accordingly.

## Trust boundary

Use this example only for trusted contributors on GitHub-hosted Linux runners.
A same-repository PR can change workflow code and receives model-invocation
credentials. Skipping forks does not protect against someone who can push a
branch. For a wider contributor set, require reviewers through a protected
GitHub environment and [update the OIDC subject](https://docs.github.com/en/actions/how-tos/secure-your-work/security-harden-deployments/oidc-in-aws).

Do not use `pull_request_target` to scan untrusted PR code with credentials, or
add PR-controlled dependency installs, builds, or commands to this job. The CLI
is installed outside the checkout before checkout; AWS credentials are scoped
to the scan step, and no `GH_TOKEN` or `GITHUB_TOKEN` is passed to the scanner.
Keep any additional scanner configuration maintainer-controlled. Only scan code
you are authorized to submit to the configured inference provider.
142 changes: 142 additions & 0 deletions examples/github-actions/codex-security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: Codex Security (Amazon Bedrock)

on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
workflow_dispatch:
# Uncomment after testing to scan the default branch weekly.
# schedule:
# - cron: "17 3 * * 1"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
scan:
# This job receives AWS credentials. Do not use pull_request_target or
# enable it for untrusted contributors; see the README's trust boundary.
if: >-
github.event_name != 'pull_request' ||
(github.event.pull_request.head.repo.full_name == github.repository &&
github.actor != 'dependabot[bot]' &&
github.event.pull_request.draft == false)
runs-on: ubuntu-24.04
timeout-minutes: 60
permissions:
contents: read
id-token: write
security-events: write
actions: read
env:
CODEX_SECURITY_VERSION: "0.1.27"
BEDROCK_MODEL_ID: ${{ vars.BEDROCK_MODEL_ID }}
# Report-only by default. Set to "high" to fail on high/critical findings.
FAIL_ON_SEVERITY: ""

steps:
- name: Set up Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: "24.21.0"

- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: "3.14.7"

# Install outside the checkout, before any repository content is present.
- name: Install Codex Security
working-directory: ${{ runner.temp }}
shell: bash
run: |
npm install --prefix "$RUNNER_TEMP/codex-security-cli" \
--ignore-scripts --no-audit --no-fund \
--registry=https://registry.npmjs.org/ \
"@openai/codex-security@$CODEX_SECURITY_VERSION"
echo "$RUNNER_TEMP/codex-security-cli/node_modules/.bin" >> "$GITHUB_PATH"

- name: Check out the commit to scan
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
# On pull_request, the default checkout is GitHub's PR merge commit.

- name: Assume the Bedrock role with OIDC
id: aws
uses: aws-actions/configure-aws-credentials@cbe3b392738ccf3f987d68400dafcf4b0624a56c # v6.2.4
with:
aws-region: ${{ vars.AWS_REGION }}
role-to-assume: ${{ vars.AWS_ROLE_ARN }}
role-session-name: codex-security-${{ github.run_id }}
role-duration-seconds: 3600
output-env-credentials: false
output-credentials: true

- name: Scan
id: scan
shell: bash
env:
AWS_REGION: ${{ vars.AWS_REGION }}
AWS_ACCESS_KEY_ID: ${{ steps.aws.outputs.aws-access-key-id }}
AWS_SECRET_ACCESS_KEY: ${{ steps.aws.outputs.aws-secret-access-key }}
AWS_SESSION_TOKEN: ${{ steps.aws.outputs.aws-session-token }}
EVENT_NAME: ${{ github.event_name }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
run: |
args=(
scan "$GITHUB_WORKSPACE"
--provider amazon-bedrock
--model "$BEDROCK_MODEL_ID"
--mode standard
--effort high
--output-dir "$RUNNER_TEMP/codex-security-scan"
--json
)
if [[ "$EVENT_NAME" == "pull_request" ]]; then
args+=(--diff "$BASE_SHA")
fi
if [[ -n "$FAIL_ON_SEVERITY" ]]; then
args+=(--fail-on-severity "$FAIL_ON_SEVERITY")
fi
scan_status=0
codex-security "${args[@]}" > "$RUNNER_TEMP/codex-security-result.json" || scan_status=$?
echo "exit-code=$scan_status" >> "$GITHUB_OUTPUT"
exit "$scan_status"

# A policy violation (1) is still a completed scan. An incomplete/error
# result (2) must not replace code-scanning alerts with a partial report.
- name: Export completed findings as SARIF
id: sarif
if: ${{ !cancelled() && (steps.scan.outputs.exit-code == '0' || steps.scan.outputs.exit-code == '1') }}
shell: bash
run: |
codex-security export "$RUNNER_TEMP/codex-security-scan" \
--export-format sarif \
--source-root "$GITHUB_WORKSPACE" \
--output "$RUNNER_TEMP/codex-security.sarif"

- name: Upload SARIF to GitHub Code Scanning
if: ${{ !cancelled() && steps.sarif.outcome == 'success' }}
uses: github/codeql-action/upload-sarif@b96794f015dfd88f77b49b1c93e0fa7110f94c63 # v4.38.0
with:
sarif_file: ${{ runner.temp }}/codex-security.sarif
category: codex-security/${{ github.event_name == 'pull_request' && 'diff' || 'full' }}

- name: Save reports
if: ${{ !cancelled() && steps.scan.outputs.exit-code != '' }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: codex-security-${{ github.run_id }}-${{ github.run_attempt }}
retention-days: 7
if-no-files-found: warn
path: |
${{ runner.temp }}/codex-security-result.json
${{ runner.temp }}/codex-security.sarif
${{ runner.temp }}/codex-security-scan/report.md
${{ runner.temp }}/codex-security-scan/coverage.json
${{ runner.temp }}/codex-security-scan/findings.json
Loading
Loading