饮墨

子安饮墨馀三斗,留与卿儿作赋来

4 步用 Trivy 构建容器镜像安全扫描流水线,CI/CD 中拦截 90% 已知漏洞

痛点:镜像上线了才发现有高危漏洞

你一定遇到过这种场景:业务镜像推到生产环境后,安全团队扫出一堆 CVE,紧急回滚、重新构建、再上线,一来一回半天没了。

问题根源很清楚——安全扫描没有左移到 CI/CD 流水线中。大多数团队的镜像构建流程是 docker build → push → deploy,中间完全没有漏洞检测环节。等到运行时才扫描,成本和风险都是最高的。

方案:Trivy + CI/CD = 自动化镜像安全门禁

Trivy 是 Aqua Security 开源的全能安全扫描器,当前最新版本 v0.69.x。它支持容器镜像、文件系统、Git 仓库、Kubernetes 集群等多种扫描目标,覆盖 OS 包漏洞、应用依赖漏洞、IaC 配置错误和密钥泄漏检测。

选 Trivy 的理由:

对比维度 Trivy Clair Snyk Container
安装复杂度 单二进制,无依赖 需部署 PostgreSQL SaaS + CLI
扫描速度(首次) ~15s ~60s ~30s
离线漏洞库 支持 不支持 不支持
开源协议 Apache 2.0 Apache 2.0 商业
IaC/密钥扫描 内置 不支持 部分支持

核心思路:在 CI 流水线的 buildpush 之间插入 Trivy 扫描环节,发现 HIGH/CRITICAL 级别漏洞直接阻断流水线,镜像不允许推送到仓库。

实操步骤

第 1 步:安装 Trivy

# 方式一:脚本安装(推荐服务器/CI Runner 使用)
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin

# 验证
trivy version

# 方式二:Docker 方式运行(无需安装)
docker run --rm aquasec/trivy:latest image alpine:3.19

第 2 步:扫描本地镜像并设置严重级别过滤

# 构建镜像
docker build -t myapp:v1.2.0 .

# 扫描,仅关注 HIGH 和 CRITICAL
trivy image --severity HIGH,CRITICAL myapp:v1.2.0

# 关键参数:--exit-code 1 表示发现漏洞返回非零退出码
# CI 流水线中用这个参数来阻断后续步骤
trivy image --severity HIGH,CRITICAL --exit-code 1 myapp:v1.2.0

输出示例:

myapp:v1.2.0 (debian 12.5)
Total: 3 (HIGH: 2, CRITICAL: 1)

┌──────────────┬────────────────┬──────────┬───────────────┬─────────────────┐
   Library     Vulnerability   Severity    Installed     Fixed Version  
├──────────────┼────────────────┼──────────┼───────────────┼─────────────────┤
 libssl3       CVE-2024-XXXXX  CRITICAL  3.0.11-1       3.0.13-1        
 curl          CVE-2024-YYYYY  HIGH      7.88.1-10+d12  7.88.1-10+d12u2 
 zlib          CVE-2024-ZZZZZ  HIGH      1:1.2.13-1     1:1.2.13-1+deb 
└──────────────┴────────────────┴──────────┴───────────────┴─────────────────┘

第 3 步:集成到 GitHub Actions 流水线

# .github/workflows/build.yml
name: Build & Security Scan

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build-and-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Run Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:${{ github.sha }}
          severity: HIGH,CRITICAL
          exit-code: '1'        # 发现高危漏洞阻断流水线
          format: table
          ignore-unfixed: true  # 忽略暂无修复版本的漏洞

      - name: Push image (仅扫描通过后执行)
        if: success()
        run: |
          docker tag myapp:${{ github.sha }} registry.example.com/myapp:${{ github.sha }}
          docker push registry.example.com/myapp:${{ github.sha }}

关键配置说明:

  • exit-code: '1' — 扫描到指定级别漏洞时返回退出码 1,阻断流水线
  • ignore-unfixed: true — 上游还没出补丁的漏洞先忽略,减少噪音
  • severity: HIGH,CRITICAL — 只关注高危和严重级别,MEDIUM/LOW 不阻断

第 4 步:生成 JSON 报告 + 配合 .trivyignore 白名单

实际项目中一定有"已知漏洞暂时无法修复"的情况,用 .trivyignore 文件管理白名单:

# .trivyignore — 白名单文件,放在项目根目录
# 格式:每行一个 CVE ID,可加注释
CVE-2024-XXXXX  # libssl 等待上游修复,预计 Q2 发布补丁
CVE-2024-YYYYY  # 内网环境不暴露此端口,风险可控

生成 JSON 格式报告用于存档或接入安全平台:

trivy image --severity HIGH,CRITICAL \
  --format json \
  --output trivy-report.json \
  --ignorefile .trivyignore \
  myapp:v1.2.0

# 用 jq 快速查看漏洞统计
cat trivy-report.json | jq '[.Results[].Vulnerabilities[]?.Severity] | group_by(.) | map({(.[0]): length}) | add'

3 个常踩的坑

坑 1:首次扫描特别慢(3-5 分钟)

Trivy 首次运行需要下载漏洞数据库(约 40MB),CI 环境中每次跑都重新下载会拖慢流水线。解决办法——缓存漏洞库:

# GitHub Actions 中缓存 Trivy DB
- uses: actions/cache@v4
  with:
    path: ~/.cache/trivy
    key: trivy-db-${{ github.run_id }}
    restore-keys: trivy-db-

坑 2:ignore-unfixed 不加导致大量误报

很多基础镜像(Debian、Ubuntu)的系统包存在上游尚未修复的 CVE。如果不加 --ignore-unfixed,扫描结果会充斥无法处理的漏洞,团队很快就会"告警疲劳"直接忽略安全报告。建议默认开启,同时定期(每月)关闭此选项做一次全量审计。

坑 3:用 latest 标签扫描结果不可复现

trivy image nginx:latest 在不同时间扫描结果可能完全不同,因为 latest 指向的镜像会变。CI 中务必使用明确的版本标签或 SHA digest:

# ✅ 正确:用 digest 固定镜像版本
trivy image nginx@sha256:a1b2c3d4e5f6...

# ❌ 错误:latest 标签无法复现
trivy image nginx:latest

总结

容器镜像安全扫描的核心思路就是左移——把安全检测从运行时提前到构建时:

  1. 安装零门槛:Trivy 单二进制部署,5 分钟接入现有 CI/CD
  2. 策略可控:通过 --severity + --exit-code 精确控制阻断级别
  3. 噪音可管.trivyignore + --ignore-unfixed 两层过滤避免告警疲劳
  4. 报告可追溯:JSON 格式输出接入安全平台,形成漏洞管理闭环

把 Trivy 扫描加到流水线里,投入不到 1 小时,但能拦截绝大多数已知漏洞进入生产环境。比起事后应急响应,这是性价比最高的安全投入。

您还没有登录,请登录后发表评论。