Português

Executar o Codex Security em CI

Analise alterações de pedidos de pull e de merge, preserve resultados estruturados, carregue SARIF e defina uma política de gravidade.

Execute a CLI do Codex Security em CI para rever as alterações exatas num pedido de pull ou pedido de merge, conservar as deteções e a cobertura e, opcionalmente, fazer falhar a verificação a um nível de gravidade escolhido. Comece com resultados informativos, reveja a qualidade e o tempo de execução da análise e, em seguida, adicione uma política de gravidade adequada ao seu repositório.

Este guia inclui exemplos para GitHub Actions e GitLab CI/CD. Os mesmos comandos de análise e exportação funcionam noutros sistemas de CI.

Preparar o fluxo de trabalho

Armazene uma API key da OpenAI no armazenamento de segredos do seu fornecedor de CI como CODEX_SECURITY_API_KEY.

Associe este segredo diretamente à variável de ambiente OPENAI_API_KEY do passo de análise. Limite a credencial ao processo de análise e utilize --auth api-key para a selecionar explicitamente.

Execute o fluxo de trabalho apenas para repositórios e pedidos de pull nos quais confia. As análises utilizam as permissões locais do executor e não aguardam aprovação. Os processos de análise podem herdar o ambiente da tarefa, pelo que deve excluir do mesmo tokens e credenciais de nuvem não relacionados.

O executor requer:

  • Node.js 22 (22.13.0 ou posterior), 24 ou 26.
  • Python 3.10 ou posterior.
  • O pacote publicado @openai/codex-security, instalado fora da cópia de trabalho do repositório.
  • O histórico da origem e da base do pedido de pull ou de merge para que o Git possa calcular a base de merge.

Adicionar o fluxo de trabalho do GitHub Actions

Para repositórios privados ou internos, ative o GitHub Code Security antes de carregar SARIF.

Crie .github/workflows/codex-security.yml. Antes de obter o pedido de pull, instale @openai/codex-security em $RUNNER_TEMP/codex-security para que o executável fidedigno fique disponível em $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

O fluxo de trabalho obtém a origem do pedido de pull, calcula a respetiva base de merge e analisa as alterações consolidadas entre essas revisões. O histórico completo mantém o alvo exato. persist-credentials: false mantém o token do repositório fora da configuração do Git da cópia de trabalho. Instalar a CLI antes da obtenção do código e executá-la através do caminho absoluto mantém os executáveis controlados pelo repositório afastados da credencial de análise. --auth api-key seleciona explicitamente a API key limitada. A análise guarda o respetivo histórico num diretório de estado gravável fora do repositório.

--json escreve um documento JSON completo em stdout, para que o fluxo de trabalho o possa guardar diretamente. O progresso, os resumos de conclusão e os erros permanecem em stderr. Isto difere de codex exec --json, que emite um fluxo de eventos JSON Lines.

O passo de exportação lê uma análise concluída e selada e escreve SARIF. Não altera o runtime nem as credenciais do Codex. Os artefactos de análise podem conter excertos de código-fonte vulnerável, provas e detalhes de remediação. Escolha controlos de acesso e um período de retenção curto adequados ao seu repositório.

Adicionar o pipeline do GitLab CI/CD

Para um fluxo de trabalho de produção com análises protegidas do ramo predefinido, análises aprofundadas agendadas mediante adesão, imposição de políticas SARIF separada e pedidos de integração de rascunho verificados opcionais, consulte Executar o Codex Security no GitLab CI/CD.

O GitLab pode ingerir relatórios SARIF 2.1.0 no GitLab Ultimate 19.2 ou posterior. Adicione uma variável de CI/CD CODEX_SECURITY_API_KEY mascarada e oculta antes de executar o pipeline.

O exemplo mínimo seguinte adiciona uma tarefa security apenas de análise ao ficheiro .gitlab-ci.yml na raiz. Mantenha no ficheiro todas as fases e tarefas existentes. Por predefinição, analisa as alterações dos pedidos de integração. Defina CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH como "true" para analisar também todo o ramo predefinido:

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

Por predefinição, a tarefa só é executada para pedidos de merge provenientes de ramos do mesmo projeto, pelo que os pipelines de forks não recebem a credencial de análise. Defina CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH como "true" ao nível do grupo, projeto ou pipeline para também executar uma análise completa normal no ramo predefinido. As análises completas demoram mais tempo e têm um custo superior ao das análises de diferenças.

