使用 Syft + Grype 生成镜像 SBOM 并扫描高危 CVE

解读

在国内金融、运营商、政务云等合规场景,“上线前必须提供 SBOM 与漏洞报告” 已写入《关基保护要求》《等保 2.0》等行业细则。面试官想确认你是否能把“镜像安全”做成一条可落地、可审计、可闭环的流水线,而不仅是跑两条命令。因此,回答要覆盖:

  1. 如何在不触碰生产镜像的前提下,离线生成 SBOM
  2. 如何精准过滤误报(国内源补丁滞后、私有补丁、自研 RPM 常见);
  3. 如何把结果自动回写至内部 CMDB 或 Jira,实现缺陷追踪;
  4. 如何在 CI 阶段卡点高危 CVE,但给业务留“白名单”通道。

知识点

  • Syft 与 Grype 的底层逻辑:Syft 通过文件系统层扫描、包管理器元数据、二进制指纹三通道生成 SBOM(支持 CycloneDX/SPDX 两种国内监管认可格式);Grype 把 SBOM 与国内加速漏洞库(如阿里云 NVD 镜像、清华源)做匹配,输出 CVSS≥7.0 的高危条目。
  • 多阶段构建与 SBOM 一致性:构建阶段使用 docker buildx --sbom=true 可直接把 SBOM 写进镜像 OCI 索引,但国内 registry 普遍版本低,需降级到sidecar json 文件方式。
  • 误报过滤机制:利用 Grype 的 .grype.yaml 配置 ignore: 规则,把CentOS 7 官方 backport 补丁、自研 so 文件、内部 JDK 版本加入白名单;同时把**国家信息安全漏洞共享平台(CNVD)**编号写入 match-by-cve: 实现双重校验。
  • 离线场景:在信创隔离区,提前用 grype db update --from-file 把漏洞库通过光盘摆渡导入,保证每日增量。
  • CI 集成示例:GitLab-CI 中 only: - merge_requests 阶段运行 syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -o cyclonedx-json > sbom.jsongrype sbom:sbom.json --fail-on high高危漏洞直接阻断 MR,但允许通过 GRYPE_IGNORE_FILE 变量提白单。
  • 合规输出:最终把 CycloneDX 文件上传至内部 Sonatype Nexus IQ Server,生成中文 PDF 报告,含镜像摘要、漏洞等级分布、修复建议,满足证监会《金融科技产品认证》现场检查要求。

答案

  1. 本地一次性准备

    # 安装国内加速版本
    curl -sSfL https://mirrors.aliyun.com/homebrew/install.sh | bash
    brew install syft grype
    # 初始化漏洞库(离线场景可跳过)
    grype db update
    
  2. 生成 SBOM(不运行容器,避免引入运行时污染)

    syft redis:7.0-alpine -o cyclonedx-json --file redis70.sbom.json
    
  3. 扫描并只留高危

    grype sbom:redis70.sbom.json --fail-on high -o template -t \
    "{{range .Matches}}{{if ge .Vulnerability.CvssScore 7.0}}{{.Vulnerability.ID}} {{.Artifact.Name}} {{.Artifact.Version}} {{.Vulnerability.Fix.State}}{{end}}{{"\n"}}{{end}}" \
    > high.list
    
  4. 误报过滤
    在项目根目录放置 .grype.yaml

    ignore:
      - vulnerability: CVE-2023-XXXX
        fix-state: wont-fix
        package:
          name: busybox
          version: 1.35.0-r15
    

    再次运行 grype sbom:redis70.sbom.json --fail-on high,若返回码为 0,则通过。

  5. 集成到 Dockerfile 构建流水线

    # 多阶段:builder 阶段编译,final 阶段最小化
    FROM golang:1.21-alpine AS builder
    COPY . /src
    RUN cd /src && go build -o app
    
    FROM alpine:3.18
    COPY --from=builder /src/app /usr/local/bin/app
    ENTRYPOINT ["app"]
    

    GitLab-CI 片段:

    security:
      stage: test
      image: docker:24-dind
      services:
        - docker:24-dind
      script:
        - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
        - syft $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -o cyclonedx-json > sbom.json
        - grype sbom:sbom.json --fail-on high --config .grype.yaml
      artifacts:
        reports:
          cyclonedx: sbom.json
        expire_in: 1 week
      allow_failure: false
    
  6. 合规交付
    sbom.jsonhigh.list 打包成 tar.gz,通过龙芯堡垒机上传到安全审计系统,完成**“三同步”**(同步规划、同步建设、同步运行)备案。

拓展思考

  • SBOM 与零信任的联动:把 SBOM 中的每个组件哈希写入内部 ServiceMesh 的 SPIFFE ID 断言,实现“漏洞未修复即拒绝 sidecar 注入”,让安全策略下沉到网格层。
  • 国产芯片适配:在鲲鹏/飞腾机器上,Syft 的 rpm 解析器需开启 __linux_capability_version=3 才能正确识别银河麒麟 V10 SP3 的 rpm 数据库;否则会出现**“package count 0”**假阴性。
  • 红队视角:攻击者可在镜像层中植入静态编译的 go木马,不依赖包管理器,Syft 默认扫描不到;解决方法是加挂 syft scope:all-layers 并开启二进制指纹--catalogers all),但耗时增加 40%,需在夜间流水线跑全量,MR 阶段跑快速模式。