2026年的供应链安全:SBOM、Sigstore以及为何软件来源证明已不再是可选项
2020年的SolarWinds事件是一个分水岭,它将”供应链安全”从一个模糊的关注点转变为董事会的强制要求。六年后,相关工具已经足够成熟,使得大规模的软件来源验证变得切实可行。本文涵盖了现代供应链安全的三大支柱:软件物料清单(SBOM)、Sigstore签名生态系统以及SLSA框架证明。它们共同为团队提供了对”How do we know this software is what we think it is?”(我们如何知道这款软件就是我们认为的那个软件?)这个问题的可信答案。
威胁模型:供应链攻击的真实面貌
在深入了解工具之前,明确威胁的定义是值得的。供应链攻击针对的是构建和分发过程,而不是您正在运行的应用程序。攻击者的目标是将恶意代码插入到您的构建系统、注册表或包管理器将获取并信任的工件中。
攻击向量包括:被入侵的开发者账户(npm令牌盗窃)、使用名称拼写混淆的恶意包(colourama与colorama)、在编译过程中注入代码的被入侵构建系统(SolarWinds事件)、流行包的恶意维护者接管(node-ipc、event-stream)以及利用私有和公共注册表解析顺序的依赖混淆攻击。
这些攻击都不需要利用您自己代码中的漏洞。您的代码可以完美无瑕,而您依赖的库——或构建它的系统——可能已被入侵。这就是为什么传统的安全工具如此难以防御供应链攻击。
软件物料清单:了解您发布的内容
软件物料清单(SBOM)是软件工件中每个组件的机器可读清单。可以将其视为软件的营养标签:它告诉您存在哪些成分、它们的版本以及来源。
2026年主要有两种格式:
- SPDX(软件包数据交换):一个ISO标准(ISO/IEC 5962:2021),最初由Linux基金会开发。得到开源工具的广泛支持,并被许多政府采购合同所要求。
- CycloneDX:由OWASP开发,明确考虑了安全用例。除了软件包外,还支持漏洞丰富、服务依赖和硬件组件。
大多数企业在容器镜像构建时生成 SBOM。最常用的两个工具是 Syft(来自 Anchore)和 Trivy(来自 Aqua Security)。
# 使用 Syft 为容器镜像生成 CycloneDX SBOM
syft scan ghcr.io/myorg/myapp:v1.2.3 -o cyclonedx-json > sbom.json
# 生成 SPDX SBOM
syft scan ghcr.io/myorg/myapp:v1.2.3 -o spdx-json > sbom.spdx.json
# 将 SBOM 作为 OCI 引用附加到注册表中的镜像
oras attach ghcr.io/myorg/myapp:v1.2.3
--artifact-type application/vnd.cyclonedx+json
sbom.json:application/vnd.cyclonedx+json
oras attach 步骤使用 OCI Referrers API 将 SBOM 存储在注册表中与镜像一起。任何消费者都可以在部署镜像前使用 oras discover 获取并验证 SBOM。这是 SBOM 分发的 emerging 标准——将 SBOM 与其描述的工件保持在同一注册表中,并通过镜像摘要进行加密绑定。
SBOM 漏洞匹配
SBOM 本身只是一个清单。当您持续将其与漏洞数据库匹配时,其价值会倍增。Grype(同样来自 Anchore)和 Trivy 都支持此工作流:
# 将现有 SBOM 与 Grype 的漏洞数据库进行匹配
grype sbom:./sbom.json
# 输出为表格(默认)、JSON 或 GitHub Code Scanning 的 SARIF 格式
grype sbom:./sbom.json -o sarif > results.sarif
当集成到 CI 管道中时,这可以为您提供对影响现有工件的新 CVE 的持续可见性——即使您没有更改任何代码。周二在基础镜像层中发现的关键漏洞会影响您周一构建的容器,而基于 SBOM 的扫描可以在不要求重建的情况下捕获到它。
Sigstore:大规模的无密钥代码签名
传统的代码签名需要管理长期存在的私钥——生成它们、在 HSM 中保护它们、向验证者分发公钥,以及在密钥泄露时撤销它们。这种运营负担是为什么大多数开源软件包历史上都是未签名的。Sigstore 通过绑定到短期 OIDC 身份令牌的临时签名密钥完全消除了密钥管理问题。
Sigstore 生态系统由三个核心组件组成:
Cosign
Cosign 是用于签名和验证容器镜像及其他 OCI 工件的 CLI 工具。在无密钥模式下,它会向 OIDC 提供程序(GitHub Actions、Google、Microsoft 或任何 OIDC 兼容身份)进行身份验证,获取临时密钥对,并在对工件进行签名之前立即将签名证书提交给 Rekor(透明日志)。
# 在 GitHub Actions 工作流中对容器镜像进行签名(无密钥)
- name: 签名容器镜像
uses: sigstore/cosign-installer@v3
- name: 签名
run: |
cosign sign --yes
ghcr.io/${{ github.repository }}@${{ steps.build.outputs.digest }}
env:
COSIGN_EXPERIMENTAL: 1
# 验证已签名的镜像 — 检查身份和 OIDC 签发者
cosign verify
--certificate-identity "https://github.com/myorg/myrepo/.github/workflows/release.yml@refs/heads/main"
--certificate-oidc-issuer "https://token.actions.githubusercontent.com"
ghcr.io/myorg/myapp@sha256:abc123...
验证步骤会检查签名是否由特定仓库路径上的特定分支的 GitHub Actions 工作流生成 — 而不仅仅是”某个 CI 系统”。这种特定性正是使 Sigstore 验证对供应链安全有意义的原因。
Rekor:防篡改的透明日志
Rekor 是一个仅附加的透明日志,用于软件供应链工件,其设计类似于 TLS 证书的证书透明度。每个 Sigstore 签名操作都会向 Rekor 添加一个日志条目,并且该日志作为 Merkle 树维护。这意味着:
- 每个签名都可以被公开审计 — 您可以搜索 Rekor 查找为特定工件摘要创建的所有签名。
- 条目无法被删除或追溯修改,否则会使所有后续哈希失效。
- 验证器可以检测他们是否看到与其他验证器不同的日志视图(一致性证明)。
# 搜索 Rekor 中特定工件哈希的所有日志条目
rekor-cli search --sha sha256:abc123def456...
# 获取完整的日志条目,包括签名证书
rekor-cli get --uuid <uuid-from-search> --format json | jq .
Fulcio:短期证书颁发机构
Fulcio 颁发 Cosign 用于临时签名的短期 X.509 证书。它验证 OIDC 身份令牌并将已验证的身份(GitHub Actions 工作流 URL、电子邮件地址、服务账户)嵌入到证书的主题备用名称中。这些证书的有效期为 10 分钟 — 足够长以完成签名操作,又足够短以至于在过期前泄露的证书是无用的。
SLSA:软件工件供应链级别框架
SLSA(发音为”salsa”)是一个安全要求框架,旨在防止在整个软件供应链中发生篡改——从源代码到构建系统,再到分发制品。它由谷歌开发,现在是 CNCF 的一个项目。SLSA 定义了四个严格程度递增的级别:
- SLSA 1:构建过程有文档记录并脚本化。生成出处(关于制品如何构建的元数据),即使未经认证。
- SLSA 2:构建使用版本控制的构建服务。出处由构建服务进行认证。
- SLSA 3:构建在强化、隔离的构建环境中运行。出处无法被构建服务本身伪造。
- SLSA 4:所有代码更改需要两人审核。密封的、可复现的构建。当前最高保证级别,需要自定义构建基础设施。
GitHub Actions、Google Cloud Build 和 Tekton Chains 都支持在级别 1-3 下开箱即生成符合 SLSA 标准的出处证明。
# GitHub Actions: 为容器镜像生成 SLSA 3 级别出处
jobs:
build:
uses: slsa-framework/slsa-github-generator/.github/workflows/container_workflow.yml@v2.0.0
with:
image: ghcr.io/myorg/myapp
digest: ${{ needs.release.outputs.digest }}
secrets:
registry-username: ${{ github.actor }}
registry-password: ${{ secrets.GITHUB_TOKEN }}
可重用工作流会生成签名的出处证明并将其附加到注册表中的镜像上。证明是一个遵循 in-toto 证明框架格式的 JSON 文档,记录了构建者身份、源代码仓库、git 提交哈希和构建参数。
整合应用:实用的供应链安全流水线
2026 年的一个完整供应链安全流水线结合了这三个要素。以下是生产容器镜像构建的流程:
- 构建: 在隔离的临时构建环境中编译应用程序(GitHub 托管的运行器或具有网络出口限制的专用构建集群)。
- 生成 SBOM: 对输出镜像运行 Syft 以生成 CycloneDX SBOM。
- 扫描 SBOM: 对 SBOM 运行 Grype 以检查已知漏洞。在发现关键 CVE 时使构建失败。
- 签名镜像: 使用 Cosign 的无密钥模式对镜像摘要进行签名。签名证书绑定到 GitHub Actions 工作流身份。
- 附加 SBOM: 将 SBOM 作为 OCI 引用者附加到注册表中的镜像,并同样使用 Cosign 对附件进行签名。
- 生成出处证明: 使用 SLSA GitHub Actions 生成器生成符合 SLSA 3 的签名出处证明。
- 部署时验证: 准入 Webhook(使用 Sigstore 的 Policy Controller 或 Kyverno)验证签名,确认 SBOM 存在,并检查出处证明是否符合 SLSA 2+,然后才允许 Pod 调度。
# Kyverno 策略:部署前要求 Sigstore 签名
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: check-image-signature
match:
any:
- resources:
kinds: [Pod]
verifyImages:
- imageReferences:
- "ghcr.io/myorg/*"
attestors:
- entries:
- keyless:
subject: "https://github.com/myorg/*/.github/workflows/*.yml@refs/heads/main"
issuer: "https://token.actions.githubusercontent.com"
rekor:
url: https://rekor.sigstore.dev
VEX:沟通漏洞可利用性
基于 SBOM 的漏洞扫描的一个实际挑战是警报疲劳。典型的容器镜像的 SBOM 可能会匹配 50-200 个 CVE,其中绝大多数要么在您的上下文中不可利用(易受攻击的代码路径永远不会被执行),要么已经得到缓解(易受攻击的组件存在,但实践中该软件包并非受影响的版本)。
VEX(漏洞可利用性交换)文档让维护者能够针对其工件特定版本沟通特定 CVE 的可利用性状态。VEX 声明可以断言某个 CVE 是”不受影响”(附带理由如”易受攻击的代码不在执行路径中”)、”受影响”、”已修复”或”正在调查中”。CycloneDX 和 SPDX 都支持嵌入 VEX 声明,而 OpenVEX 是一种新兴的独立格式。
# 使用 vexctl 生成 VEX 文档
vexctl create
--product "pkg:oci/myapp@sha256:abc123"
--vuln CVE-2024-12345
--status not_affected
--justification "vulnerable_code_not_in_execute_path"
> myapp.vex.json
像 Grype 这样的扫描器可以消费 VEX 文档来过滤其输出,大幅减少警报噪音,同时不会隐藏真正的风险。
合规性和监管背景
对于从事美国联邦合同的团队,NIST SP 800-204D 和行政命令 14028 要求向联邦机构提供的软件生成 SBOM。CISA 已发布了最低 SBOM 元素要求(供应商名称、组件名称、版本、组件哈希、依赖关系、SBOM 作者和时间戳)。
将于 2026-2027 年生效的欧盟网络安全韧性法案,对在欧盟销售的具有数字元素的产品提出了类似要求。满足 SLSA 2+ 并生成 SPDX 或 CycloneDX SBOM 的供应链安全工具满足这两个监管框架中的技术文档要求。
结论
供应链安全不再是政府承包商的利基关注点。SBOM 生成、Sigstore 无密钥签名和 SLSA 来源证明的结合,为每个工程团队提供了回答”我们如何知道这个软件是我们认为的那个软件?”这个问题的工具——而无需管理签名密钥或构建自定义工具的操作负担。从在镜像构建管道中生成 SBOM 开始,添加带有 GitHub Actions OIDC 集成的 Cosign 签名,并通过准入策略在部署时逐步强制执行验证。生态系统已经足够成熟,如今可以在标准 CI/CD 管道中完成所有这些工作。