GIT_DEPTH: "0" fornece o histórico necessário para calcular a base de merge a partir de CI_MERGE_REQUEST_DIFF_BASE_SHA e CI_COMMIT_SHA nas análises de pedidos de merge.

A tarefa instala a CLI em /tmp, executa-a através do caminho absoluto e expõe a API key apenas ao processo de análise. artifacts: when: always preserva o relatório SARIF quando a análise falha, enquanto artifacts:access: maintainer limita o acesso a resultados de análise detalhados.

As alterações a .gitlab-ci.yml podem expor variáveis de CI/CD, pelo que deve rever as alterações do pipeline antes de executar a tarefa. Se proteger CODEX_SECURITY_API_KEY, o GitLab disponibiliza-a apenas para pedidos de merge do mesmo projeto entre ramos protegidos e apenas quando o utilizador pode aceder ao ramo de destino.

O guia dedicado ao GitLab expande esta tarefa mínima para o fluxo de trabalho de produção indicado no início desta secção.

Escolher uma política de gravidade

Ambos os exemplos apenas produzem relatórios porque omitem --fail-on-severity. Quando estiver preparado para permitir que as deteções afetem a verificação, adicione um limiar ao comando de análise:

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

Os limiares suportados são critical, high, medium e low. Um limiar inclui deteções da análise atual com essa gravidade ou superior. As deteções abertas anteriores apresentadas no resumo do repositório não afetam a política.

O passo de análise utiliza estes códigos de saída:

Saída Significado
0 A análise foi concluída com cobertura completa e qualquer política configurada foi cumprida.
1 A análise concluída contém uma deteção com gravidade igual ou superior ao limiar.
2 A CLI encontrou um erro de entrada ou de runtime, ou a análise concluída tem cobertura incompleta.
130 Ctrl-C interrompeu a análise.
143 SIGTERM terminou a análise.

Uma análise com cobertura partial ou unknown devolve 2, mesmo sem uma política de gravidade. A CLI continua a escrever as deteções e a cobertura disponíveis. Reveja as áreas adiadas em coverage.json antes de considerar a verificação conclusiva.

Repetir com um diretório de resultados existente

Utilize um diretório novo do executor para cada tarefa de CI. Para um executor persistente ou autoalojado, preserve um resultado anterior com --archive-existing:

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

O comando arquiva os resultados anteriores e começa com um diretório de análise vazio.

Resolver problemas de uma análise de CI

  • Referência do Git desconhecida ou diferenças inesperadas: Obtenha o histórico da base e da origem, calcule a base de merge e transmita explicitamente ambas as revisões.
  • Diretório de saída protegido ou não vazio: Escolha um diretório privado fora da árvore de trabalho do Git envolvente. Utilize --archive-existing quando o diretório já contiver resultados.
  • Credenciais em falta: Confirme que CODEX_SECURITY_API_KEY está disponível para o fluxo de trabalho ou pipeline fidedigno e associado diretamente à variável de ambiente OPENAI_API_KEY do processo de análise.
  • Erro no histórico da análise: Defina CODEX_SECURITY_STATE_DIR como um diretório gravável fora do repositório.
  • Erro de configuração do Python: Confirme que o executor utiliza Python 3.10 ou posterior.
  • Cobertura incompleta: Reveja coverage.json, incluindo as superfícies adiadas e as questões em aberto, e volte a executar com um alvo ou ambiente adequado.
  • Erro de exportação SARIF: Confirme que a análise foi concluída e que o diretório completo da análise está disponível. A exportação valida os artefactos selados antes de escrever SARIF.
  • Erro de carregamento SARIF: Para GitHub Actions, confirme que a sua organização ativou o GitHub Code Security para o repositório e que o fluxo de trabalho concede actions: read, contents: read e security-events: write. Para GitLab CI/CD, confirme que o projeto utiliza GitLab Ultimate 19.2 ou posterior e que a tarefa carrega um ficheiro SARIF 2.1.0 através de artifacts:reports:sarif.

Para todos os comandos, opções, artefactos e campos de saída, consulte a referência da CLI. Para uma revisão de CI interativa baseada em plugins, consulte Rever alterações ao código quanto à segurança.