如何在 CI 阶段阻断 CVE 评分≥7.0 的镜像晋级

解读

面试官想验证三件事:

  1. 你是否把“安全左移”真正落地到CI 流水线,而不是事后补救;
  2. 能否熟练调用国产或国际主流扫描引擎(如阿里云 ACR 云原生扫描、腾讯云 TCR、Harbor Clair、Trivy、Snyk)并解析其JSON/CSV 报告
  3. 能否用零信任思路把阻断逻辑做成可灰度、可审计、可回滚的代码,而非人工拍脑袋。

知识点

  • CVE 评分体系:NVD 与 CNNVD 双源对齐,≥7.0 对应“高危”与“超危”;
  • 镜像 SBOM:OCI 标准中的 SPDX/CycloneDX 格式,用于精确匹配漏洞库;
  • 扫描时机:必须在docker build 多阶段构建之后、docker push 之前执行,避免污染 registry;
  • 国产合规要求:等保 2.0、关基条例要求高危漏洞 24h 内闭环,CI 阻断是首选手段;
  • 流水线即代码:GitLab CI、GitHub Actions、Jenkinsfile、Tekton Pipeline 均支持exit 1 阻断
  • 例外审批:通过OAS 3.0 注解Kubernetes AdmissionPolicy 实现白名单,防止业务停摆。

答案

GitLab CI + Trivy + 阿里云 ACR 为例,给出可直接落地的最小闭环:

  1. build 阶段
build:
  stage: build
  script:
    - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
    - docker save $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA -o image.tar
  artifacts:
    paths: [image.tar]
  1. scan 阶段
scan:
  stage: test
  image: aquasec/trivy:0.45
  script:
    - trivy image --severity HIGH,CRITICAL --exit-code 1 --format json --output result.json --input image.tar
    - |
      HIGH_COUNT=$(jq '[.Results[].Vulnerabilities[] | select(.Severity == "HIGH" or .Severity == "CRITICAL") | select(.CVSS.nvd.V3Score >= 7.0)] | length' result.json)
      if [ "$HIGH_COUNT" -gt 0 ]; then
        echo "发现 $HIGH_COUNT 个 CVE≥7.0 的高危漏洞,阻断晋级"
        exit 1
      fi
  allow_failure: false
  1. push 阶段
push:
  stage: deploy
  script:
    - docker load -i image.tar
    - docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA $CI_REGISTRY_IMAGE:prod
    - docker push $CI_REGISTRY_IMAGE:prod
  only:
    - master
  1. 国产增强
  • 若公司强制使用阿里云 ACR 云原生扫描,可在 .gitlab-ci.yml 里调用ACS API
    aliyun cr GetRepoTagScanReport --RegionId cn-shanghai --RepoNamespace foo --RepoName bar --Tag $CI_COMMIT_SHORT_SHA
    解析返回 JSON,同样判断 Level == "HIGH"CVSSScore >= 7.0exit 1
  • 把扫描结果通过钉钉群机器人飞书 webhook 实时通知安全owner,满足等保审计留痕

拓展思考

  1. 灰度阻断:对老业务镜像设置7 天宽限期,在 CI 里读取 ALLOW_CVE_7_DAYS=true 环境变量,通过 git blame 判断 Dockerfile 是否新增漏洞包,实现增量阻断
  2. 供应链签名:结合国产签名方案(阿里云 Notary v2 兼容实现)在 CI 末端对“干净”镜像加签,后续集群侧通过Admission Controller 验签,双因子阻断(CVE+无签名)才能彻底防止绕过;
  3. 镜像瘦身:用 docker-slimdive 先把业务裁剪到 50 MB 以内,再跑扫描,可减少 30% 误报
  4. 红蓝演练:每季度在流水线里故意植入 CVE≥9.0 的恶意层,验证阻断逻辑是否真生效,避免“CI 扫描摆设化”
  5. 国产化替代:若公司处于信创环境,可把 Trivy 漏洞库离线同步到长城、麒麟仓库,并用龙芯构建机跑扫描,保证全链路自主可控