セキュリティのためにコード変更をレビューする¶
1 つの Git 管理された変更セットによって導入されたリグレッションの証拠が必要な場合は、セキュリティ変更レビューを使用します。このワークフローでは、リポジトリ全体の一般的な監査にすることなく、変更されたすべてのソースに類するファイルと、それを直接サポートするコードをレビューします。
特定の変更ではなくリポジトリ全体をスキャンする場合は、セキュリティスキャンを実行するを参照してください。
手動レビューを実行する¶
コミットされていない変更の場合は、次の内容を送信します。
Use $codex-security:security-diff-scan to review my current uncommitted changes for security regressions.
コミットまたはブランチ範囲の場合は、必要に応じて両端を指定します。
Use $codex-security:security-diff-scan to review the changes from origin/main to HEAD for security regressions. Focus on authentication, authorization, input handling, filesystem access, network requests, and secrets.
ローカルチェックアウトでベースとヘッドのリビジョンを利用できる場合は、プルリクエストを指定することもできます。
セットアップで変更を確認する¶
- スキャンタイプが
Changesであることを確認します。 - チェックアウトされている コードベース、現在のブランチ、最後のコミットを確認します。
- レビューする変更で、次のいずれかを選択します。
- 現在の作業ツリーには
Uncommitted changesを選択します。 - 1 つのコミットをレビューするには、最新のコミットを選択します。
- ブランチまたはプルリクエストの範囲には、ベースとヘッドのリビジョンを選択します。
- 概要に、レビューする意図した変更が記載されていることを確認します。
- スキャンを開始を選択します。
このワークフローでは、別のブランチをチェックアウトしたり、選択した作業ツリーを変更したりすることはありません。要求されたリビジョンがローカルで利用できない場合は、レビューの前にフェッチするか、ローカルで利用できるベースとヘッドを指定してください。
検出結果に対応する¶
結果をレビューしたら、承認した検出結果を修正して検証するか、検出結果をエクスポートして追跡することができます。
CI/CD でレビューを自動化する¶
ランナーが Codex CLI を対話なしで呼び出せる場合は、CI から同じ $codex-security:security-diff-scan スキルを実行します。まず、スキャン認証情報を公開せずに CLI とプラグインをインストールします。
次に、CI のシークレットストアから OpenAI API キーを CODEX_SECURITY_API_KEY として、スキャン時にのみ公開します。
CODEX_API_KEY="$CODEX_SECURITY_API_KEY" codex exec \
--sandbox workspace-write \
"Use \$codex-security:security-diff-scan to review changes from $BASE_REVISION to $HEAD_REVISION for security regressions. Do not modify the checkout."
スキャンは出力を $TMPDIR/codex-security-scans/<repository>/<scan-id>/ に書き込みます。
| ファイル | 内容 |
|---|---|
report.md |
完全なスキャンディレクトリへの、主要な可読エントリポイントです。 |
findings/<slug>/ |
報告対象の検出結果ごとに 1 つ作成される詳細な脆弱性レポートです。利用可能な場合は、裏付けとなる概念実証ファイルも含まれます。 |
hardening/ |
構造的な強化のポートフォリオと、スキャンに報告対象の検出結果がある場合の補足提案または図です。 |
findings.json |
安定した識別子、重大度、信頼度、ソースの場所、修正方法を含む検出結果です。プルリクエストのコメント作成や下流ツールへの入力に使用します。 |
scan-manifest.json |
レビュー対象、リビジョン、アーティファクトのハッシュを含む、封印されたスキャンレシートです。 |
coverage.json |
レビュー済みおよび保留中のサーフェス、除外、カバレッジの完全性です。 |
findings.json スキーマでは、完全な構造を定義しています。主なフィールドは次のとおりです。
| フィールド | 型 | 説明 |
|---|---|---|
documentType |
String | ドキュメントが codex-security.findings であることを識別します。 |
schemaVersion |
String | 検出結果スキーマのバージョンを識別します。 |
scanId |
String | 検出結果を生成したスキャンを識別します。 |
findings |
Array | 0 個以上の検出結果オブジェクトを含みます。 |
findings[].findingId |
String | 検出結果のフィンガープリントから導出された安定した検出結果識別子です。 |
findings[].occurrenceId |
String | 特定のスキャンにおける、この検出結果の発生を識別します。 |
findings[].ruleId |
String | 脆弱性ファミリーを識別します。 |
findings[].identity |
Object | セマンティックアンカーと、任意の兄弟インスタンス識別子を含みます。 |
findings[].fingerprints |
Object | フィンガープリントアルゴリズムと主要なフィンガープリントを含みます。 |
findings[].title |
String | 検出結果の短いタイトルを指定します。 |
findings[].summary |
String | 脆弱性とその影響を要約します。 |
findings[].severity |
Object | 重大度レベルと、任意のスコアリングの詳細を含みます。 |
findings[].confidence |
Object | 信頼度レベルとその根拠を含みます。 |
findings[].taxonomy |
Object | 脆弱性カテゴリと CWE 識別子を含みます。 |
findings[].locations |
Array | 影響を受けるファイル、行番号、場所の役割を一覧表示します。 |
findings[].remediation |
String | 推奨される修正方法を説明します。 |
findings[].provenance |
Object | 検出結果のソースを識別します。 |
たとえば、次のコマンドは検出結果ごとにタブ区切りの行を 1 行出力します。
jq -r '
.findings[] |
[.findingId, .severity.level, .confidence.level, .locations[0].path, .locations[0].startLine, .title] |
@tsv
' findings.json
これらの例では、Node.js と npm、Git、Python 3、jq、およびプロバイダーのコマンドラインツールがインストールされた、信頼できる Linux ランナーを想定しています。npm グローバルパッケージプレフィックスは書き込み可能である必要があります。
一般的なパイプラインで Codex Security を使用する例を次に示します。
<Tabs id="codex-security-ci-examples" param="ci" defaultTab="github" tabs={[ { id: "github", label: "GitHub Actions" }, { id: "gitlab", label: "GitLab CI/CD" }, { id: "azure", label: "Azure Pipelines" }, { id: "jenkins", label: "Jenkins" }, ]}
name: Codex Security review on: pull_request: jobs: security-review: if: github.event.pull_request.head.repo.full_name == github.repository runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@v5 with: ref: ${{ github.event.pull_request.head.sha }} fetch-depth: 0 persist-credentials: false - name: Install Codex Security env: CODEX_HOME: ${{ runner.temp }}/codex-home run: | npm install --global @openai/codex codex plugin add codex-security@openai-curated - name: Review code changes env: CODEX_SECURITY_API_KEY: ${{ secrets.CODEX_SECURITY_API_KEY }} CODEX_HOME: ${{ runner.temp }}/codex-home TMPDIR: ${{ runner.temp }}/codex-security BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_REVISION: ${{ github.event.pull_request.head.sha }} run: | BASE_REVISION="$(git merge-base "$BASE_SHA" "$HEAD_REVISION")" CODEX_API_KEY="$CODEX_SECURITY_API_KEY" codex exec \ --sandbox workspace-write \ "Use \$codex-security:security-diff-scan to review changes from $BASE_REVISION to $HEAD_REVISION for security regressions. Do not modify the checkout." - name: Comment with findings if: always() env: GH_TOKEN: ${{ github.token }} PR_NUMBER: ${{ github.event.pull_request.number }} run: | findings="$(find "${{ runner.temp }}/codex-security/codex-security-scans" -name findings.json -print -quit 2>/dev/null || true)" test -n "$findings" || exit 0 jq -r ' "## Codex Security findings", "", if (.findings | length) == 0 then "No findings reported." else .findings[] | "- **\(.severity.level | ascii_upcase)**: \(.title) (`\(.locations[0].path):\(.locations[0].startLine)`)\n \(.summary)" end ' "$findings" | gh pr comment "$PR_NUMBER" --body-file - - uses: actions/upload-artifact@v4 if: always() with: name: codex-security-review path: ${{ runner.temp }}/codex-security/codex-security-scans
codex-security-review:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_SOURCE_PROJECT_ID == $CI_PROJECT_ID'
variables:
GIT_DEPTH: "0"
script:
- |
codex_security_api_key="$CODEX_SECURITY_API_KEY"
unset CODEX_SECURITY_API_KEY GITLAB_TOKEN
export CODEX_HOME="/tmp/codex-home-$CI_JOB_ID"
export TMPDIR="/tmp/codex-security-$CI_JOB_ID"
export BASE_REVISION="$CI_MERGE_REQUEST_DIFF_BASE_SHA"
export HEAD_REVISION="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}"
npm install --global @openai/codex
codex plugin add codex-security@openai-curated
CODEX_API_KEY="$codex_security_api_key" codex exec \
--sandbox workspace-write \
"Use \$codex-security:security-diff-scan to review changes from $BASE_REVISION to $HEAD_REVISION for security regressions. Do not modify the checkout."
after_script:
- |
gitlab_token="$GITLAB_TOKEN"
unset CODEX_SECURITY_API_KEY GITLAB_TOKEN
scan_root="/tmp/codex-security-$CI_JOB_ID/codex-security-scans"
findings="$(find "$scan_root" -name findings.json -print -quit 2>/dev/null || true)"
if [ -n "$findings" ]; then
jq -r '
"## Codex Security findings",
"",
if (.findings | length) == 0 then "No findings reported."
else .findings[] | "- **\(.severity.level | ascii_upcase)**: \(.title) (`\(.locations[0].path):\(.locations[0].startLine)`)\n \(.summary)"
end
' "$findings" > codex-security-comment.md
curl --fail --request POST \
--header "PRIVATE-TOKEN: $gitlab_token" \
--form "body=<codex-security-comment.md" \
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
fi
if [ -d "$scan_root" ]; then
tar -czf codex-security-artifacts.tar.gz -C "$scan_root" .
fi
artifacts:
when: always
paths:
- codex-security-artifacts.tar.gz
trigger: none
pool:
vmImage: ubuntu-latest
steps:
- checkout: self
fetchDepth: 0
- bash: |
set -euo pipefail
export CODEX_HOME="$AGENT_TEMPDIRECTORY/codex-home"
npm install --global @openai/codex
codex plugin add codex-security@openai-curated
displayName: Install Codex Security
- bash: |
set -euo pipefail
export CODEX_HOME="$AGENT_TEMPDIRECTORY/codex-home"
export TMPDIR="$AGENT_TEMPDIRECTORY/codex-security"
export HEAD_REVISION="$SYSTEM_PULLREQUEST_SOURCECOMMITID"
export BASE_REVISION="$(git merge-base HEAD^1 "$HEAD_REVISION")"
CODEX_API_KEY="$CODEX_SECURITY_API_KEY" codex exec \
--sandbox workspace-write \
"Use \$codex-security:security-diff-scan to review changes from $BASE_REVISION to $HEAD_REVISION for security regressions. Do not modify the checkout."
displayName: Review code changes
condition: and(succeeded(), ne(variables['System.PullRequest.IsFork'], 'True'))
env:
CODEX_SECURITY_API_KEY: $(CODEX_SECURITY_API_KEY)
- publish: $(Agent.TempDirectory)/codex-security/codex-security-scans
artifact: codex-security-review
condition: always()
pipeline {
agent { label 'linux' }
stages {
stage('Codex Security review') {
when {
allOf {
changeRequest()
expression { !env.CHANGE_FORK?.trim() }
}
}
steps {
sh '''#!/usr/bin/env bash
set -euo pipefail
export CODEX_HOME="/tmp/codex-home-$BUILD_TAG"
export TMPDIR="/tmp/codex-security-$BUILD_TAG"
mkdir -p "$TMPDIR"
git fetch --no-tags origin "$CHANGE_TARGET"
target="$(git rev-parse FETCH_HEAD)"
git fetch --no-tags origin "$CHANGE_BRANCH"
git rev-parse FETCH_HEAD > "$TMPDIR/head"
git merge-base "$target" "$(cat "$TMPDIR/head")" > "$TMPDIR/base"
npm install --global @openai/codex
codex plugin add codex-security@openai-curated
'''
withCredentials([string(credentialsId: 'codex-security-api-key', variable: 'CODEX_SECURITY_API_KEY')]) {
sh '''#!/usr/bin/env bash
set +x
set -euo pipefail
export CODEX_HOME="/tmp/codex-home-$BUILD_TAG"
export TMPDIR="/tmp/codex-security-$BUILD_TAG"
export HEAD_REVISION="$(cat "$TMPDIR/head")"
export BASE_REVISION="$(cat "$TMPDIR/base")"
CODEX_API_KEY="$CODEX_SECURITY_API_KEY" codex exec \
--sandbox workspace-write \
"Use \$codex-security:security-diff-scan to review changes from $BASE_REVISION to $HEAD_REVISION for security regressions. Do not modify the checkout."
'''
}
}
post {
always {
sh '''#!/usr/bin/env bash
set -euo pipefail
scan_root="/tmp/codex-security-$BUILD_TAG/codex-security-scans"
if [ -d "$scan_root" ]; then
tar -czf codex-security-artifacts.tar.gz -C "$scan_root" .
fi
'''
archiveArtifacts artifacts: 'codex-security-artifacts.tar.gz', allowEmptyArchive: true
}
}
}
}
}
この例では、フォークからのプルリクエストをスキップします。認証情報を使用するジョブは、保護されたパイプライン定義からのみ実行し、スキャン認証情報を信頼できる貢献者に対してのみ実行してください。構造化された検出結果、マニフェスト、カバレッジアーティファクト、report.md、およびそれにリンクされた findings/ と hardening/ の出力をまとめて保持するために、codex-security-scans をアーカイブします。まずは助言的な結果から始め、ジョブを必須チェックにする前に、カバレッジと実行時間を確認してください。
API キーの処理とサンドボックス制御については、非対話モードを参照してください。組織で Codex GitHub Action が許可されている場合は、実行時に CLI をインストールできますが、それでも最初にプラグインをインストールし、アクションの codex-home 入力を同じ CODEX_HOME に指定する必要があります。