审查代码变更的安全性
当你需要获取有关某个 Git 支持的变更集所引入回归问题的证据时,可以使用安全变更审查。该工作流会审查每个发生变更的源代码类文件及其直接支撑代码,但不会将任务扩展为常规的代码仓库审计。
如果你想扫描整个代码仓库,而不是特定变更,请参阅运行安全扫描。
运行手动审查
Section titled “运行手动审查”对于未提交的变更,请发送:
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.如果本地检出中提供了基准修订和头部修订,你也可以指定拉取请求。
在设置中确认变更
Section titled “在设置中确认变更”- 确认 Scan type 为
Changes。 - 确认已检出的 Codebase、Current branch 和 Last commit。
- 在 Changes to review 下选择:
- 对于当前工作树,请选择
Uncommitted changes。 - 对于单次提交的审查,请选择最新提交。
- 对于分支或拉取请求范围,请选择基准修订和头部修订。
- 对于当前工作树,请选择
- 确认摘要描述的是你要审查的变更。
- 选择 Start scan。
该工作流不会检出其他分支,也不会更改所选工作树。如果请求的修订在本地不可用,请在审查前获取该修订,或提供本地可用的基准修订和头部修订。
处理发现的问题
Section titled “处理发现的问题”查看结果后,可以修复并验证已接受的问题,或导出并跟踪发现的问题。
在 CI/CD 中自动执行审查
Section titled “在 CI/CD 中自动执行审查”当运行程序可以无交互地调用 Codex CLI 时,可以在 CI 中运行同一个 $codex-security:security-diff-scan 技能。首先安装 CLI 和插件,同时不要暴露扫描凭据:
npm install --global @openai/codexcodex plugin add codex-security@openai-curated然后,仅在扫描期间,将 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>/ |
每个可报告问题对应一份详细的漏洞报告;如果有可用的概念验证文件,也会一并包含。 |
hardening/ |
结构化加固方案集,以及扫描发现可报告问题时提供的支持性提案或图表。 |
findings.json |
包含稳定标识符、严重性、置信度、源代码位置和修复建议的问题。可用它创建拉取请求评论,或将数据提供给下游工具。 |
scan-manifest.json |
已封存的扫描回执,其中包含审查目标、修订版本和构件哈希。 |
coverage.json |
已审查和延后的范围、排除项以及覆盖完整性。 |
findings.json 架构定义了完整结构。以下是一些关键字段:
| 字段 | 类型 | 描述 |
|---|---|---|
documentType |
String | 将文档标识为 codex-security.findings。 |
schemaVersion |
String | 标识问题架构版本。 |
scanId |
String | 标识生成这些问题的扫描。 |
findings |
Array | 包含零个或多个问题对象。 |
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 | 标识问题来源。 |
例如,此命令会为每个问题输出一行以制表符分隔的记录:
jq -r ' .findings[] | [.findingId, .severity.level, .confidence.level, .locations[0].path, .locations[0].startLine, .title] | @tsv' findings.json这些示例假设使用受信任的 Linux 运行程序,并已安装 Node.js、npm、Git、Python 3、jq 和提供商的命令行工具。npm 全局软件包前缀必须可写。
以下是如何在常见流水线中使用 Codex Security 的示例。
GitHub Actions
Section titled “GitHub Actions”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-scansGitLab CI/CD
Section titled “GitLab CI/CD”创建经过掩码处理的 CODEX_SECURITY_API_KEY 和 GITLAB_TOKEN CI/CD 变量。GitLab 令牌需要具备 API 访问权限,以创建合并请求备注。
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.gzAzure Pipelines
Section titled “Azure Pipelines”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()对于 Azure Repos,请配置 Build validation 分支策略,使该流水线在拉取请求上运行。
Jenkins
Section titled “Jenkins”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 } } } }}这些示例会跳过来自复刻仓库的拉取请求。仅从受保护的流水线定义中运行包含凭据的任务,并且仅允许受信任的贡献者使用扫描凭据。归档 codex-security-scans,以便将结构化发现、清单、覆盖范围构件、report.md 及其链接的 findings/ 和 hardening/ 输出保存在一起。在将该任务设为必需检查之前,请先从建议性结果开始,并审查覆盖范围和运行时。
有关 API 密钥处理和沙箱控制,请参阅非交互模式。如果你的组织允许使用 Codex GitHub Action,它可以在运行时安装 CLI,但你仍必须先安装插件,并将该操作的 codex-home 输入指向同一个 CODEX_HOME。