Русский

Запуск Codex Security в GitLab CI/CD

Запускайте Codex Security в GitLab CI/CD, чтобы сканировать зафиксированные изменения и защищённые ветви, публиковать результаты в GitLab Security и при необходимости предлагать проверенные исправления в черновиках запросов на слияние.

Рабочий процесс хранит учётные данные для сканирования отдельно от доступа на запись в репозиторий. Все сгенерированные изменения перед слиянием обязательно проверяются человеком.

Начните с отчётности только по результатам сканирования. Включайте исправление только после проверки раннера, результатов и границ доступа к учётным данным вашего проекта.

Подготовка

Вам потребуются:

  • Проект GitLab с доверенным раннером, поддерживающим пространство имён пользователя песочницы Codex.
  • Роль Maintainer или Owner в проекте GitLab, чтобы настраивать переменные CI/CD проекта и защищённые ресурсы.
  • API key OpenAI с доступом к Codex Security. Организации, использующие ключи Platform API, могут запросить Trusted Access для Cyber. Пользователи, применяющие аутентификацию ChatGPT, могут воспользоваться персональной процедурой получения Trusted Access. Некоторым аккаунтам или репозиториям такой доступ необходим для сканирования всего репозитория.
  • GitLab Ultimate 19.2 или более поздней версии для приёма отчётов SARIF 2.1.0.
  • Полная история Git, чтобы задания запросов на слияние могли вычислить базу слияния.

Образ конвейера устанавливает Node.js 26, Python 3, Git, rg и закреплённую версию Codex Security CLI. Для автоматического исправления также необходимы существующий регрессионный тест и раннер, способный выполнять управляемые репозиторием команды без защищённых учётных данных.

Начните с конвейера, выполняющего только сканирование

Создайте маскируемую, скрытую и защищённую переменную GitLab CI/CD с именем CODEX_SECURITY_API_KEY. Используйте API key OpenAI Platform с доступом к Codex Security и задайте для его области окружения значение codex-security/openai. См. переменные CI/CD с областью окружения.

Сначала добавьте этот минимальный конвейер в тестовый проект. Он сканирует зафиксированные изменения в подходящих защищённых запросах на слияние, публикует SARIF из успешно выполненного задания отчётности и восстанавливает результат сканера в отдельной проверке:

stages:
  - security_scan
  - security_gate

.codex-security-merge-request:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID && $CI_MERGE_REQUEST_SOURCE_BRANCH_PROTECTED == "true" && $CI_MERGE_REQUEST_TARGET_BRANCH_PROTECTED == "true"'

codex-security:
  extends: .codex-security-merge-request
  stage: security_scan
  image: node:26-bookworm-slim
  environment:
    name: codex-security/openai
    action: access
  variables:
    GIT_DEPTH: "0"
  before_script:
    - npm install --prefix /tmp/codex-security-cli --ignore-scripts --no-audit --no-fund @openai/codex-security@0.1.20
  script:
    - |
      set -eu
      test -n "${CODEX_SECURITY_API_KEY:-}"

      CODEX_SECURITY_BIN="/tmp/codex-security-cli/node_modules/.bin/codex-security"
      RESULTS_DIR="/tmp/codex-security-results-$CI_JOB_ID"
      ARTIFACT_DIR="codex-security-artifacts"
      BASE_REVISION="$(git merge-base \
        "$CI_MERGE_REQUEST_DIFF_BASE_SHA" "$CI_COMMIT_SHA")"
      install -d -m 700 "$RESULTS_DIR" "$ARTIFACT_DIR/results"

      codex_security_api_key="$CODEX_SECURITY_API_KEY"
      unset CODEX_SECURITY_API_KEY
      set +e
      OPENAI_API_KEY="$codex_security_api_key" \
        "$CODEX_SECURITY_BIN" scan . \
          --diff "$BASE_REVISION" \
          --head "$CI_COMMIT_SHA" \
          --auth api-key \
          --output-dir "$RESULTS_DIR" \
          --json
      scan_exit="$?"
      set -e
      unset codex_security_api_key

      case "$scan_exit" in
        0|1|2) ;;
        *) exit "$scan_exit" ;;
      esac

      "$CODEX_SECURITY_BIN" export "$RESULTS_DIR" \
        --export-format sarif \
        --source-root "$CI_PROJECT_DIR" \
        --output "$ARTIFACT_DIR/results.sarif"
      test -s "$ARTIFACT_DIR/results.sarif"
      cp -R "$RESULTS_DIR"/. "$ARTIFACT_DIR/results/"
      printf '%s\n' "$scan_exit" > "$ARTIFACT_DIR/scan-exit-code.txt"
      exit 0
  artifacts:
    when: always
    access: maintainer
    expire_in: 7 days
    paths:
      - codex-security-artifacts/
    reports:
      sarif: codex-security-artifacts/results.sarif

