Bahasa Indonesia

Jalankan Codex Security di CI

Pindai perubahan pull request dan merge request, pertahankan hasil terstruktur, unggah SARIF, dan tetapkan kebijakan tingkat keparahan.

Jalankan Codex Security CLI di CI untuk meninjau perubahan persis dalam pull request atau merge request, mempertahankan temuan dan cakupan, serta secara opsional menggagalkan pemeriksaan pada tingkat keparahan yang dipilih. Mulailah dengan hasil yang bersifat saran, tinjau kualitas dan waktu proses pemindaian, lalu tambahkan kebijakan tingkat keparahan yang sesuai dengan repositori Anda.

Panduan ini menyertakan contoh untuk GitHub Actions dan GitLab CI/CD. Perintah pemindaian dan ekspor yang sama dapat digunakan di sistem CI lainnya.

Siapkan alur kerja

Simpan API key OpenAI di penyimpanan rahasia penyedia CI Anda sebagai CODEX_SECURITY_API_KEY.

Petakan rahasia ini secara langsung ke variabel lingkungan OPENAI_API_KEY milik langkah pemindaian. Batasi kredensial hanya untuk proses pemindaian dan gunakan --auth api-key untuk memilihnya secara eksplisit.

Runner memerlukan:

  • Node.js 22 atau yang lebih baru.
  • Python 3.10 atau yang lebih baru.
  • Paket @openai/codex-security yang telah dipublikasikan, diinstal di luar checkout repositori.
  • Riwayat head dan base pull request atau merge request agar Git dapat menghitung merge base.

Tambahkan alur kerja GitHub Actions

Untuk repositori privat atau internal, aktifkan GitHub Code Security sebelum Anda mengunggah SARIF.

Buat .github/workflows/codex-security.yml. Sebelum melakukan checkout pull request, instal @openai/codex-security di bawah $RUNNER_TEMP/codex-security agar berkas yang dapat dieksekusi dan tepercaya tersedia di $RUNNER_TEMP/codex-security/node_modules/.bin/codex-security:

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

Alur kerja melakukan checkout head pull request, menghitung merge base-nya, dan memindai perubahan yang telah di-commit di antara revisi tersebut. Riwayat lengkap menjaga target tetap akurat. persist-credentials: false mencegah token repositori masuk ke konfigurasi Git yang telah di-checkout. Menginstal CLI sebelum checkout dan menjalankannya melalui path absolut menjauhkan berkas yang dapat dieksekusi dan dikendalikan repositori dari kredensial pemindaian. --auth api-key secara eksplisit memilih API key yang dibatasi cakupannya. Pemindaian menyimpan riwayatnya dalam direktori status yang dapat ditulisi di luar repositori.

--json menulis satu dokumen JSON lengkap ke stdout, sehingga alur kerja dapat menyimpannya secara langsung. Progres, ringkasan penyelesaian, dan kesalahan tetap berada di stderr. Ini berbeda dari codex exec --json, yang menghasilkan aliran peristiwa JSON Lines.

Langkah ekspor membaca pemindaian yang telah selesai dan disegel, lalu menulis SARIF. Langkah ini tidak mengubah runtime dan kredensial Codex. Artefak pemindaian dapat memuat cuplikan kode sumber yang rentan, bukti, dan detail remediasi. Pilih kontrol akses dan periode retensi singkat yang sesuai untuk repositori Anda.

Tambahkan pipeline GitLab CI/CD

GitLab dapat menyerap laporan SARIF 2.1.0 di GitLab Ultimate 19.2 atau yang lebih baru. Tambahkan variabel CI/CD CODEX_SECURITY_API_KEY yang disamarkan dan disembunyikan sebelum Anda menjalankan pipeline.

Tambahkan tahap security dan job Codex Security ke .gitlab-ci.yml tingkat root. Pertahankan semua tahap dan job yang sudah ada dalam berkas tersebut. Secara default, contoh ini memindai perubahan merge request. Tetapkan CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH ke "true" untuk turut memindai seluruh branch default:

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
      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

Secara default, job hanya berjalan untuk merge request dari branch dalam proyek yang sama, sehingga pipeline fork tidak menerima kredensial pemindaian. Tetapkan CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH ke "true" pada tingkat grup, proyek, atau pipeline untuk turut menjalankan pemindaian penuh standar pada branch default. Pemindaian penuh memerlukan waktu lebih lama dan biaya lebih besar daripada pemindaian diff.

