如何把镜像漏洞扫描真正纳入 DevSecOps 流水线?

来源:前端技术作者:下班再修头衔:程序员
导读:本期聚焦于下班再修创作的《如何把镜像漏洞扫描真正纳入 DevSecOps 流水线?》,敬请观看详情。生产环境里因为基础镜像携带高危CVE被通报,往往是最被动的安全事件之一。镜像漏洞扫描接入 DevSecOps 的核心价值不在于多出一条扫描命令,而是让每一次构建都自动生成可决策的风险数据,并在漏洞达到阈值时直接阻断发布。本文从镜像分层与漏洞传播特征讲起,分析 Trivy、Grype、Clair 等常见扫描器的差异,再以 GitLab CI 和 Trivy 为例演示如何设置扫描阶段、失败门禁和高危漏洞白名单。扫描只是前半程,后面还需要结合 SBOM 生成、基础镜像升级和漏洞跟踪形成修复闭环。读者可以照着把扫描从演示脚本变成流水线的强制卡点,避免有扫描无响应的尴尬。

容器镜像的漏洞问题往往不是业务代码引起的,而是来自基础操作系统包、语言运行时和构建阶段引入的依赖。镜像构建完成后立刻执行漏洞扫描,把结果作为后续发布的前置条件,是 DevSecOps 落地中成本较低但收益很高的一步。下面围绕扫描工具选型、CI 接入方式和修复闭环展开。

如何把镜像漏洞扫描真正纳入 DevSecOps 流水线?

一、为什么必须把扫描左移到构建阶段

镜像由多个只读层叠加而成。开发者在 Dockerfile 中写下的 FROM 指令,往往直接决定了一半以上的攻击面。像 openssl、curl、glibc、systemd 这类系统组件一旦被爆出高危漏洞,即使应用代码没有变化,已经构建好的镜像也会变成风险载体。等镜像进入生产集群后再由安全团队扫描,通常已经过去数天甚至数周,攻击窗口被拉长。

把扫描放进 CI 构建之后,可以让漏洞信息在镜像推送到仓库之前就暴露出来。流水线只需要在 build 阶段生成镜像,在 scan 阶段调用扫描器,如果高危或严重漏洞数量超过阈值就直接退出,后续 deploy 阶段不会执行。这样开发人员提交代码后几分钟内就能看到失败原因,而不是等到发布评审时才被拦截。

左移不只提升响应速度,也把安全责任从单一安全团队分散到开发团队。扫描器每次运行都基于最新漏洞库,基础镜像是否过期会在构建阶段持续暴露,团队自然会形成及时升级依赖和基础镜像的习惯。

二、常见镜像漏洞扫描工具与选型

目前开源社区比较常用的扫描器有 Trivy、Grype 和 Clair。Trivy 由 Aqua Security 维护,安装方式简单,单个二进制文件即可运行,支持容器镜像、文件系统、Git 仓库和 Terraform 等目标。它的扫描速度较快,适合嵌入 CI 流程。

Grype 来自 Anchore,常与同一团队的 Syft 配合使用。Syft 负责生成 SBOM,Grype 再基于 SBOM 做漏洞匹配。这种组合适合需要软件物料清单、且希望把扫描范围从镜像层扩展到源码依赖的场景。Clair 则是 Quay 项目背后的静态分析引擎,很多私有镜像仓库会内置 Clair 做批量扫描,适合已把 Harbor 或 Quay 作为镜像中心的团队。

工具核心优势适用场景
Trivy安装简单,扫描快,支持多目标CI 流水线、本地排查
Grype与 Syft 联动,SBOM 友好软件成分分析、细粒度清单
Clair静态分析能力强,与 Quay 和 Harbor 集成镜像仓库批量扫描

工具选型不必追求功能最全。刚开始接入时,重要的是降低使用成本,让扫描稳定跑通。Trivy 的命令行参数清晰,CI 镜像也不大,是多数团队的起点。如果后续需要统一管理多仓库镜像,可以再引入 Harbor 加 Clair 或 Trivy 的集中式扫描。

