GitLab CI/CD で Codex Security を実行する
GitLab CI/CD で Codex Security を実行して、コミット済みの変更と保護された ブランチをスキャンし、検出結果を GitLab Security に公開します。また、検証済みの 修正をドラフトマージリクエストとして提案することもできます。
このワークフローでは、スキャン認証情報とリポジトリへの書き込みアクセスを分離します。 生成された変更は、マージ前に必ず人によるレビューを必要とします。
まずはスキャン専用のレポートから始めてください。プロジェクトの ランナー、検出結果、認証情報の境界を確認した後にのみ、修復を有効にしてください。
始める前に
次のものが必要です。
- Codex サンドボックスのユーザー名前空間をサポートする、信頼できるランナーを備えた GitLab プロジェクト。
- プロジェクトの CI/CD 変数と保護された リソースを設定できる、GitLab プロジェクトの Maintainer または Owner ロール。
- Codex Security へのアクセス権を持つ OpenAI API key。Platform API key を使用する組織は、Cyber 向け Trusted Access を リクエストできます。 ChatGPT 認証を使用する個人は、個人向け Trusted Access フローを利用できます。一部のアカウントまたはリポジトリでは、 リポジトリ全体のスキャンにこのアクセス権が必要です。
- SARIF 2.1.0 の 取り込みには、GitLab Ultimate 19.2 以降。
- マージリクエストジョブでマージベースを計算するための完全な Git 履歴。
パイプラインイメージには、Node.js 26、Python 3、Git、rg、固定バージョンの
Codex Security CLI がインストールされます。自動修復にはさらに、既存の
回帰テストと、保護された認証情報を使用せずにリポジトリ管理下のコマンドを実行できる
ランナーが必要です。
スキャン専用パイプラインから始める
CODEX_SECURITY_API_KEY という名前の、マスク済み、非表示、保護対象の GitLab CI/CD 変数を
作成します。Codex Security へのアクセス権を持つ OpenAI Platform API key を使用し、
環境スコープを 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 をリポジトリ外にインストールし、絶対パスで実行します。 dry-run の事前チェックではプロセススコープの 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 プロジェクトアクセストークンやランナーから注入される 認証情報は渡されません。
セキュリティ契約は 3 つの部分で構成されます。リポジトリ管理下のコマンドには 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 ステップだけが、正規のチェックアウトまたは GitLab の
隣接するファイル変数ディレクトリにアクセスできます。コピーのクリーンな環境に含まれるのは、
PATH、HOME、LANG、CI、CI_PROJECT_DIR だけです。コマンドに別の
非機密値が必要な場合は、コマンドをレビューした後に許可リストへ追加してください。
ランナーでユーザーを切り替えられない場合は、修復を有効にする前に、検証を認証情報のない別のジョブへ
移動してください。
ドラフトマージリクエストを公開する
Developer ロールと api および write_repository のスコープを持つ
GitLab プロジェクトアクセストークンを
作成します。codex-security/publish 環境のみをスコープとする、
保護済み、マスク済み、非表示の GITLAB_REMEDIATION_TOKEN として保存します。
公開を有効にするには、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 |
スケジュール済みディープスキャン | 0 より大きい USD 建ての推定コスト上限が必要 |
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 |
ドラフトマージリクエストの作成 | codex-security/publish をスコープとする Developer プロジェクトトークン |
CODEX_SECURITY_GITLAB_INTERNAL_URL |
任意のセルフホスト型公開 | ランナーから GitLab origin に到達可能 |
CODEX_SECURITY_MR_TEST_COMMAND |
ドラフトマージリクエストの公開 | 必須の非機密なプロジェクト固有の回帰テスト |
CODEX_SECURITY_MR_SETUP_COMMAND |
任意の修復ブランチセットアップ | 非機密な依存関係セットアップ |
CI_* 変数は GitLab が提供します。パイプラインは
CODEX_SECURITY_BIN、CODEX_SECURITY_EFFORT、CODEX_SECURITY_MODE、
CODEX_SECURITY_STATE_DIR、CODEX_SECURITY_TARGET を管理するため、これらを
プロジェクト変数として設定しないでください。差分スキャンでは、CLI が正規化されたベースリビジョンと
ヘッドリビジョンから正規のターゲット ID を導出します。
適用レベルとコストを調整する
マージリクエストへのフィードバックには対象を絞った差分スキャン、デフォルトブランチには
標準のリポジトリスキャン、より広範なカバレッジにはスケジュール済みディープスキャンを使用します。
リポジトリ全体を対象とする 2 つのプロファイルは、どちらもデフォルトではオフです。スケジュール済みディープスキャンには
CODEX_SECURITY_DEEP_MAX_TIME_HOURS と CODEX_SECURITY_DEEP_MAX_COST も必要です。CLI の
時間予算はジョブの 8 時間のタイムアウトより短くしてください。予算を設定する前に、代表的な実行を
計測してください。--max-cost はハードな請求上限ではなく、推定コストのガードレールとして扱ってください。
まずはレポート専用スキャンから始めてください。代表的な検出結果、カバレッジ、コスト、
実行時間をチームでレビューした後に、--fail-on-severity を追加します。重大度ポリシーと終了コードの
詳細については、CI で Codex
Security を実行するを参照してください。
ジョブが失敗した場合は、次を確認します。
- スキャンアーティファクトがない場合は、設定またはランナーに問題があります。
- アーティファクトが存在していてカバレッジが部分的な場合は、
coverage.jsonを確認する必要があります。 - GitLab の検出結果がない場合は、SARIF レポートジョブが 成功したか、GitLab がレポートを受け入れたかを確認する必要があります。
- 修復がスキップされた場合は、保護されたブランチ、完全な カバレッジ、検出結果の重大度、検証コマンド、オプトイン変数を確認する必要があります。
- 公開エラーが発生した場合は、プロジェクトトークンのロール、スコープ、 環境制限を確認する必要があります。
すべてのコマンド、フラグ、アーティファクトについては、Codex Security CLI リファレンスを参照してください。