软件供应链安全入门:学习什么以及使用哪些工具进行验证

软件供应链安全不仅仅是检查自己编写的代码。它关乎管理代码成为产品并到达运行环境的所有环节的信任,包括外部库、构建服务器、CI/CD工作流、容器镜像、注册表和部署策略。

因此,仅仅引入一个漏洞扫描器并不能解决问题。你需要列出引入了什么,证明是谁在什么环境下构建的,阻止未经批准的产物被部署,并在出现问题时快速追踪影响。本文将这一流程与学习顺序和小型实践项目相结合。

源代码和依赖项通过构建、签名和注册表验证安全部署的软件供应链

首先纠正一个误解:供应链安全并非漏洞扫描

查找Log4Shell等已知漏洞库固然重要。但是,如果合法库的发布账户被盗用,开发者安装了名称相似的恶意软件包,或者构建阶段的产物被篡改,仅凭CVE列表将难以发现。

NIST将网络安全供应链风险管理(C-SCRM)描述为在设计、开发、部署、获取、运营和处置等整个生命周期中识别、评估和缓解风险的活动。具体到软件,以下五个问题是核心:

  1. 包含了什么? 你是否了解直接和间接依赖项以及许可证?
  2. 它来自哪里? 你能否追溯源代码、软件包、基础镜像和供应商?
  3. 它是如何构建的? 你能否证明构建过程和输入?
  4. 是否被篡改? 你是否在部署前验证产物的签名和摘要?
  5. 如果出现问题能否找到? 你能否快速识别受影响的服务和部署版本?

首先描绘整体流程

供应链流程为:源代码 → 依赖项 → 构建 → 产物 → 注册表 → 部署。每个阶段都需要不同的证据。

阶段 主要风险 需保留的证据 主要控制措施
— — — —
源代码 账户盗用,未经授权的修改 提交和审查记录 分支保护,MFA,CODEOWNERS
依赖项 恶意软件包,依赖混淆 Lockfile,SBOM 版本锁定,私有注册表优先级
构建 CI权限滥用,构建中篡改 构建日志,溯源信息 隔离构建,最小权限,工作流锁定
产物 镜像替换,标签重用 摘要,签名,证明 Cosign签名·验证
部署 未经授权的镜像执行 批准·策略日志 准入策略,摘要部署
运营 迟发现的漏洞 部署版本与SBOM关联 重新扫描,VEX,影响分析

SBOM(软件物料清单)是软件中包含的组件列表。SPDX和CycloneDX是其代表性格式。Provenance是解释“此产物是由何种源代码和构建过程创建的”的证明材料。两者并非替代关系。如果说SBOM是成分表,那么Provenance更像是制造历史。

应该学习什么以及按什么顺序学习

第一阶段:依赖图和信任边界

首先,理解直接依赖和传递依赖的区别、包仓库的优先级以及Lockfile的作用。npm、PyPI、Maven等公共仓库与内部仓库的交汇点是重要的信任边界。即使固定了版本,也可能固定了一个已经恶意的版本,因此“固定了就安全”的结论是不可取的。

第二阶段:SBOM和漏洞信息

分别从源代码目录和最终容器镜像生成SBOM,并比较其差异。Syft可以识别目录、镜像和归档中的组件,并以SPDX或CycloneDX格式导出。Grype、Trivy和OSV-Scanner可用于将这些组件与已知漏洞信息进行比对。

扫描结果并非判决书,而是调查清单。你需要确认它们是否到达执行路径,是否实际包含在部署镜像中,以及是否存在补充控制措施。对于例外情况,应记录负责人、原因和到期日期。

第三阶段:构建完整性和SLSA

SLSA(软件产物供应链级别)是一个逐步提高供应链保障的规范。截至2026年9月,已批准的SLSA 1.2构建轨道将保障级别分为:溯源信息存在、由托管构建平台生成的签名溯源信息以及强化的构建环境。

与其一开始就声明最高级别,不如确定“需要何种级别的证据来阻止何种威胁”。这也是为什么不应允许应用程序在CI中随意生成关于自身的证明,以及为什么应由可信的构建控制层生成溯源信息的原因。

第四阶段:签名和验证

Sigstore的Cosign用于OCI镜像和其他产物的签名·验证以及证明工作。重要的是验证策略,而非仅仅签名命令。如果在部署阶段不检查可信的发行者、OIDC颁发者、仓库和工作流条件,即使有签名文件,也无法实现批准控制。

在运营中,应以镜像摘要(Digest)而非可变标签为基准进行部署,并在签名验证失败时拒绝执行。对于Kubernetes,可以将Kyverno或OPA Gatekeeper等策略引擎连接到部署网关。

第五阶段:CI/CD和响应流程

工作流令牌应以默认读取权限开始,并仅为必要任务授予写入权限。外部CI操作应固定到已审查的提交SHA,而非可变标签,并尽可能使用短期凭证而非长期密钥。

最后一个学习主题是事件响应。当发现新的CVE或恶意软件包时,应练习使用SBOM查找受影响的产品和部署版本,创建修复构建,验证新的签名和溯源信息,然后重新部署的过程。

