Deutsch

Codex Security in CI ausführen

Änderungen aus Pull Requests und Merge Requests scannen, strukturierte Ergebnisse aufbewahren, SARIF hochladen und eine Schweregradrichtlinie festlegen.

Führen Sie die Codex Security CLI in CI aus, um exakt die Änderungen in einem Pull Request oder Merge Request zu prüfen, Befunde und Abdeckung aufzubewahren und die Prüfung optional ab einem gewählten Schweregrad fehlschlagen zu lassen. Beginnen Sie mit informativen Ergebnissen, prüfen Sie Scanqualität und Laufzeit und ergänzen Sie anschließend eine zu Ihrem Repository passende Schweregradrichtlinie.

Dieser Leitfaden enthält Beispiele für GitHub Actions und GitLab CI/CD. Dieselben Scan- und Exportbefehle funktionieren auch in anderen CI-Systemen.

Workflow vorbereiten

Speichern Sie einen OpenAI API key im Secret-Speicher Ihres CI-Anbieters als CODEX_SECURITY_API_KEY.

Ordnen Sie dieses Secret direkt der Umgebungsvariable OPENAI_API_KEY des Scan-Schritts zu. Beschränken Sie die Anmeldedaten auf den Scan-Prozess und verwenden Sie --auth api-key, um sie ausdrücklich auszuwählen.

Führen Sie den Workflow nur für vertrauenswürdige Repositories und Pull Requests aus. Scans verwenden die lokalen Berechtigungen des Runners und halten nicht für eine Genehmigung an. Scan-Prozesse können die Jobumgebung übernehmen; halten Sie daher nicht benötigte Tokens und Cloud- Anmeldedaten davon fern.

Der Runner benötigt:

  • Node.js 22 (22.13.0 oder höher), 24 oder 26.
  • Python 3.10 oder höher.
  • Das veröffentlichte Paket @openai/codex-security, installiert außerhalb des Repository-Checkouts.
  • Den Verlauf des Heads und der Basis des Pull Requests oder Merge Requests, damit Git die Merge-Basis berechnen kann.

GitHub-Actions-Workflow hinzufügen

Aktivieren Sie für private oder interne Repositories GitHub Code Security, bevor Sie SARIF hochladen.

Erstellen Sie .github/workflows/codex-security.yml. Installieren Sie vor dem Auschecken des Pull Requests @openai/codex-security unter $RUNNER_TEMP/codex-security, damit die vertrauenswürdige ausführbare Datei unter $RUNNER_TEMP/codex-security/node_modules/.bin/codex-security verfügbar ist:

name: Codex Security scan

on:
  pull_request:

jobs:
  codex-security:
    if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]'
    runs-on: ubuntu-latest
    permissions:
      actions: read
      contents: read
      security-events: write
    steps:
      - name: Set up Node.js
        uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7
        with:
          node-version: "26"

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

      - name: Install Codex Security
        run: |
          set -euo pipefail
          npm install \
            --prefix "$RUNNER_TEMP/codex-security" \
            --ignore-scripts \
            --no-audit \
            --no-fund \
            @openai/codex-security

      - name: Verify Codex Security
        env:
          CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
        run: |
          set -euo pipefail
          test -x "$CODEX_SECURITY_BIN"
          "$CODEX_SECURITY_BIN" --version

      - name: Check out the pull request
        uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
        with:
          ref: ${{ github.event.pull_request.head.sha }}
          fetch-depth: 0
          persist-credentials: false

      - name: Scan the pull request
        env:
          OPENAI_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }}
          CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
          CODEX_SECURITY_STATE_DIR: ${{ runner.temp }}/codex-security-state
          BASE_SHA: ${{ github.event.pull_request.base.sha }}
          HEAD_SHA: ${{ github.event.pull_request.head.sha }}
          SCAN_DIR: ${{ runner.temp }}/codex-security-results
        run: |
          set -euo pipefail
          BASE_REVISION="$(git merge-base "$BASE_SHA" "$HEAD_SHA")"
          "$CODEX_SECURITY_BIN" scan . \
            --diff "$BASE_REVISION" \
            --head "$HEAD_SHA" \
            --auth api-key \
            --output-dir "$SCAN_DIR" \
            --json > "$RUNNER_TEMP/codex-security.json"

      - name: Export SARIF
        id: export-sarif
        if: always()
        env:
          CODEX_SECURITY_BIN: ${{ runner.temp }}/codex-security/node_modules/.bin/codex-security
          SCAN_DIR: ${{ runner.temp }}/codex-security-results
          SARIF_FILE: ${{ runner.temp }}/codex-security.sarif
        run: |
          set -euo pipefail
          if test -f "$SCAN_DIR/scan-manifest.json"; then
            "$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
              --export-format sarif \
              --source-root "$GITHUB_WORKSPACE" \
              --output "$SARIF_FILE"
            echo "available=true" >> "$GITHUB_OUTPUT"
          fi

      - name: Upload SARIF
        if: always() && steps.export-sarif.outputs.available == 'true'
        uses: github/codeql-action/upload-sarif@e4fba868fa4b1b91e1fdab776edc8cfbe6e9fb81 # v4
        with:
          sarif_file: ${{ runner.temp }}/codex-security.sarif
          ref: refs/pull/${{ github.event.pull_request.number }}/head
          sha: ${{ github.event.pull_request.head.sha }}
          category: codex-security

      - name: Preserve scan results
        if: always()
        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
        with:
          name: codex-security-results
          path: |
            ${{ runner.temp }}/codex-security-results
            ${{ runner.temp }}/codex-security.json
          if-no-files-found: warn
          retention-days: 7

