Запуск 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 перед запуском задания с секретами.
В минимальном примере намеренно отсутствуют полное сканирование и исправление.
Перейдите на конвейер промышленного уровня
- Скачайте полный конвейер GitLab
и сохраните его как
.gitlab-ci.ymlв корне репозитория. Если в репозитории уже есть конвейер, объедините этапы, скрытые шаблоны и задания примера с существующим файлом. - Сохраните существующие этапы сборки, тестирования и развёртывания. Если проект использует
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.jsonfindings.jsoncoverage.jsonresults.sarifscan-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, доступ на запись в репозиторий получает только задание публикации, а каждое сгенерированное изменение остаётся черновиком, пока человек не проверит и не сольёт его.
Рабочий процесс:
- Требует полного охвата сканирования и результата с уровнем серьёзности
highилиcritical. - Проверяет, что настроенный регрессионный тест завершается ошибкой до внесения исправления.
- Создаёт целевое исправление и отклоняет изменения файлов CI, учётных данных, двоичных и других защищённых файлов.
- Запускает регрессионный тест без учётных данных OpenAI, GitLab, реестра, развёртывания или токена задания.
- Использует
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.