为什么这事变重要了

最近几年的几起公开事件让"软件供应链安全"从合规话题变成工程话题:

  • 2020 SolarWinds:构建系统被入侵,向客户分发的更新里带了后门
  • 2021 log4j (Log4Shell):一个 Java 日志库的远程代码执行漏洞,全球应急
  • 2024 xz-utils:Linux 核心压缩库被植入后门,差一步就进入主流发行版稳定版

共同点:你信任的基础组件被攻击 → 你的服务也跟着挂。

攻击面有哪些

应用代码         (有 SCA / SAST 扫)
   ↓ 依赖
开源库            (npm / pypi / maven 投毒)
   ↓ 打包
镜像 / 制品       (base image / 中间层漏洞)
   ↓ 构建系统
CI/CD             (pipeline 凭据 / 注入)
   ↓ 分发
Registry / Mirror (镜像被替换 / Tag 漂移)
   ↓ 运行
集群运行时        (特权容器 / 逃逸)

每一层都有专门的工具和实践。本篇覆盖应用→镜像层

SBOM:软件物料清单

"你的服务里到底用了哪些依赖、各是什么版本?"

SBOM(Software Bill of Materials)就是这张清单。两种主流格式:

  • CycloneDX(OWASP)
  • SPDX(Linux Foundation)

生成工具:

# Syft(Anchore 出品,支持镜像 / 文件系统 / 仓库)
syft ghcr.io/me/myapp:1.4.2 -o cyclonedx-json > sbom.json

# 或 Trivy 也能生成
trivy image --format cyclonedx ghcr.io/me/myapp:1.4.2

有了 SBOM,新 CVE 出来时一秒能查"我们中招没"——log4j 那年没 SBOM 的公司全员加班几周。

漏洞扫描

主流工具:

工具 类型 备注
Trivy 镜像 + 文件系统 + Git 仓库 开源,社区活跃
Grype 镜像 + SBOM 输入 开源,搭配 Syft
Snyk 依赖 + 镜像 + IaC 商业 + 免费档
Dependabot(GitHub) 依赖 PR 仓库自带,免费
Renovate 依赖 PR 开源,更可定制

CI 里跑(GitHub Actions 例):

- uses: aquasecurity/trivy-action@master
  with:
    image-ref: ghcr.io/me/myapp:${{ github.sha }}
    severity: CRITICAL,HIGH
    exit-code: 1

发现 Critical/High 漏洞 → 流水线失败。

镜像签名:Sigstore + cosign

镜像被改了或被中间人替换 → 你拿到的不是你以为的那个。签名确保镜像出自可信源。

# Sigstore cosign(Linux Foundation 项目)
cosign sign ghcr.io/me/myapp:1.4.2
cosign verify --certificate-identity ... ghcr.io/me/myapp:1.4.2

K8s 部署时校验签名(用 [Cosign Policy Controller / Kyverno / OPA Gatekeeper]):未签名镜像直接拒绝调度。

SLSA:完整供应链框架

SLSA(Supply-chain Levels for Software Artifacts,发音 "salsa")由 Google 主导,OpenSSF 维护,定义 4 个等级:

L1:构建过程有文档记录
L2:使用版本化构建脚本 + 来源(provenance)记录
L3:构建在受隔离环境,凭据不可访问
L4:双人审核 + 可重现构建(最高)

中小公司先到 L2 就有显著提升——大多数被攻击的故事到不了 L2。

生产可执行的几条最低实践

  1. CI 跑 Trivy 扫描,high/critical 阻断
  2. 每次构建生成 SBOM 存档
  3. 签名 + K8s admission 校验签名(Sigstore Policy Controller)
  4. 依赖升级自动化(Dependabot / Renovate)
  5. 基础镜像选官方且小(distroless / chainguard images)
  6. 私有 registry 配置 image pull policy: Always + 用 digest 锁定

反模式

  • base image 选 latest:今天 OK 明天有 CVE 你都不知道
  • CI 装一堆 npm 包不锁版本:lockfile 的存在就是为了防这事
  • 生产部署用 :latest tag:没有可重现性
  • 扫描结果有但没人看:CI 红了开 jira 单 → 半年没人动

推荐阅读

下一篇:IAM 与最小权限——访问控制的基础。