Der Workflow checkt den Head des Pull Requests aus, berechnet dessen Merge-Basis und scannt die zwischen diesen Revisionen committeten Änderungen. Der vollständige Verlauf hält das Ziel exakt. persist-credentials: false hält das Repository-Token aus der ausgecheckten Git-Konfiguration heraus. Wenn Sie die CLI vor dem Checkout installieren und über ihren absoluten Pfad ausführen, bleiben vom Repository kontrollierte ausführbare Dateien von den Scan-Anmeldedaten getrennt. --auth api-key wählt ausdrücklich den eingeschränkten API key aus. Der Scan speichert seinen Verlauf in einem beschreibbaren Zustandsverzeichnis außerhalb des Repositories.

--json schreibt ein vollständiges JSON-Dokument nach stdout, sodass der Workflow es direkt speichern kann. Fortschritt, Abschlusszusammenfassungen und Fehler verbleiben auf stderr. Dies unterscheidet sich von codex exec --json, das einen JSON-Lines-Ereignisstream ausgibt.

Der Exportschritt liest einen abgeschlossenen, versiegelten Scan und schreibt SARIF. Codex- Laufzeit und Anmeldedaten bleiben dabei unverändert. Scan-Artefakte können anfällige Quelltextausschnitte, Nachweise und Behebungsdetails enthalten. Wählen Sie Zugriffskontrollen und ein kurzes Aufbewahrungsfenster, die für Ihr Repository angemessen sind.

GitLab-CI/CD-Pipeline hinzufügen

Verwenden Sie für einen Produktionsworkflow mit Scans des geschützten Standard-Branches, optional aktivierten geplanten Tiefenscans, einer separaten SARIF-Richtlinienprüfung und optionalen verifizierten Entwurfs-Merge-Requests den Leitfaden Codex Security in GitLab CI/CD ausführen.

GitLab kann SARIF-2.1.0-Berichte ab GitLab Ultimate 19.2 verarbeiten. Fügen Sie eine maskierte und ausgeblendete CI/CD-Variable CODEX_SECURITY_API_KEY hinzu, bevor Sie die Pipeline ausführen.

Das folgende Minimalbeispiel fügt der Stammdatei einen reinen Scan-Job namens security hinzu: .gitlab-ci.yml. Behalten Sie alle bereits in der Datei vorhandenen Stages und Jobs bei. Standardmäßig werden Änderungen aus Merge Requests gescannt. Setzen Sie CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH auf "true", um zusätzlich den vollständigen Standard-Branch zu scannen:

variables:
  CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH: "false"

stages:
  - test
  - security

