第一章:GitHub上发布Go项目的OpenSSF Scorecard 4.0合规总览
OpenSSF Scorecard 4.0 是开源软件安全基金会推出的自动化安全健康度评估工具,专为 GitHub 仓库设计,全面检查项目在开发流程、依赖管理、代码审查、签名验证等维度的实践成熟度。对于 Go 语言项目,Scorecard 不仅识别 .go 文件和 go.mod 结构,还深度集成 Go 生态特有机制(如 gofumpt 格式化、govulncheck 漏洞扫描、cosign 签名验证)以提供精准评分。
安装与本地运行 Scorecard
确保已安装 scorecard CLI(v4.0+)及 Go 工具链:
# 使用 Go install 安装最新稳定版(需 Go 1.21+)
go install github.com/ossf/scorecard/v4/cmd/scorecard@latest
# 验证版本(输出应含 v4.x.x)
scorecard --version
执行扫描时需提供 GitHub 令牌以访问私有 API(如启用 Dependabot 或 Code Scanning):
# 扫描公开 Go 仓库(替换为你的仓库 URL)
scorecard --repo=https://github.com/your-org/your-go-project \
--show-details \
--format=json > scorecard-report.json
关键 Go 专属检查项
Scorecard 4.0 对 Go 项目启用以下高价值检查(默认激活):
- Pinned Dependencies:验证
go.mod中所有依赖是否使用精确语义化版本(非latest或通配符) - Vulnerability Detection:调用
govulncheck扫描模块依赖中的已知 CVE(需GOOS=linux GOARCH=amd64 govulncheck可用) - Signed Releases:检查 GitHub Release 是否使用
cosign签名,并在release.yml中配置sign-release步骤 - Automated Security Testing:识别是否在 CI(如 GitHub Actions)中集成
gosec或staticcheck
合规提升建议
| 检查项 | 推荐实践 |
|---|---|
| Branch Protection | 启用 main 分支保护规则:要求 PR 审查、状态检查通过、线性提交历史 |
| Code Review | 在 .github/workflows/ci.yml 中添加 reviewdog 或 golangci-lint 检查 |
| Dependency Updates | 配置 Dependabot 自动更新 go.mod,并启用 security_updates: true |
项目根目录应包含 SECURITY.md 和 CODE_OF_CONDUCT.md,且 go.mod 文件必须存在——Scorecard 将据此判定为有效 Go 项目并启用全部语言特异性检查。
第二章:代码签名(Signed Releases)的深度实践
2.1 Go模块签名机制与cosign原理剖析
Go 模块签名依托于 go.sum 文件的校验机制,但其本身不提供强身份认证。cosign 填补了这一空白,通过基于 Sigstore 的透明日志(Rekor)和密钥管理(Fulcio)实现可验证的签名。
签名流程核心组件
- Fulcio:颁发短期证书(X.509),绑定 OIDC 身份(如 GitHub Actions)
- Rekor:不可篡改的签名存证账本,支持二分查找验证
- Cosign CLI:统一接口封装签名/验证/审计操作
cosign 签名示例
# 使用 OIDC 身份自动签发证书并签名模块包
cosign sign --oidc-issuer https://token.actions.githubusercontent.com \
--fulcio-url https://fulcio.sigstore.dev \
--rekor-url https://rekor.sigstore.dev \
ghcr.io/myorg/mymodule@sha256:abc123
此命令触发三步链式操作:① 向 Fulcio 请求 OIDC 认证证书;② 用私钥签名模块 digest;③ 将签名+证书+公钥哈希写入 Rekor。
--rekor-url参数确保所有签名公开可查,实现供应链透明性。
| 组件 | 协议/标准 | 关键保障 |
|---|---|---|
| Fulcio | X.509 + OIDC | 身份绑定、证书时效性 |
| Rekor | Merkle Tree | 签名防篡改、存在证明 |
| Cosign CLI | OCI Artifact | 兼容容器生态与模块包 |
graph TD
A[开发者执行 cosign sign] --> B[Fulcio 颁发短期证书]
B --> C[本地私钥签名模块摘要]
C --> D[上传签名+证书到 Rekor]
D --> E[生成可验证的 OCI artifact]
2.2 在GitHub Actions中自动化生成和验证SLSA3级签名
SLSA3 要求构建过程受控、可重现且具备完整 provenance(来源证明),GitHub Actions 是实现该等级的理想执行环境。
核心依赖组件
slsa-framework/slsa-github-generator: 官方认证的 Go 构建器(.github/workflows/build.yml)sigstore/cosign: 签名与验证工具actions/checkout@v4+actions/setup-go@v5: 确保源码与构建环境一致性
构建与签名工作流节选
- name: Generate SLSA provenance and sign
uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_v1.yml@v1.12.0
with:
binary: ./bin/app
upload-assets: true
此动作自动触发
slsa-verifier验证构建环境完整性,生成符合 SLSA Spec v1.0 的slsa-provenance.json,并用 GitHub OIDC 签发短时效证书签名二进制与 provenance。binary指定输出路径,upload-assets启用 GitHub Release 关联发布。
验证流程(mermaid)
graph TD
A[下载 release assets] --> B[cosign verify-blob --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp '.*github\.com/.*/.*' bin/app]
B --> C{验证通过?}
C -->|是| D[确认 provenance 签名 & 构建链完整性]
C -->|否| E[拒绝执行]
| 验证项 | 工具 | 输出示例 |
|---|---|---|
| 二进制签名 | cosign verify-blob |
Verified OK |
| Provenance 结构 | slsa-verifier verify-artifact |
PASSED: Verified SLSA level 3 |
2.3 使用fulcio+rekor构建可审计的签名基础设施
Fulcio 是一个 OIDC 驱动的证书颁发机构,专为软件供应链签名设计;Rekor 则是不可篡改的透明日志,用于存证签名事件。二者协同构成零信任签名基础设施的核心。
核心组件职责
- Fulcio:签发短期 X.509 证书(默认10分钟),绑定 OIDC 身份(如 GitHub Actions OIDC token)
- Rekor:接收并持久化签名条目(
tlog entry),提供全局可验证、可查询的审计线索
签名流程示意
graph TD
A[开发者触发 CI] --> B[OIDC Token 向 Fulcio 申请证书]
B --> C[Fulcio 验证身份并签发证书]
C --> D[cosign sign -cert -key -oidc-issuer ...]
D --> E[签名 + 证书 + payload hash 写入 Rekor]
E --> F[Rekor 返回唯一 UUID 和 tlog index]
示例签名命令
cosign sign \
--fulcio-url https://fulcio.sigstore.dev \
--rekor-url https://rekor.sigstore.dev \
--oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/myorg/mymodule:v1.0.0
--fulcio-url指定证书颁发端点;--rekor-url声明日志写入位置;--oidc-issuer必须与 OIDC token 的iss声明严格匹配,否则 Fulcio 拒绝签发。
| 组件 | 审计能力 | 数据持久性 |
|---|---|---|
| Fulcio | 仅保留证书签发元数据(无签名体) | 临时缓存 |
| Rekor | 完整存储签名、证书、哈希、时间戳 | 永久、Merkle 化 |
2.4 修复go.dev/pkg签名状态缺失的典型错误链
根因定位:签名元数据未随模块同步
go.dev/pkg 依赖 index.golang.org 提供的签名状态(sigstore/rekor 索引),但常见错误是 go list -m -json 输出中缺失 Signatures 字段。
关键修复步骤
- 确保模块发布时启用
GOSUMDB=sum.golang.org(默认)且未被代理拦截 - 检查
go.mod中go 1.21+版本声明(签名验证自 1.21 起强制增强) - 验证
GOPROXY未跳过校验(如GOPROXY=https://proxy.golang.org,direct合法;GOPROXY=direct则丢失签名元数据)
签名状态获取示例
# 查询模块签名状态(需 go 1.22+)
go list -m -json -versions rsc.io/quote@v1.5.2
此命令触发
index.golang.org/v1/lookupHTTP 请求,返回含"Signatures": [...]的 JSON。若字段为空,表明索引服务尚未同步该版本的 Sigstore 签名条目。
| 字段 | 含义 | 缺失影响 |
|---|---|---|
Signatures |
Sigstore 公钥签名哈希列表 | go.dev/pkg 显示“Unsigned”红标 |
Origin |
模块源仓库 URL | 影响可信来源判定 |
Timestamp |
签名时间戳 | 决定是否接受过期签名 |
graph TD
A[开发者推送 v1.5.2] --> B{go.dev/pkg 轮询 index.golang.org}
B --> C[发现新版本但无签名条目]
C --> D[显示“Signature status: missing”]
D --> E[手动触发 rekor CLI 提交签名]
2.5 签名策略与语义化版本标签的协同治理
签名策略需与语义化版本(SemVer)标签深度耦合,确保每次 vX.Y.Z 发布均携带不可篡改的可信凭证。
签名验证流程
# 使用 Git tag 签名 + SemVer 校验脚本
git verify-tag v1.2.0 && \
semver --validate $(git describe --tags --exact-match)
git verify-tag验证 GPG 签名有效性;semver --validate检查标签是否符合MAJOR.MINOR.PATCH格式及递增逻辑。
协同校验规则
| 触发事件 | 版本变更要求 | 签名强制级别 |
|---|---|---|
PATCH 更新 |
允许热修复,需签名 | 强制 |
MINOR 新增 |
向后兼容,需双签 | 强制+审计日志 |
MAJOR 不兼容 |
需三方会审+签名链 | 强制+CA背书 |
自动化流水线协同
graph TD
A[Git push tag v2.1.0] --> B{SemVer 格式校验}
B -->|通过| C[调用 GPG 签名服务]
B -->|失败| D[拒绝推送]
C --> E[写入签名元数据至 OCI registry]
第三章:分支保护(Branch Protection)的Go项目适配
3.1 Go monorepo场景下的main/main-v2/develop多分支保护策略
在大型 Go monorepo 中,main(稳定发布)、main-v2(v2 API 过渡)与 develop(集成预演)三分支并行演进,需差异化保护。
分支语义与准入规则
main:仅允许经 CI 验证的 tag 推送,禁止直接 pushmain-v2:需v2/目录变更 + v2 兼容性测试通过develop:允许 PR 合并,但须通过全部单元与集成测试
GitHub Actions 分支保护配置示例
# .github/workflows/branch-protection.yml
name: Branch Protection
on:
pull_request:
branches: [main, main-v2, develop]
jobs:
enforce:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Validate Go modules
run: go list -m all 2>/dev/null || exit 1
此检查确保 PR 修改未破坏模块依赖图;
go list -m all验证go.mod可解析性,避免隐式版本漂移。
CI 策略对比表
| 分支 | 必需检查项 | 合并阻断条件 |
|---|---|---|
main |
e2e 测试、CVE 扫描、签名验证 | 任一失败即拒绝合并 |
main-v2 |
v2 接口契约测试、双栈路由兼容性 | v2/ 外路径修改需额外审批 |
develop |
单元测试覆盖率 ≥85%、gofmt 校验 | 覆盖率下降超 0.5% 报警 |
graph TD
A[PR 提交] --> B{目标分支}
B -->|main| C[触发 release-candidate pipeline]
B -->|main-v2| D[注入 v2-contract-validator]
B -->|develop| E[运行 quick-test suite]
C --> F[签署并归档]
D --> G[生成兼容性报告]
E --> H[实时覆盖率反馈]
3.2 基于go mod graph的依赖变更自动触发保护规则升级
当模块依赖图发生变更时,需实时感知并触发对应安全策略升级。核心机制基于 go mod graph 的结构化输出解析:
# 生成当前模块的完整依赖有向图(含版本)
go mod graph | grep "github.com/org/pkg@v1\."
该命令输出形如 main@v0.0.0 github.com/org/pkg@v1.2.3 的边关系,可作为依赖变更的原子信号源。
依赖变更检测流程
- 每次 CI 构建前执行
go mod graph快照比对 - 差异项经白名单过滤后,映射至预定义的规则集(如
CWE-798对应golang.org/x/crypto/bcrypt升级)
规则升级决策表
| 依赖包 | 风险等级 | 触发动作 | 最低安全版本 |
|---|---|---|---|
| golang.org/x/text | HIGH | 强制升级 + 扫描 | v0.14.0 |
| github.com/gorilla/mux | MEDIUM | 警告 + 人工复核 | v1.8.0 |
graph TD
A[go mod graph] --> B[解析边关系]
B --> C{是否新增高危依赖?}
C -->|是| D[加载对应保护规则模板]
C -->|否| E[跳过]
D --> F[注入版本约束与审计钩子]
3.3 GitHub Branch Protection API与go-github SDK集成实战
初始化客户端与认证
使用 github.NewTokenClient 构建带 OAuth Token 的 HTTP 客户端,确保具备 admin:org, repo 权限。
配置分支保护规则
opts := &github.ProtectionRequest{
RequiredStatusChecks: &github.RequiredStatusChecks{
Strict: true,
Contexts: []string{"ci/test", "ci/build"},
},
RequiredPullRequestReviews: &github.PullRequestReviewsEnforcement{
RequireCodeOwnerReviews: true,
RequiredApprovingReviewCount: 2,
},
EnforceAdmins: &github.EnforceAdmins{Enabled: true},
}
该结构体映射 GitHub REST API /repos/{owner}/{repo}/branches/{branch}/protection 的完整 payload。Strict 控制合并前是否强制通过所有状态检查;Contexts 指定 CI 系统上报的检查名称;RequiredApprovingReviewCount 设定最小批准数。
触发保护策略更新
调用 client.Repositories.UpdateBranchProtection() 提交配置,失败时需捕获 *github.ErrorResponse 判断 404(仓库/分支不存在)或 403(权限不足)。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
Strict |
bool | 否 | 强制状态检查通过后才可合并 |
Contexts |
[]string | 否 | CI 检查上下文名列表 |
RequireCodeOwnerReviews |
bool | 否 | 是否要求代码所有者评审 |
graph TD
A[Go程序] --> B[构造ProtectionRequest]
B --> C[调用UpdateBranchProtection]
C --> D{HTTP 200?}
D -->|是| E[分支保护生效]
D -->|否| F[解析ErrorResponse]
第四章:自动化安全工具(Automated Security Tools)集成方案
4.1 静态分析:gosec + staticcheck + govulncheck的CI流水线编排
在Go项目CI中,三工具协同可覆盖安全、规范与漏洞维度:
gosec:检测硬编码密钥、不安全函数调用(如http.ListenAndServe未启用TLS)staticcheck:识别死代码、错误的并发模式、低效类型转换govulncheck:基于Go中心漏洞数据库(GOVULNDB)实时扫描已知CVE
流水线执行顺序
# .github/workflows/static-analysis.yml
- name: Run static analysis
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
go install honnef.co/go/tools/cmd/staticcheck@latest
go install golang.org/x/vuln/cmd/govulncheck@latest
# 并行扫描,失败即中断
gosec -fmt=json -out=gosec.json ./... && \
staticcheck -checks=all -exclude=ST1005 ./... && \
govulncheck -json ./...
-fmt=json统一输出便于后续解析;./...递归扫描全部包;&&确保短路执行。
工具能力对比
| 工具 | 检测重点 | 实时性 | 依赖更新 |
|---|---|---|---|
| gosec | 安全反模式 | 高 | 无需手动更新 |
| staticcheck | 代码质量与正确性 | 中 | @latest自动拉取 |
| govulncheck | CVE级漏洞 | 依赖GOVULNDB同步 | 每日自动更新 |
graph TD
A[源码提交] --> B[gosec扫描]
A --> C[staticcheck扫描]
A --> D[govulncheck扫描]
B & C & D --> E[聚合报告 → GitHub Annotations]
4.2 依赖扫描:trivy-go + syft + GitHub Dependency Graph三重校验
现代软件供应链安全需多源交叉验证。单一工具易漏报(如仅静态解析忽略构建时注入)或误报(如未区分开发/生产依赖)。
三重校验逻辑
- trivy-go:深度扫描 Go 模块的
go.sum和go.mod,识别已知 CVE; - syft:生成 SBOM(SPDX/ CycloneDX),覆盖二进制嵌入依赖;
- GitHub Dependency Graph:实时同步仓库
go.mod及 PR 变更,提供上下文感知依赖关系。
数据同步机制
# 同步 GitHub Dependency Graph 数据(需 GitHub App 权限)
curl -H "Authorization: Bearer $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.hawkgirl-preview+json" \
https://api.github.com/repos/org/repo/dependency-graph/sbom
该 API 返回标准化 SPDX SBOM,用于比对 trivy/syft 输出差异项,自动标记“仅 GitHub 检出”或“仅 syft 检出”的依赖路径。
| 工具 | 覆盖维度 | 实时性 | 优势场景 |
|---|---|---|---|
| trivy-go | CVE + license | 高 | 安全漏洞优先级排序 |
| syft | 构建产物 SBOM | 中 | 容器镜像/离线环境审计 |
| GitHub DG | 仓库级依赖拓扑 | 秒级 | PR 级细粒度影响分析 |
graph TD
A[go.mod/go.sum] --> B(trivy-go)
C[编译后二进制] --> D(syft)
E[GitHub 仓库] --> F(GitHub Dependency Graph)
B & D & F --> G[差异聚合引擎]
G --> H[统一告警看板]
4.3 模糊测试:go-fuzz与afl++在Go核心包中的靶向注入实践
模糊测试是验证 Go 标准库鲁棒性的关键手段。以 net/http 包的 ParseHTTPVersion 函数为例,可构造精准语料进行靶向注入:
func FuzzParseHTTPVersion(f *testing.F) {
f.Add("HTTP/1.1")
f.Fuzz(func(t *testing.T, input string) {
_, err := http.ParseHTTPVersion(input)
if err != nil && !strings.Contains(err.Error(), "invalid") {
t.Fatalf("unexpected error: %v", err)
}
})
}
该测试利用 Go 内置 fuzzing 框架,f.Add() 提供种子,f.Fuzz() 启动变异循环;参数 input 由 go-fuzz 自动变异生成,覆盖边界值(如 "HTTP/0.9"、"HTT P/1.1")。
| 工具 | 适用场景 | Go 原生支持 | 靶向能力 |
|---|---|---|---|
| go-fuzz | 纯 Go 代码 | ✅ | 高(函数级) |
| afl++ (with goffi) | 混合编译型目标 | ❌(需插桩) | 中(需符号化入口) |
graph TD
A[初始种子] --> B[go-fuzz 变异引擎]
B --> C[编译为 instrumented binary]
C --> D[覆盖率反馈驱动]
D --> E[发现 panic / crash]
4.4 安全门禁:基于Scorecard结果动态阻断PR合并的Policy-as-Code实现
当 GitHub Scorecard 扫描完成,其 JSON 报告需实时驱动合并策略。核心是将合规性评估转化为可执行的准入策略。
数据同步机制
Scorecard 结果通过 Webhook 推送至 Policy Engine(如 Open Policy Agent),或由 CI 触发拉取:
# .github/workflows/policy-check.yaml
- name: Fetch Scorecard Result
run: |
curl -s "https://api.securityscorecards.dev/projects/github.com/$ORG/$REPO" \
-H "Accept: application/json" > scorecard.json
此步骤获取权威、不可篡改的 Scorecard v4.3+ 原始数据;
$ORG和$REPO由上下文注入,确保租户隔离。
策略决策流
graph TD
A[PR 提交] --> B{Scorecard API 调用}
B --> C[解析 critical/low_score 指标]
C --> D[OPA evaluate policy.rego]
D -->|deny if score < 70| E[拒绝合并]
D -->|allow if all checks pass| F[批准合并]
策略规则示例
| 检查项 | 阈值 | 阻断动作 |
|---|---|---|
Token-Permissions |
≥ 80 | 否则禁止合并 |
Signed-Tags |
≥ 90 | 否则标记高风险 |
# policy.rego
package github.pr
import data.scorecard
default allow := false
allow {
scorecard.token_permissions >= 80
scorecard.signed_tags >= 90
}
scorecard.token_permissions来自 JSON 中checks[i].score,单位为百分制整数;策略仅在所有关键检查达标时返回true。
第五章:从Scorecard 4.0到SLSA Level 3的演进路径
Scorecard 4.0核心检查项与SLSA Level 3能力映射
Scorecard 4.0包含18项自动化检查(如Signed-Releases、Pinned-Dependencies、Branch-Protection),其中12项直接支撑SLSA Level 3的四个支柱:出处(Provenance)、构建过程(Build Process)、依赖完整性(Dependency Integrity)和防篡改(Tamper Resistance)。例如,Code-Review检查强制PR需双人批准,对应SLSA要求“所有变更经授权团队审查”;Automated-Tests覆盖率达85%以上,则为SLSA构建可重现性提供数据基线。
某云原生CI/CD平台实战升级路径
某金融科技公司使用GitHub Actions托管Kubernetes Operator项目。初始Scorecard得分为6.2/10,主要短板在Binary-Artifacts(未验证构建产物哈希)和Vulnerability-Alerts(依赖扫描未集成至PR流水线)。团队通过三阶段改造:第一阶段启用slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml模板生成SLSA3级Provenance;第二阶段将Trivy扫描嵌入on: pull_request触发器,并绑定GitHub Dependabot;第三阶段用Cosign对容器镜像签名,签名密钥由HashiCorp Vault动态分发。升级后Scorecard得分跃升至9.4,且通过SLSA Verifier v2.3.0验证全部17项Level 3断言。
关键差距分析表
| Scorecard检查项 | 当前状态 | SLSA Level 3要求 | 解决方案 |
|---|---|---|---|
Signed-Releases |
仅Tag签名,无二进制签名 | 所有发布产物需独立签名 | 改用cosign sign-blob --key $KEY_PATH ./dist/app-linux-amd64 |
Fuzzing |
未启用 | 构建流程需集成模糊测试 | 在build-and-test job中插入- name: Run go-fuzz<br> run: go install github.com/dvyukov/go-fuzz/go-fuzz@latest && go-fuzz -bin=./fuzz.zip -workdir=fuzz-corpus |
构建环境加固实践
SLSA Level 3强制要求“隔离、不可变、最小化”的构建环境。该团队废弃自建Docker-in-Docker节点,转而采用GitHub-hosted runners + 自定义container image(基于cgr.dev/chainguard/wolfi-base:latest),该镜像仅含glibc、curl、git及Go 1.22,体积actions/checkout@v4配合persist-credentials: false禁用Git凭据继承,并在post:钩子中执行rm -rf $GITHUB_WORKSPACE/.git清除元数据。
flowchart LR
A[Scorecard 4.0扫描] --> B{是否通过12项SLSA映射检查?}
B -->|否| C[自动触发修复流水线:<br>- 注入SLSA Provenance生成步骤<br>- 启用Cosign密钥轮换策略]
B -->|是| D[调用slsa-verifier verify-artifact<br> --provenance provenance.intoto.jsonl<br> --source github.com/org/repo]
C --> E[重新提交PR并标记\"slsa-fix/\"
供应链透明度增强
团队将SLSA Provenance JSONL文件同步至专用Blob存储(Azure Blob Storage),设置SAS Token有效期为72小时,并在每次Release时向Slack频道推送结构化卡片,包含:构建时间戳、Git commit SHA、SLSA level、验证结果链接及cosign verify命令示例。运维团队通过curl -s https://blob.core.windows.net/provenance/2024.08.15.jsonl | jq '.predicate.buildDefinition'实时审计构建定义一致性。
审计日志留存机制
所有SLSA验证操作均写入OpenTelemetry Collector,采样率100%,字段包含slsa_level, verifier_version, provenance_hash, signature_status。日志经Fluent Bit过滤后持久化至Elasticsearch集群,保留周期365天,支持按repository_name和build_timestamp范围查询。审计人员可通过Kibana仪表盘查看过去30天SLSA验证失败TOP5原因分布,其中invalid-signature占比达63%,推动团队将Cosign密钥轮换周期从90天缩短至30天。
工具链版本锁定清单
- GitHub Actions Runner: 2.315.0(固定patch版本,禁用自动升级)
- Cosign: v2.2.1(SHA256:
a1b2c3...f8e9d0) - SLSA Verifier: v2.3.0(通过
go install github.com/slsa-framework/slsa-verifier/cmd/slsa-verifier@v2.3.0安装) - Trivy: v0.45.0(Docker镜像tag精确指定,非
latest)
持续验证闭环设计
每日凌晨2点触发Cron Job,遍历所有已发布release tag,执行slsa-verifier verify-artifact并比对历史Provenance哈希。若发现哈希漂移,自动创建GitHub Issue并@security-team,Issue模板预填curl -s https://api.github.com/repos/{org}/{repo}/releases/tags/{tag} | jq '.assets[].browser_download_url'用于快速定位异常产物。