按角色选择工具

目的 工具·标准 擅长 注意事项
— — — —
SBOM生成 Syft, Trivy 列出目录·镜像中的组件 需验证是否遗漏及生成时间
SBOM格式 SPDX, CycloneDX 组织·工具间可交换的表示 若仅创建而不保存,则作用不大
漏洞检测 Grype, Trivy, OSV-Scanner 匹配软件包与已知漏洞 可执行性·环境上下文需单独判断
仓库卫生 OpenSSF Scorecard 分支保护、令牌权限等启发式检查 不应仅凭总分判断安全性
签名·验证 Sigstore Cosign OCI产物签名和基于身份的验证 部署点的验证策略也必不可少
构建证明 SLSA, in-toto 构建输入·过程·产物的溯源信息和证明 区分声明与实际构建平台保障
部署策略 Kyverno, OPA Gatekeeper 阻止未签名·违反策略的产物 需要紧急例外程序和审计日志

最好不要试图用一个产品来填满整个表格。例如,即使Trivy支持多种扫描,它也无法自动解决SBOM标准、构建溯源信息和签名信任策略等问题。

4周实践项目:从头到尾保护一个小型容器

对于学习项目,一个API和一个容器镜像就足够了。目标不是安装大量工具,而是逐一添加可验证的证据和拦截点。

第1周:建立基线

  • 在一张图上绘制应用程序的源代码、包仓库、CI、注册表和部署环境。
  • 记录直接和传递依赖项以及基础镜像。
  • 检查分支保护、审查规则、CI令牌权限以及外部操作是否固定。
  • 完成标准:能够解释任意更改通过何种路径到达生产镜像。

第2周:SBOM和漏洞门禁

  • 分别使用Syft或Trivy为源代码和最终镜像生成SBOM。
  • 使用Grype、Trivy或OSV-Scanner扫描结果。
  • 不要只看严重性;记录实际包含情况、可达性、修复版本和例外到期日期。
  • 完成标准:输入特定软件包后,能够找到该软件包已部署到哪些镜像和服务。

第3周:签名和溯源信息

  • 通过摘要(Digest)而非标签识别镜像。
  • 使用Cosign对CI创建的镜像进行签名,并在单独的验证步骤中检查发行者条件。
  • 保存描述构建输入和构建器的SLSA Provenance或in-toto Attestation。
  • 完成标准:本地随意创建的同名镜像无法通过验证。

第4周:部署拦截和事故演练

  • 在测试Kubernetes集群中应用拒绝未签名镜像的策略。
  • 部署三种类型的镜像:正常镜像、未签名镜像和签名后被篡改的镜像,并比较结果。
  • 假设一个新的漏洞软件包被公布,并计时从影响查询到修复、重新签名和重新部署的整个过程。
  • 完成标准:拦截日志和批准例外以可审计的形式保留。

实践应在单独的测试仓库和集群中进行。不要将秘密或内部SBOM上传到公共注册表,并且自动修复命令可能会在不受信任的项目中执行软件包安装脚本,因此请务必先验证其行为。

CI流水线中应包含的最小门禁

소스 검증
  → 의존성 설치와 테스트
  → 이미지 빌드
  → SBOM 생성
  → 취약점 정책 평가
  → 이미지 Digest 확정
  → 서명·Provenance 발행
  → 배포 전 신원·서명 검증
  → 승인된 Digest만 배포

如果将所有扫描失败都转化为构建失败,可能会导致例外泛滥。反之,如果只堆积警告,则不能称之为门禁。例如,应将组织风险标准转化为机器可判定的规则,如“阻止已确认可利用的严重漏洞,其余则通过有时限的例外工单进行管理”。

常见的失败方式

  • 只创建一次SBOM。 如果不与部署版本关联,后期难以追踪影响。
  • 只相信扫描器分数。 软件包来源、构建篡改和账户盗用需要单独的控制措施。
  • 信任镜像标签。 标签可能会改变,因此需要摘要(Digest)和签名验证。
  • 授予CI广泛权限。 构建系统是供应链中的强大枢纽,因此最小权限和隔离至关重要。
  • 只签名不验证。 如果没有策略执行点,签名就只是参考资料。
  • 例外没有到期日期。 临时允许会固化为永久策略。

现实的起点

供应链安全的第一个目标不是“完美的产品”,而是能够证明哪些源代码和依赖项经过了哪些构建,目前部署在哪里。在此基础上,依次添加漏洞响应、签名验证和部署拦截。

本周,选择一个服务,为其源代码和最终镜像创建SBOM并比较差异。下周,固定同一镜像的摘要(Digest)并附加签名验证。最后,确认未签名镜像在实际部署阶段是否被拒绝。当这三个步骤连接起来时,供应链安全将不再是抽象的口号,而是一个可重复的工程流程。

官方参考资料

类别: 通用IT/IT安全

标签: 供应链安全, 软件供应链, SBOM, SLSA, Sigstore, Cosign, DevSecOps


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注