跳转到内容

审查代码变更的安全性

当你需要获取有关某个 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.

如果本地检出中提供了基准修订和头部修订,你也可以指定拉取请求。

  1. 确认 Scan type 为 Changes。
  2. 确认已检出的 Codebase、Current branch 和 Last commit。
  3. 在 Changes to review 下选择:
    • 对于当前工作树,请选择 Uncommitted changes。
    • 对于单次提交的审查,请选择最新提交。
    • 对于分支或拉取请求范围,请选择基准修订和头部修订。
  4. 确认摘要描述的是你要审查的变更。
  5. 选择 Start scan。

该工作流不会检出其他分支,也不会更改所选工作树。如果请求的修订在本地不可用,请在审查前获取该修订,或提供本地可用的基准修订和头部修订。

查看结果后,可以修复并验证已接受的问题,或导出并跟踪发现的问题。

当运行程序可以无交互地调用 Codex CLI 时,可以在 CI 中运行同一个 $codex-security:security-diff-scan 技能。首先安装 CLI 和插件,同时不要暴露扫描凭据:

Terminal window
npm install --global @openai/codex
codex plugin add codex-security@openai-curated

然后,仅在扫描期间,将 CI 密钥存储中的 OpenAI API 密钥作为 CODEX_SECURITY_API_KEY 暴露:

Terminal window
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 标识问题来源。

例如,此命令会为每个问题输出一行以制表符分隔的记录:

Terminal window
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 的示例。

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_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.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()

对于 Azure Repos,请配置 Build validation 分支策略,使该流水线在拉取请求上运行。

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。