codex-security-gate:
  extends: .codex-security-merge-request
  stage: security_gate
  image: alpine:3.20
  needs:
    - job: codex-security
      artifacts: true
  script:
    - exit "$(cat codex-security-artifacts/scan-exit-code.txt)"

Проверяйте каждое изменение в .gitlab-ci.yml перед запуском задания с секретами. В минимальном примере намеренно отсутствуют полное сканирование и исправление.

Перейдите на конвейер промышленного уровня

  1. Скачайте полный конвейер GitLab и сохраните его как .gitlab-ci.yml в корне репозитория. Если в репозитории уже есть конвейер, объедините этапы, скрытые шаблоны и задания примера с существующим файлом.
  2. Сохраните существующие этапы сборки, тестирования и развёртывания. Если проект использует workflow: rules, убедитесь, что он разрешает события конвейера, которые требуется сканировать.

Пример добавляет этапы security_scan, security_remediation, security_publish и security_gate. Для отчётности только по результатам сканирования требуется лишь CODEX_SECURITY_API_KEY.

По умолчанию задание сканирования запускается только для запросов на слияние между защищёнными ветвями одного проекта. Задайте CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH=true, чтобы сканировать отправки в защищённую ветвь по умолчанию и конвейеры, запускаемые вручную. Задайте CODEX_SECURITY_SCHEDULED_DEEP_SCAN=true и настройте явные ограничения времени и стоимости, чтобы включить плановое глубокое сканирование защищённой ветви по умолчанию.

Конвейер запроса на слияние может обращаться к защищённым переменным и раннерам, только если:

Конвейеры форков и незащищённые запросы на слияние не получают учётные данные для сканирования. Проверяйте каждое изменение в .gitlab-ci.yml перед запуском задания с секретами. Маскирование и скрытие переменной не делают недоверенный код CI безопасным.

Запустите сканирование и проверьте результаты

Создайте подходящий защищённый запрос на слияние или запустите конвейер для защищённой ветви по умолчанию. Начните с небольшого различия перед запуском платного сканирования всего репозитория.

Откройте задание codex-security и убедитесь, что его артефакты содержат:

  • scan-manifest.json
  • findings.json
  • coverage.json
  • results.sarif
  • scan-exit-code.txt

Затем откройте вкладку Security конвейера, проверьте предупреждения при загрузке и убедитесь в корректности идентификаторов результатов, уровней серьёзности и расположения в исходном коде. При сканировании ветви по умолчанию также создаются записи об уязвимостях проекта. Результаты запросов на слияние отображаются на вкладке Security конвейера или в виджете безопасности запроса на слияние, но не создают записей об уязвимостях на уровне всего проекта.

Ограничьте доступ к артефактам, поскольку результаты сканирования могут содержать уязвимые фрагменты исходного кода, доказательства и сведения об исправлении.

Выберите профиль сканирования

Конвейер выбирает профиль в зависимости от события запуска:

Событие запуска Цель Режим Интенсивность
Защищённый запрос на слияние в пределах одного проекта Зафиксированные изменения standard low
Включаемая по желанию отправка в защищённую ветвь по умолчанию или ручной запуск Весь репозиторий standard high
Включаемый по желанию запуск по расписанию в защищённой ветви по умолчанию Весь репозиторий deep xhigh

Сканирование запросов на слияние концентрирует обратную связь на зафиксированном изменении. Сканирование ветви по умолчанию проверяет интегрированный репозиторий. Плановое глубокое сканирование обеспечивает более широкий периодический охват. Завершённое сканирование различий относится только к данному изменению и не подтверждает отсутствие проблем во всём репозитории.

Рабочий процесс устанавливает CLI вне репозитория и запускает его по абсолютному пути. Предварительная проверка в режиме пробного запуска использует API key, доступный только процессу, но не начинает платное сканирование и не проверяет аутентификацию API, доступ к Codex Security, квоту или доступность модели.

Рабочий процесс записывает состояние и результаты сканирования вне рабочего дерева и предоставляет OPENAI_API_KEY только процессу сканирования. CLI получает небольшое явно заданное окружение вместо наследования всех переменных GitLab. Для сканирования различий рабочий процесс вычисляет базу слияния и привязывает сканирование к проверяемым базовой и головной ревизиям.

В примере @openai/codex-security закреплён на версии 0.1.20. Перед изменением закреплённой версии повторно проверьте аутентификацию, артефакты, загрузку SARIF и применение политик.

Отделите отчётность от применения политик

GitLab принимает SARIF из успешно выполненного задания отчётности. Сначала конвейер публикует отчёт, а затем восстанавливает код завершения сканера в отдельном задании codex-security-gate.