codex-security:
  stage: security
  image: node:26-bookworm-slim
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID'
      variables:
        CODEX_SECURITY_SCAN_SCOPE: "diff"
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH == "true"'
      variables:
        CODEX_SECURITY_SCAN_SCOPE: "full"
  variables:
    GIT_DEPTH: "0"
    CODEX_SECURITY_CLI_DIR: "/tmp/codex-security-cli"
  before_script:
    - |
      set -eu
      apt-get update -qq
      apt-get install -y -qq --no-install-recommends \
        ca-certificates \
        git \
        python3 \
        ripgrep
      npm install \
        --prefix "$CODEX_SECURITY_CLI_DIR" \
        --ignore-scripts \
        --no-audit \
        --no-fund \
        @openai/codex-security@0.1.20
      export CODEX_SECURITY_BIN="$CODEX_SECURITY_CLI_DIR/node_modules/.bin/codex-security"
      test -x "$CODEX_SECURITY_BIN"
      "$CODEX_SECURITY_BIN" --version
  script:
    - |
      set -eu
      if test -z "${CODEX_SECURITY_API_KEY:-}"; then
        echo "Set the CODEX_SECURITY_API_KEY CI/CD variable." >&2
        exit 2
      fi

      codex_security_api_key="$CODEX_SECURITY_API_KEY"
      unset CODEX_SECURITY_API_KEY

      case "${CODEX_SECURITY_SCAN_SCOPE:-}" in
        diff)
          BASE_SHA="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
          HEAD_SHA="$CI_COMMIT_SHA"
          BASE_REVISION="$(git merge-base "$BASE_SHA" "$HEAD_SHA")"
          set -- --diff "$BASE_REVISION" --head "$HEAD_SHA"
          echo "Scanning committed changes from $BASE_REVISION to $HEAD_SHA."
          ;;
        full)
          set -- --mode standard
          echo "Scanning the complete default branch at $CI_COMMIT_SHA."
          ;;
        *)
          echo "Unsupported Codex Security scan scope: ${CODEX_SECURITY_SCAN_SCOPE:-unset}" >&2
          exit 2
          ;;
      esac

      export CODEX_SECURITY_STATE_DIR="/tmp/codex-security-state-$CI_JOB_ID"
      SCAN_DIR="/tmp/codex-security-results-$CI_JOB_ID"
      JSON_FILE="/tmp/codex-security-$CI_JOB_ID.json"
      SARIF_FILE="/tmp/codex-security-$CI_JOB_ID.sarif"

      install -d -m 700 "$CODEX_SECURITY_STATE_DIR" "$SCAN_DIR"

      set +e
      OPENAI_API_KEY="$codex_security_api_key" \
        "$CODEX_SECURITY_BIN" scan . \
          "$@" \
          --auth api-key \
          --output-dir "$SCAN_DIR" \
          --json > "$JSON_FILE"
      scan_exit="$?"
      set -e
      unset codex_security_api_key

      install -d -m 700 codex-security-artifacts/results
      cp -R "$SCAN_DIR"/. codex-security-artifacts/results/
      if test -s "$JSON_FILE"; then
        cp "$JSON_FILE" codex-security-artifacts/codex-security.json
      fi
      printf '%s\n' "$scan_exit" > codex-security-artifacts/scan-exit-code.txt

      export_exit=0
      if test -f "$SCAN_DIR/scan-manifest.json"; then
        set +e
        "$CODEX_SECURITY_BIN" export "$SCAN_DIR" \
          --export-format sarif \
          --source-root "$CI_PROJECT_DIR" \
          --output "$SARIF_FILE"
        export_exit="$?"
        set -e
        if test -s "$SARIF_FILE"; then
          cp "$SARIF_FILE" codex-security-artifacts/codex-security.sarif
        fi
      fi

      if test "$scan_exit" -ne 0; then
        exit "$scan_exit"
      fi
      exit "$export_exit"
  artifacts:
    when: always
    access: maintainer
    expire_in: 7 days
    paths:
      - codex-security-artifacts/
    reports:
      sarif: codex-security-artifacts/codex-security.sarif

Standardmäßig wird der Job nur für Merge Requests von Branches desselben Projekts ausgeführt, sodass Fork-Pipelines die Scan-Anmeldedaten nicht erhalten. Setzen Sie CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH auf Gruppen-, Projekt- oder Pipeline-Ebene auf "true", um zusätzlich einen regulären vollständigen Scan auf dem Standard-Branch auszuführen. Vollständige Scans dauern länger und kosten mehr als Diff-Scans.

GIT_DEPTH: "0" stellt den Verlauf bereit, der zum Berechnen der Merge-Basis aus CI_MERGE_REQUEST_DIFF_BASE_SHA und CI_COMMIT_SHA für Merge-Request-Scans erforderlich ist.

Der Job installiert die CLI unter /tmp, führt sie über den absoluten Pfad aus und stellt den API key nur dem Scan-Prozess bereit. artifacts: when: always bewahrt den SARIF- Bericht auf, wenn der Scan fehlschlägt, während artifacts:access: maintainer den Zugriff auf detaillierte Scan-Ergebnisse einschränkt.

Änderungen an .gitlab-ci.yml können CI/CD-Variablen offenlegen. Prüfen Sie daher Pipeline- Änderungen, bevor Sie den Job ausführen. Wenn Sie CODEX_SECURITY_API_KEY schützen, stellt GitLab es nur für Merge Requests desselben Projekts zwischen geschützten Branches bereit und nur dann, wenn der Benutzer auf den Ziel-Branch zugreifen kann.

Der spezielle GitLab-Leitfaden erweitert diesen Minimaljob zu dem am Anfang dieses Abschnitts verlinkten Produktionsworkflow.