GIT_DEPTH: "0" menyediakan riwayat yang diperlukan untuk menghitung merge base dari CI_MERGE_REQUEST_DIFF_BASE_SHA dan CI_COMMIT_SHA untuk pemindaian merge request.

Job menginstal CLI di bawah /tmp, menjalankannya melalui path absolut, dan hanya mengekspos API key kepada proses pemindaian. artifacts: when: always mempertahankan laporan SARIF ketika pemindaian gagal, sedangkan artifacts:access: maintainer membatasi akses ke hasil pemindaian terperinci.

Perubahan pada .gitlab-ci.yml dapat mengekspos variabel CI/CD, jadi tinjau perubahan pipeline sebelum menjalankan job. Jika Anda melindungi CODEX_SECURITY_API_KEY, GitLab menyediakannya hanya untuk merge request dalam proyek yang sama di antara branch yang dilindungi dan hanya ketika pengguna dapat mengakses branch target.

Pilih kebijakan tingkat keparahan

Kedua contoh hanya membuat laporan karena tidak menyertakan --fail-on-severity. Setelah Anda siap menjadikan temuan memengaruhi pemeriksaan, tambahkan ambang batas ke perintah pemindaian:

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

Ambang batas yang didukung adalah critical, high, medium, dan low. Sebuah ambang batas mencakup temuan pada tingkat keparahan tersebut dan yang lebih tinggi.

Langkah pemindaian menggunakan kode keluar berikut:

Keluar Arti
0 Pemindaian selesai dengan cakupan lengkap dan semua kebijakan yang dikonfigurasi terpenuhi.
1 Pemindaian yang selesai memuat temuan pada atau di atas ambang batas.
2 CLI menemukan kesalahan input atau runtime, atau pemindaian yang selesai memiliki cakupan tidak lengkap.
130 Ctrl-C menghentikan pemindaian.
143 SIGTERM mengakhiri pemindaian.

Pemindaian dengan cakupan partial atau unknown mengembalikan 2, bahkan tanpa kebijakan tingkat keparahan. CLI tetap menulis temuan dan cakupan yang tersedia. Tinjau area yang ditangguhkan dalam coverage.json sebelum menganggap pemeriksaan tersebut konklusif.

Coba lagi dengan direktori hasil yang sudah ada

Gunakan direktori runner baru untuk setiap job CI. Untuk runner persisten atau yang di-host sendiri, pertahankan hasil sebelumnya dengan --archive-existing:

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

Perintah tersebut mengarsipkan hasil sebelumnya dan memulai dengan direktori pemindaian kosong.

Atasi masalah pemindaian CI

  • Ref Git tidak dikenal atau diff tidak sesuai harapan: Ambil riwayat base dan head, hitung merge base, lalu teruskan kedua revisi secara eksplisit.
  • Direktori output dilindungi atau tidak kosong: Pilih direktori privat di luar worktree Git yang menaunginya. Gunakan --archive-existing ketika direktori sudah memuat hasil.
  • Kredensial tidak ada: Pastikan CODEX_SECURITY_API_KEY tersedia untuk alur kerja atau pipeline tepercaya dan dipetakan secara langsung ke variabel lingkungan OPENAI_API_KEY milik proses pemindaian.
  • Kesalahan riwayat pemindaian: Tetapkan CODEX_SECURITY_STATE_DIR ke direktori yang dapat ditulisi di luar repositori.
  • Kesalahan penyiapan Python: Pastikan runner menggunakan Python 3.10 atau yang lebih baru.
  • Cakupan tidak lengkap: Tinjau coverage.json, termasuk permukaan yang ditangguhkan dan pertanyaan terbuka, lalu jalankan ulang dengan target atau lingkungan yang sesuai.
  • Kesalahan ekspor SARIF: Pastikan pemindaian selesai dan seluruh direktori pemindaian tersedia. Ekspor memvalidasi artefak yang disegel sebelum menulis SARIF.
  • Kesalahan unggah SARIF: Untuk GitHub Actions, pastikan organisasi Anda mengaktifkan GitHub Code Security untuk repositori dan alur kerja memberikan actions: read, contents: read, dan security-events: write. Untuk GitLab CI/CD, pastikan proyek menggunakan GitLab Ultimate 19.2 atau yang lebih baru dan job mengunggah berkas SARIF 2.1.0 melalui artifacts:reports:sarif.

Untuk setiap perintah, flag, artefak, dan field output, lihat referensi CLI. Untuk peninjauan CI interaktif berbasis plugin, lihat Tinjau perubahan kode untuk keamanan.