Задание отчётности принимает результаты с кодами завершения 0 и 1. Оно принимает код завершения 2 только в том случае, если манифест сканирования подтверждает завершение сканирования, охват явно обозначен как partial и существует непустой отчёт SARIF. Другие сбои выполнения, конфигурации или экспорта остаются блокирующими.

Итоговая проверка сохраняет следующие коды завершения сканера:

Код Значение
0 Сканирование завершилось с полным охватом и прошло проверку политики.
1 Сканирование завершилось и обнаружило проблему на заданном пороговом уровне серьёзности или выше.
2 Сканирование имело неполный охват либо произошла ошибка входных данных или выполнения.

В примере временно допускается код завершения 2 на период настройки частичного охвата. Удалите это допущение, когда неполный охват должен блокировать конвейер.

Исправление и публикация выполняются до итоговой проверки политики. Подходящий результат может привести к созданию проверенного черновика запроса на слияние, даже если позднее проверка завершит конвейер ошибкой.

Включите проверенное исправление

Автоматическое исправление необязательно и выполняется только для конвейеров защищённой ветви по умолчанию. Процесс исправления Codex и управляемые репозиторием команды проверки не получают токен доступа к проекту GitLab или учётные данные, предоставленные раннером.

Контракт безопасности состоит из трёх частей: управляемые репозиторием команды никогда не получают учётные данные OpenAI или GitLab, доступ на запись в репозиторий получает только задание публикации, а каждое сгенерированное изменение остаётся черновиком, пока человек не проверит и не сольёт его.

Рабочий процесс:

  1. Требует полного охвата сканирования и результата с уровнем серьёзности high или critical.
  2. Проверяет, что настроенный регрессионный тест завершается ошибкой до внесения исправления.
  3. Создаёт целевое исправление и отклоняет изменения файлов CI, учётных данных, двоичных и других защищённых файлов.
  4. Запускает регрессионный тест без учётных данных OpenAI, GitLab, реестра, развёртывания или токена задания.
  5. Использует verify-fix для возврата fixed, still_vulnerable или inconclusive. Задание публикует исправление, только когда verify-fix возвращает fixed и процесс проверки не изменяет исправление.

Для включения исправления задайте следующие защищённые переменные:

  • Задайте для CODEX_SECURITY_ENABLE_REMEDIATION значение true.
  • Задайте для CODEX_SECURITY_VERIFICATION_COMMAND существующий регрессионный тест, который завершается с кодом 1 до исправления и 0 после него.
  • При необходимости задайте для CODEX_SECURITY_SETUP_COMMAND неинтерактивную команду установки зависимостей.

Выбирайте регрессионный тест, проверяющий базовый инвариант безопасности, а не конкретную реализацию. Проверяйте сгенерированные изменения тестов и исходного кода столь же тщательно.

Дополнительно: изоляция команд репозитория

Команды validate, patch и verify-fix получают доступный только процессу CODEX_API_KEY. Управляемые репозиторием команды настройки и тестирования выполняются от имени отдельного непривилегированного пользователя в доступной для записи копии отслеживаемых исходных файлов. В копию намеренно не включаются метаданные Git, содержимое подмодулей и загруженные артефакты. Команды настройки и тестирования, которым требуются .git или подмодули, должны выполняться в отдельно спроектированном задании без учётных данных.

Только шаги Codex, выполняемые от имени root, могут обращаться к канонической рабочей копии или соседнему каталогу файловых переменных GitLab. Чистое окружение копии содержит только PATH, HOME, LANG, CI и CI_PROJECT_DIR. Если команде требуется другое несекретное значение, добавьте его в список разрешённых после проверки команды. Если ваш раннер не умеет переключать пользователей, перенесите проверку в отдельное задание без учётных данных, прежде чем включать исправление.

Опубликуйте черновик запроса на слияние

Создайте токен доступа к проекту GitLab с ролью Developer и областями доступа api и write_repository. Сохраните его как защищённую, маскируемую и скрытую переменную GITLAB_REMEDIATION_TOKEN, область которой ограничена окружением codex-security/publish.

Задайте CODEX_SECURITY_CREATE_MR=true, чтобы включить публикацию. Также задайте несекретную переменную CODEX_SECURITY_MR_TEST_COMMAND, указав специфичный для проекта регрессионный тест безопасности, который должна пройти каждая сгенерированная ветвь исправления. Оставьте эту переменную незащищённой, чтобы сгенерированный незащищённый запрос на слияние мог прочитать команду. Рабочий процесс публикации:

  • Получает токен для записи в репозиторий, но не учётные данные OpenAI.
  • Создаёт ветвь codex-security/fix-<finding-hash>.
  • Открывает черновик запроса на слияние и повторно использует существующий открытый черновик вместо создания дубликата.
  • Запускает регрессионный тест незащищённой ветви исправления от имени непривилегированного пользователя в копии только из отслеживаемых файлов без защищённых учётных данных.
  • Никогда не выполняет слияние сгенерированного изменения автоматически.