三、在 GitLab CI 中接入并配置门禁

下面以 GitLab CI 和 Trivy 为例,展示一个最精简的三阶段流水线。build 阶段负责构建并推送镜像,scan 阶段对刚构建的镜像执行漏洞扫描,只有扫描通过才会进入 deploy 阶段。扫描命令设置 --exit-code 1,当发现 HIGH 或 CRITICAL 级别漏洞时返回非零退出码,GitLab Runner 会将任务标记为失败。

stages:
  - build
  - scan
  - deploy

build_image:
  stage: build
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .

scan_image:
  stage: scan
  image: aquasec/trivy:0.50.0
  variables:
    TRIVY_DB_REPOSITORY: ghcr.io/aquasecurity/trivy-db
  script:
    - trivy image --exit-code 1 --severity HIGH,CRITICAL --no-progress $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
  allow_failure: false

deploy:
  stage: deploy
  script:
    - echo "deploy after scan passed"
  only:
    - main

这里需要注意的是 allow_failure 必须设为 false,否则漏洞扫描失败后流水线仍然会继续,门禁就形同虚设。变量 TRIVY_DB_REPOSITORY 用来指定漏洞库下载源,如果流水线运行在无法直连公网的环境,可以提前准备内网漏洞库镜像。

如果团队暂时不想让所有高危漏洞都阻断构建,可以用 --exit-code 0 先收集数据,再把结果输出为 JSON 报告。也可以使用 .trivyignore 文件精确忽略某些暂时无法修复的 CVE。

trivy image --format json --output trivy-report.json myapp:latest
trivy image --exit-code 0 --severity HIGH,CRITICAL myapp:latest

白名单文件的用法非常简单,每行写入一个 CVE 编号即可。不过白名单应当有审批记录,不能随意追加,否则扫描门禁会逐渐失效。

CVE-2023-1234
CVE-2024-5678

四、用 SBOM 和基础镜像升级形成修复闭环

扫描失败只是开始。真正有价值的工作是把漏洞清单转成可执行任务。生成 SBOM 可以让团队知道镜像里到底装了什么,漏洞落在哪个包、哪个版本上。Syft 可以直接从镜像生成 CycloneDX 或 SPDX 格式的物料清单,方便归档和审计。

syft myapp:latest -o cyclonedx-json > sbom.json

修复镜像漏洞最直接的方法是升级基础镜像。如果 Dockerfile 固定使用某个旧版本标签,即使重新构建也无法获取新的安全补丁。更推荐使用可被重新解析的标签,例如 node:20 或 debian:12-slim,并在构建时定期拉取最新补丁。

进一步的优化是采用多阶段构建和精简基础镜像。编译阶段保留完整工具链,运行阶段只复制编译产物,基础镜像切换到 distroless 或 scratch。这样既减少镜像体积,也大幅缩小可被漏洞扫描器标记的系统包数量。下面是一个 Go 服务的示例。

FROM golang:1.22 AS builder
WORKDIR /src
COPY . .
RUN go build -o app .

FROM gcr.io/distroless/base-debian12
COPY --from=builder /src/app /app
ENTRYPOINT ["/app"]

如果扫描结果中存在大量无法立即修复的漏洞,可以按严重级别设定处理时限:CRITICAL 当天处理,HIGH 一周内处理,MEDIUM 纳入版本升级计划。将 Trivy 或 Grype 的 JSON 输出接入缺陷系统,自动创建工单,也能避免漏洞清单长期无人认领。

镜像漏洞扫描接入 DevSecOps 后,构建失败率短期可能上升,但这是把原本隐藏在上线后的风险提前暴露。先卡住高危漏洞,再通过 SBOM、白名单和基础镜像升级逐步收敛,流水线会从被动检查变成团队日常开发的一部分。

镜像漏洞扫描DevSecOps容器安全修改时间:2026-09-21 18:56:52

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/0921/60164.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。