Schweregradrichtlinie auswählen

Beide Beispiele dienen ausschließlich der Berichterstellung, da sie --fail-on-severity auslassen. Sobald Befunde die Prüfung beeinflussen sollen, ergänzen Sie den Scan- Befehl um einen Schwellenwert:

"$CODEX_SECURITY_BIN" scan . \
  --diff origin/main \
  --output-dir /path/outside/repository/results \
  --fail-on-severity high

Die unterstützten Schwellenwerte sind critical, high, medium und low. Ein Schwellenwert umfasst Befunde des aktuellen Scans mit diesem oder einem höheren Schweregrad. Frühere offene Befunde in der Repository-Zusammenfassung wirken sich nicht auf die Richtlinie aus.

Der Scan-Schritt verwendet folgende Exitcodes:

Exit Bedeutung
0 Der Scan wurde mit vollständiger Abdeckung abgeschlossen und jede konfigurierte Richtlinie eingehalten.
1 Der abgeschlossene Scan enthält einen Befund ab dem festgelegten Schwellenwert.
2 Die CLI hat einen Eingabe- oder Laufzeitfehler festgestellt oder der abgeschlossene Scan weist eine unvollständige Abdeckung auf.
130 Der Scan wurde durch Ctrl-C unterbrochen.
143 Der Scan wurde durch SIGTERM beendet.

Ein Scan mit Abdeckung vom Typ partial oder unknown gibt 2 zurück, auch ohne eine Schweregrad- richtlinie. Die CLI schreibt weiterhin die verfügbaren Befunde und Abdeckungsdaten. Prüfen Sie die zurückgestellten Bereiche in coverage.json, bevor Sie die Prüfung als abschließend betrachten.

Mit einem vorhandenen Ergebnisverzeichnis erneut versuchen

Verwenden Sie für jeden CI-Job ein neues Runner-Verzeichnis. Bewahren Sie bei einem persistenten oder selbst gehosteten Runner ein früheres Ergebnis mit --archive-existing auf:

"$CODEX_SECURITY_BIN" scan . \
  --diff origin/main \
  --output-dir /path/outside/repository/results \
  --archive-existing

Der Befehl archiviert die früheren Ergebnisse und beginnt mit einem leeren Scan-Verzeichnis.

Fehler bei einem CI-Scan beheben

  • Unbekannte Git-Referenz oder unerwarteter Diff: Rufen Sie den Verlauf von Basis und Head ab, berechnen Sie die Merge-Basis und übergeben Sie beide Revisionen ausdrücklich.
  • Geschütztes oder nicht leeres Ausgabeverzeichnis: Wählen Sie ein privates Verzeichnis außerhalb des umgebenden Git-Worktrees. Verwenden Sie --archive-existing, wenn das Verzeichnis bereits Ergebnisse enthält.
  • Fehlende Anmeldedaten: Vergewissern Sie sich, dass CODEX_SECURITY_API_KEY für den vertrauenswürdigen Workflow oder die vertrauenswürdige Pipeline verfügbar und direkt der Umgebungsvariable OPENAI_API_KEY des Scan-Prozesses zugeordnet ist.
  • Fehler im Scan-Verlauf: Setzen Sie CODEX_SECURITY_STATE_DIR auf ein beschreibbares Verzeichnis außerhalb des Repositories.
  • Fehler bei der Python-Einrichtung: Vergewissern Sie sich, dass der Runner Python 3.10 oder höher verwendet.
  • Unvollständige Abdeckung: Prüfen Sie coverage.json einschließlich zurückgestellter Bereiche und offener Fragen und führen Sie den Scan dann mit einem geeigneten Ziel oder einer geeigneten Umgebung erneut aus.
  • Fehler beim SARIF-Export: Vergewissern Sie sich, dass der Scan abgeschlossen wurde und das vollständige Scan- Verzeichnis verfügbar ist. Der Export validiert die versiegelten Artefakte, bevor er SARIF schreibt.
  • Fehler beim SARIF-Upload: Vergewissern Sie sich bei GitHub Actions, dass Ihre Organisation GitHub Code Security für das Repository aktiviert hat und der Workflow actions: read, contents: read und security-events: write gewährt. Vergewissern Sie sich bei GitLab CI/CD, dass das Projekt GitLab Ultimate 19.2 oder höher verwendet und der Job über artifacts:reports:sarif eine SARIF-2.1.0-Datei hochlädt.

Informationen zu allen Befehlen, Flags, Artefakten und Ausgabefeldern finden Sie in der CLI- Referenz. Informationen zu einer interaktiven pluginbasierten CI- Prüfung finden Sie unter Codeänderungen auf Sicherheitsprobleme prüfen.