Не заменяйте токен доступа к проекту на CI_JOB_TOKEN. Он не может выполнить необходимую операцию создания запроса на слияние. Перед слиянием проверьте предлагаемое исправление, свидетельства проверки и результат сканирования.

Настройте необязательные переменные

Настраивайте только переменные, необходимые для включаемых функций:

Переменная Когда требуется Значение по умолчанию или назначение
CODEX_SECURITY_API_KEY Каждое сканирование Защищённая, маскируемая, скрытая; область ограничена codex-security/openai
CODEX_SECURITY_VERSION Обновление CLI Закреплена на 0.1.20; повторно протестируйте перед изменением
CODEX_SECURITY_FULL_SCAN_DEFAULT_BRANCH Полное сканирование ветви по умолчанию Явное включение; по умолчанию выключено
CODEX_SECURITY_SCHEDULED_DEEP_SCAN Плановое глубокое сканирование Явное включение; по умолчанию выключено
CODEX_SECURITY_DEEP_MAX_TIME_HOURS Плановое глубокое сканирование Обязательный лимит времени больше 0 и меньше 8
CODEX_SECURITY_DEEP_MAX_COST Плановое глубокое сканирование Обязательное ограничение предполагаемой стоимости в USD больше 0
CODEX_SECURITY_ENABLE_REMEDIATION Создание исправления Защищённое включение; по умолчанию выключено
CODEX_SECURITY_VERIFICATION_COMMAND Создание исправления Защищённый регрессионный тест
CODEX_SECURITY_SETUP_COMMAND Необязательная настройка исправления Защищённая установка зависимостей
CODEX_SECURITY_REMEDIATION_EFFORT Необязательная настройка параметров исправления high
CODEX_SECURITY_MAX_CHANGED_FILES Необязательное ограничение размера исправления 8; допустимый диапазон от 1 до 20
CODEX_SECURITY_CREATE_MR Создание черновика запроса на слияние Защищённое включение; по умолчанию выключено
GITLAB_REMEDIATION_TOKEN Создание черновика запроса на слияние Токен проекта Developer с областью codex-security/publish
CODEX_SECURITY_GITLAB_INTERNAL_URL Необязательная публикация в самостоятельно размещённом GitLab Сервер GitLab доступен с раннера
CODEX_SECURITY_MR_TEST_COMMAND Публикация черновика запроса на слияние Обязательный несекретный регрессионный тест, специфичный для проекта
CODEX_SECURITY_MR_SETUP_COMMAND Необязательная настройка ветви исправления Несекретная установка зависимостей

GitLab предоставляет переменные CI_*. Конвейер управляет CODEX_SECURITY_BIN, CODEX_SECURITY_EFFORT, CODEX_SECURITY_MODE, CODEX_SECURITY_STATE_DIR и CODEX_SECURITY_TARGET; не настраивайте их как переменные проекта. Для сканирования различий CLI получает канонический идентификатор цели из нормализованных базовой и головной ревизий.

Настройте применение политик и стоимость

Используйте целевое сканирование различий для обратной связи по запросам на слияние, стандартное сканирование репозитория для ветви по умолчанию и плановое глубокое сканирование для более широкого охвата. Оба профиля полного сканирования репозитория по умолчанию выключены. Для планового глубокого сканирования также требуются CODEX_SECURITY_DEEP_MAX_TIME_HOURS и CODEX_SECURITY_DEEP_MAX_COST; лимит времени CLI должен быть меньше восьмичасового тайм-аута задания. Измерьте длительность типичных запусков, прежде чем задавать лимит. Рассматривайте --max-cost как ориентировочное ограничение стоимости, а не жёсткий предел оплаты.

Начните со сканирования только с отчётами. Добавьте --fail-on-severity после того, как ваша команда проверит типичные результаты, охват, стоимость и время выполнения. Сведения о политиках серьёзности и кодах завершения см. в разделе Запуск Codex Security в CI.

При сбое задания:

  • Отсутствие артефактов сканирования указывает на проблему конфигурации или раннера.
  • Если артефакты существуют, но охват неполный, проверьте coverage.json.
  • Если в GitLab отсутствуют результаты, проверьте, успешно ли завершилось задание отчёта SARIF и принял ли GitLab отчёт.
  • Если исправление пропущено, проверьте защищённую ветвь, полноту охвата, серьёзность результата, команду проверки и переменные включения.
  • При ошибках публикации проверьте роль и области доступа токена проекта, а также ограничение окружения.

Описание всех команд, флагов и артефактов см. в справочнике Codex Security CLI.