开篇先给结论:NanoClaw 项目在公开说明中表示,通过一轮系统性的容器镜像治理,消除了镜像中 1400 个 CVE。这个数字不是靠换一个扫描工具、改一个 base image 就能凑出来的。1400 个 CVE 背后,是基础镜像里的系统库漏洞、语言依赖里的老版本组件、编译过程遗留下来的临时文件、甚至是为了省事直接apt-get install装上去的大量无用包。要把它们一个个摘干净,再让修复结果不被下一次构建覆盖,需要一整套可落地的镜像安全流程。
本文不写概念堆砌,直接拆解一套从“扫描基线”到“持续准入”的容器镜像 CVE 治理方法,并解释 NanoClaw 这类项目可以怎样把 1400 这个数字压下来。内容包含工具选型、扫描命令、依赖修复、SBOM 生成、CI 流水线集成、批量扫描脚本、性能观察和常见问题排查。文章适合负责镜像打包、DevOps 流水线、安全合规的工程师阅读,也适合想搞懂“CVE 修复到底在修什么”的同学收藏。
1. 核心能力速览
以“消除 1400 个 CVE”为目标的 NanoClaw 镜像安全治理,本质上是一套容器镜像安全工程化能力。下面用表格快速过一遍核心要素。
| 能力项 | 说明 |
|---|---|
| 治理目标 | 降低基础镜像与依赖组件中的所有可发现 CVE 数量,保持镜像最小可用 |
| 核心工具 | Trivy、Grype、Syft、Docker Scout、Cosign、Docker Buildx 等 |
| 主要手段 | 多阶段构建、最小基础镜像替换、依赖锁定与升级、组件裁剪、SBOM 生成、镜像签名 |
| 验证指标 | 扫描漏洞数、高危/严重级别数量、基础镜像大小、依赖引入数 |
| 支持场景 | 本地单镜像修复、CI 流水线扫描、私有仓库批量巡检、镜像准入控制 |
| 适用角色 | 平台工程师、DevOps、安全工程师、发布负责人 |
| 部署环境 | Linux / macOS / Windows,Docker 或 containerd 环境 |
| API 能力 | Trivy、Grype 均可输出 JSON/SBOM,支持脚本化和平台集成 |
| 批量任务 | 支持仓库级批量扫描、并发扫描、结果聚合与去重 |
| 注意事项 | CVE 数量受扫描器数据库和触发条件影响,不同工具结果可能有差异 |
需要说明的是,“1400”这个数字来自 NanoClaw 项目公开信息,不同时间、不同版本、不同扫描器得到的绝对数量不一定一致。对大多数项目来说,重要的不是跟 1400 较劲,而是建立一套能持续发现、修复、验证的机制。
2. 容器镜像里为什么能藏这么多 CVE
很多第一次接触镜像安全的人会问:一个业务镜像,代码没变过,为什么扫描出来几百上千个漏洞?
原因在于,容器镜像不是“一个运行文件”,而是一层一层叠加起来的文件系统。每一层都可能带来 CVE:
- 基础镜像自带的系统包:比如 Debian/Ubuntu 里的 glibc、openssl、zlib、bash,CentOS 里的 rpm 包。基础镜像不是官方一更新你就跟着更新的,很可能一个基础镜像用半年,底层库已经积累了数十个已公开漏洞。
- 语言依赖:Node 项目里的
node_modules、Python 项目里的site-packages、JVM 项目里的 fat jar。这些依赖版本如果锁定时间早,后端漏洞库里可能存在大量已知 CVE。 - 包管理器缓存:
apt-get install之后如果没清理/var/lib/apt/lists,会把索引文件带进镜像,这些文件本身不算是漏洞,但会让镜像体积膨胀,关键是容易让人忽略清理步骤。 - 构建期工具残留:编译用的 gcc、make、curl、git,开发依赖,如果没有用多阶段构建隔离,全部留在最终镜像里,既增加攻击面,也会被 CVE 扫描器识别为风险组件。
- 拷贝进去的配置文件和二进制:一些项目直接把下载的二进制、脚本、证书放入镜像,没做版本校验,也可能包含已知漏洞组件。
当这些因素叠加在一起,1400 这个数字就并不夸张。NanoClaw 能清除这么多 CVE,说明它多半做了一次彻底的“镜像减肥 + 依赖升级 + 组件替换”的组合动作,而不是只升级其中一层。
3. 容器镜像安全工具链准备
在做修复之前,先把工具链准备好。这里推荐一套目前社区使用最广的组合,全部基于开源工具,不需要额外授权。
3.1 安装 Docker
如果本机还没有 Docker,先安装 Docker Engine。在 Ubuntu 上可以直接用官方脚本,但建议先看一遍脚本内容,再执行:
curl -fsSL https://get.docker.com -o get-docker.sh sh get-docker.sh安装完成后验证:
docker version确保 Docker 服务在运行,并且当前用户有执行权限。如果不想每次加sudo,可以把用户加入 docker 组:
sudo usermod -aG docker $USER3.2 安装 Trivy
Trivy 是目前最常用的镜像漏洞扫描工具,支持容器镜像、文件系统、SBOM、Git 仓库等扫描对象。安装方法很多,这里给一个通用脚本,具体版本以官方发布为准:
# 通过 GitHub Release 安装,需要根据实际版本替换路径 wget https://github.com/aquasecurity/trivy/releases/download/v0.50.0/trivy_0.50.0_Linux-64bit.tar.gz tar zxvf trivy_0.50.0_Linux-64bit.tar.gz sudo mv trivy /usr/local/bin/ trivy --version也可以使用包管理器安装:
sudo apt-get install -y wget apt-transport-https gnupg lsb-release wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add - echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -sc) main | sudo tee -a /etc/apt/sources.list.d/trivy.list sudo apt-get update sudo apt-get install -y trivy3.3 安装 Grype 与 Syft
Grype 是 Anchore 出品的漏洞扫描器,Syft 用于生成 SBOM(软件物料清单)。两者配合使用很流畅,安装方式:
# 使用 Homebrew(macOS / Linux) brew install anchore/grype/grype anchore/syft/syft或者直接下载二进制,以官方仓库 Release 页面为准。
# 通用安装脚本,需要以实际发布版本为准 curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin3.4 安装 Cosign(镜像签名)
Cosign 用于对镜像进行签名,保障镜像完整性。安装方式:
# 以官方最新版为准 wget https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64 sudo mv cosign-linux-amd64 /usr/local/bin/cosign sudo chmod +x /usr/local/bin/cosign cosign version3.5 扫描前准备
扫描本地镜像之前,先把目标镜像拉到本地:
# 以实际项目镜像名为准 docker pull nanoclaw-server:latest然后先用 Trivy 做一次基线扫描:
trivy image --format table --severity HIGH,CRITICAL nanoclaw-server:latest这一步会输出所有扫到的高危和严重级别漏洞。如果团队习惯了 JSON 输出,方便后续写脚本统计,可以加--format json:
trivy image --format json --output nanoclaw-scan.json nanoclaw-server:latest4. 从 1400 个 CVE 到 0 的修复流程模型
NanoClaw 的治理过程,如果用工程化思维拆解,可以归纳为下面八个步骤。这个流程模型可以复用到任何项目里。
4.1 基线扫描与结果归档
第一步不是急着改 Dockerfile,而是先把现状摸清楚。要同时回答几个问题:
- 当前镜像有多少个 CVE,其中 CRITICAL 和 HIGH 各有多少?
- 这些 CVE 分布在哪些包/组件上?
- 哪些是因为基础镜像版本太旧导致的?
- 哪些是语言依赖导致的?
- 哪些是重复出现在多个层里的?
建议把扫描结果 JSON 归档到 git 仓库或者对象存储里,作为治理前基线。后续每次修复,都拿新结果跟基线比,量化进展。
4.2 CVE 分类与修复优先级
CVE 不全是“必须立刻修”的。有的是生产环境真正可利用的远程代码执行漏洞,有的只是本地权限提升,而且需要攻击者已经拿到一个 shell,还有的干脆是因为依赖库包含漏洞代码,但运行时根本没有调用受影响函数。
建议按以下优先级处理:
| 优先级 | 类型 | 处理策略 |
|---|---|---|
| P0 | 远程可利用的 RCE / 未授权访问漏洞 | 立即升级依赖或基础镜像,不能等待 |
| P1 | 需要本地交互的权限提升 / 文件泄露 | 最近一个迭代内升级 |
| P2 | 影响面小或利用条件苛刻的低危漏洞 | 跟随基础镜像月度更新解决 |
| P3 | 扫描器误报 / 运行时不可达路径 | 记录并声明,持续跟踪 |
4.3 基础镜像替换为最小可用镜像
1400 个 CVE 里,相当一部分来自完整版基础镜像。比如python:3.10-slim比python:3.10少很多系统包,gcr.io/distroless系列镜像里甚至没有 shell、没有包管理器。把基础镜像从ubuntu:22.04换成ubuntu:22.04-slim或者 distroless,短时间内就能砍掉大量系统级 CVE。
换基础镜像时要重新验证应用依赖了哪些系统库,不能盲目更换。常见情况是很多 Python 扩展包依赖 gcc、libffi、libssl-dev,如果直接使用 distroless 镜像,缺了编译器和头文件,构建阶段就会失败。解决办法是保留多阶段构建,在构建阶段装编译依赖,最终运行阶段只拷贝编译产物。
NanoClaw 如果做了这种切换,镜像内层组件数量会大幅降低,CVE 数量自然呈指数级下降。
4.4 语言依赖升级与锁定
镜像内的应用依赖,是最容易被忽视但也很容易被扫描器识别的一部分。
以 Python 项目为例,先导出依赖清单:
pip freeze > requirements-lock.txt然后使用pip-audit或safety检查漏洞:
pip install pip-audit pip-audit -r requirements-lock.txt看到旧版本依赖后,逐个升级,但不是直接pip install --upgrade了事。升级后要跑一遍测试用例,确认没有破坏兼容性。同样的逻辑,Node.js 项目用npm audit、Java 项目可以用 OWASP Dependency Check 或者 Trivy 的--scanners vuln直接扫文件系统。
语言依赖的锁定,关键是生成 lockfile 并提交到仓库。这样每次构建使用的是同一组依赖,方便追踪漏洞来源。
4.5 清理掉无用包和缓存
镜像里每多一个不需要的包,就多一块攻击面。清理动作一般包括:
- 删除
/var/lib/apt/lists/缓存 - 删除
~/.cache/pip缓存 - 删除
/tmp下的临时文件 - 删除文档、示例、测试代码
- 如果不需要 shell,最终镜像用 distroless 或者多阶段构建只拷贝二进制
一个典型的省事做法是,在 Dockerfile 的同一层完成安装和清理,避免缓存被提交到中间层:
RUN apt-get update && \ apt-get install -y --no-install-recommends libssl3 && \ rm -rf /var/lib/apt/lists/*4.6 生成并维护 SBOM
SBOM 是软件物料清单,用来记录镜像里所有组件和版本信息。有了 SBOM,才能准确知道哪些组件受到某个 CVE 影响,也方便修复后做差异对比。
用 Syft 生成 SBOM:
syft packages nanoclaw-server:latest -o cyclonedx-json > nanoclaw-sbom.jsonSBOM 文件建议保存到单独的仓库,或者作为 CI 产物上传到制品库。以后每次扫描可以直接基于 SBOM 做增量比对,不用每次全量重新解析镜像层。
4.7 持续扫描与增量验证
一次性把 1400 个 CVE 清完,只是开始。真正的问题是如何避免“修完又冒出来”。需要把扫描动作嵌进 CI/CD,每次提交代码后自动对镜像做一次扫描,并设置阈值:
- 如果 HIGH/CRITICAL 漏洞数大于 N,构建失败。
- 如果与上一次相比新增了 HIGH 漏洞,构建失败。
- 如果 SBOM 内容变化但未更新安全说明,需要人工确认。
这样新引入的组件必须在合入前经过漏洞检查,就不会出现“一次清零,三个月后回退”的情况。
4.8 镜像签名与运行准入
CVE 清零不等于镜像就安全了。还要保证运行环境里的镜像确实是经过扫描、批准的那一份。用 Cosign 给镜像签名:
cosign sign --key cosign.key nanoclaw-server:latest在 Kubernetes 侧,可以用 Kyverno 或 OPA Gatekeeper 校验签名,不允许未签名的镜像进入 cluster。通过签名和准入控制,把“修好的镜像”锁定为“唯一可运行的镜像”。
5. 关键实操:Trivy 扫描、修复与验证
前面讲的是方法论,这里给一组可以直接跑的实操命令,覆盖扫描、修复、再扫描的闭环。
5.1 修复前先看漏洞明细
扫描时不要只盯着总数,要能看清漏洞属于哪一层、哪个包、影响哪个路径。用 Trivy 输出详细表格:
trivy image --severity CRITICAL,HIGH --ignore-unfixed --format table nanoclaw-server:latest加上--ignore-unfixed可以只显示已经存在修复版本的漏洞。这一项很有用,因为有些 CVE 至今没有上游补丁,修也没有目标版本,先不占用处理精力。
如果希望把结果按 Target(目标对象)分组,可以加--report all或使用--format json后自行处理。
5.2 定位到具体层
想确认漏洞来自哪个镜像层,可以用docker history查看层信息:
docker history --no-trunc nanoclaw-server:latest再对照docker image inspect查看每一层对应的命令。通常可以判断出哪一层是 apt 安装层,哪一层是 pip install 层。
5.3 修复一个典型漏洞
假设扫描发现镜像里的openssl版本低于 3.0.8,存在 CVE-2022-4304,修复方式不是直接改 Dockerfile 里的一个数字,而是:
- 将基础镜像更新到包含安全补丁的新版本,比如从
debian:11.5更新到debian:11.6。 - 或者直接在安装步骤里指定
openssl的最低版本。
在 Dockerfile 里可以这样写:
FROM debian:11 RUN apt-get update && \ apt-get install -y openssl=3.0.8-1~deb11u1 && \ rm -rf /var/lib/apt/lists/*不过更推荐的方式是直接换基础镜像:当上游官方镜像发布安全更新后,重新拉取新 tag。
5.4 用多阶段构建隔离构建期依赖
多阶段构建是清除构建期 CVE 的最有效手段。以 Node.js 项目为例:
# 构建阶段 FROM node:20-slim AS build WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # 运行阶段 FROM gcr.io/distroless/nodejs20-debian12 WORKDIR /app COPY --from=build /app/dist ./dist COPY --from=build /app/node_modules ./node_modules CMD ["dist/server.js"]最终镜像里没有npm,没有源码,也没有缓存目录。构建阶段的漏洞不会进入运行镜像,CVE 数量大幅下降。
5.5 修复后重新扫描对比
修复后重新扫描,并把结果和基线对比:
trivy image --severity CRITICAL,HIGH --format json --output after.json nanoclaw-server:latest在脚本里对比before.json和after.json中的漏洞 ID,统计减少数量。也可以直接看表格输出:
trivy image --severity CRITICAL,HIGH --format table nanoclaw-server:latest确认高危数量已经降下来后,把新的扫描结果和 SBOM 一起归档。
6. 批量扫描与 API 接入
单个镜像手动扫描容易,仓库里几十个镜像就不行了。这里提供一个批量扫描的思路,用脚本自动遍历镜像列表、输出结果、生成报告。
6.1 批量扫描脚本示例
#!/usr/bin/env bash # batch-scan.sh # 用法: ./batch-scan.sh images.txt set -euo pipefail IMAGES_FILE="${1:-images.txt}" OUTPUT_DIR="./scan-results" mkdir -p "$OUTPUT_DIR" while IFS= read -r image; do [ -z "$image" ] && continue echo "Scanning $image ..." trivy image --severity CRITICAL,HIGH --format json \ --output "$OUTPUT_DIR/$(echo "$image" | tr '/:' '__').json" "$image" done < "$IMAGES_FILE" echo "All scans done. Results in $OUTPUT_DIR"images.txt每行一个镜像,例如:
nanoclaw-server:1.0.0 nanoclaw-worker:1.0.0 nanoclaw-web:1.0.0这个脚本会逐个扫描,并把 JSON 结果写到scan-results目录。想并行加速,可以在循环后面加&配合wait,但要注意本机资源,扫描器本身也会消耗内存和 CPU。
6.2 用 Python 调用 Trivy 进行批量统计
如果想要更灵活的结果聚合,可以在脚本里调用trivy并解析 JSON:
#!/usr/bin/env python3 import json import subprocess images = ["nanoclaw-server:latest", "nanoclaw-worker:latest"] for image in images: result = subprocess.run( ["trivy", "image", "--format", "json", "--severity", "CRITICAL,HIGH", image], capture_output=True, text=True, check=False, ) data = json.loads(result.stdout) vulns = data.get("Results", []) total = sum(len(v["Vulnerabilities"] or []) for v in vulns) print(f"{image}: {total} HIGH/CRITICAL vulnerabilities")实际使用中,建议把镜像是私有仓库的情况考虑进去,加上认证参数,比如--registry.token或提前docker login。
6.3 在 CI 流水线中集成扫描
以 GitLab CI 为例,在流水线中加入扫描阶段:
stages: - build - scan build: stage: build script: - docker build -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} . - docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} scan: stage: scan script: - trivy image --exit-code 1 --severity CRITICAL,HIGH \ --ignore-unfixed \ ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event"--exit-code 1的作用是,如果扫描出高危/严重漏洞,就让 CI 任务失败,从而阻止合并请求。
6.4 批量修复的辅助思路
批量扫描发现问题后,批量修复不建议靠人工一个个改版本。可以使用以下辅助手段:
- 使用 Renovate 或 Dependabot 自动更新依赖。
- 定期执行
pip-audit fix或npm audit fix,需要验证兼容性。 - 基础镜像升级通过脚本统一更新 Dockerfile 中的 base image tag,再跑一遍完整测试和扫描。
7. 资源占用与性能观察
CVE 扫描不是零成本操作。扫描一个中等大小的镜像,需要下载漏洞数据库、解包每一层、解析包管理器数据、匹配 CVE。对大批量镜像做定期扫描时,要观察资源占用。
7.1 观察扫描期间资源占用
可以用top或docker stats观察扫描进程的 CPU 和内存占用。
top -p $(pgrep -f trivy)Trivy 首次扫描需要下载漏洞数据库,耗时较长,后续使用缓存会快很多。Grype 的首次运行也需要构建数据库缓存。
7.2 影响扫描性能的关键因素
| 因素 | 影响 |
|---|---|
| 镜像层数 | 层越多,解包和文件比对耗时越长 |
| 组件数量 | SBOM 里的组件越多,匹配漏洞库的时间越长 |
| 漏洞数据库大小 | 首次下载数据库耗时可能达到分钟级 |
| 并发扫描任务数 | 并发过高会导致内存被占满,扫描变慢甚至被操作系统杀掉 |
| 网络带宽 | 拉取镜像、下载数据库都依赖网络 |
7.3 降低扫描资源的建议
- 尽量复用 Trivy 的缓存目录,不要每次清空。
- 在 CI 里把扫描放到独立 job,避免和构建任务抢资源。
- 生成 SBOM 后,后续可以基于 SBOM 做漏洞匹配,不需要每次解包整镜像。
- 如果只需要知道“有没有新增高危 CVE”,可以只扫差异层,而不是全量扫描。
8. 常见问题与排查方法
下面这个表汇总了容器镜像 CVE 治理过程中最容易遇到的几类问题。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 扫描时下载漏洞数据库失败 | 网络受限或镜像源不可达 | 查看扫描器日志,确认网络连通性 | 配置代理或使用离线漏洞库。离线库的更新频率需要结合实际环境评估 |
| 私有仓库镜像扫描提示认证失败 | 未登录镜像仓库 | 先执行docker login,或在扫描参数中传入仓库凭证 | 在 CI 中使用 CI 变量注入仓库认证信息 |
| 扫描结果出现大量“未知”应用包 | 应用使用非标准方式安装或压缩了二进制 | 检查镜像内文件系统布局 | 为应用生成 SBOM 并在扫描时指定 SBOM 路径 |
| 修复后重新扫描,漏洞数量未减少 | 使用了缓存镜像,或没有重新拉取基础镜像 | 确认 Dockerfile 是否COPY了旧依赖缓存 | 清理构建缓存,强制docker build --pull --no-cache |
| 扫描报告显示某个 CVE 不存在修复版本 | 上游尚未发布补丁 | 查询漏洞库中的 Affected Versions 字段 | 暂时记录,加白名单,持续跟踪 |
| 升级依赖后应用启动失败 | 依赖存在兼容性变更 | 查看应用日志,确认崩溃堆栈 | 回滚到安全且兼容的版本,或调整代码 |
| 使用 distroless 镜像后容器无法调试 | 镜像内没有 shell | 这是预期行为 | 临时使用带 shell 的 debug 版镜像,或使用kubectl exec加上 ephemeral container 调试 |
| CI 扫描任务耗时过长 | 镜像过大或扫描器缓存未持久化 | 查看 job 耗时图,定位到扫描阶段 | 使用缓存目录,分割扫描 job,或提前生成 SBOM |
9. 最佳实践与合规边界
NanoClaw 的 1400 个 CVE 清零经验,背后是一套可持续的镜像安全规范。这里把最重要的实践和边界整理清楚。
9.1 工程化实践
- 基础镜像要有一个固定的更新周期,例如每两周拉取一次上游镜像并重新构建。
- 不要使用
latest标签作为生产基础镜像,要锁定具体版本或摘要(digest)。 - 依赖锁文件必须提交到代码仓库,并在 CI 中校验锁文件是否与当前依赖一致。
- SBOM 不是一次性产出,每次发布都要生成并归档。
- 镜像扫描要有退出码阈值,HIGH/CRITICAL 漏洞必须阻止合并或发布。
- 构建缓存不要无脑复用,基础镜像更新后要强制
--pull重新拉取基础镜像。 - 启用镜像签名,在部署阶段校验签名。
9.2 Dockerfile 编写建议
# 固定基础镜像版本 FROM debian:11.6-slim AS build RUN apt-get update && \ apt-get install -y --no-install-recommends build-essential && \ rm -rf /var/lib/apt/lists/* # 应用构建过程... # 最终运行镜像阶段 FROM gcr.io/distroless/base-debian12 COPY --from=build /app/bin /app/bin USER nonroot:nonroot ENTRYPOINT ["/app/bin/server"]关键点:
- 基础镜像 tag 精确到补丁版本,不要只写
debian:11。 - 安装包使用
--no-install-recommends,避免引入推荐包。 - 用完包管理器立刻清理缓存列表。
- 最终镜像使用非 root 用户。
- 如果可能,挂载只读根文件系统。
9.3 合规与责任边界
必须明确一点:扫描器报出的 CVE 数量,不等于真实攻击面。你的应用可能根本没有运行受影响函数,也可能漏洞被网络隔离挡在外面。CVE 治理的目标是把已知风险控制在可接受范围,而不是追求绝对的数字归零。如果某些漏洞因为上游没有补丁而无法修复,要做好记录和声明,必要时通过临时缓解措施(如网络策略、IPC 限制、禁止用户态访问)降低可利用性。
如果项目涉及第三方代码、闭源组件或受 License 限制的库,升级版本时必须检查许可证兼容性。镜像里扫描出的组件如果是商业授权,需要确认是否被允许在容器内部分发和运行。容器镜像中如果包含人脸数据、用户个人信息、密钥、证书,一旦被构建进镜像并推送,便很难彻底清除,需要按数据安全要求处理。
10. 总结与下一步
从 NanoClaw 的项目结果看,消除 1400 个 CVE 并不是做一次trivy clean就能复现的数字,它依赖的是一整套镜像治理机制:基础镜像收敛、依赖锁定与升级、多阶段构建隔离、SBOM 追踪、持续扫描和签名准入。这套机制跑通后,镜像内的高危漏洞数量会稳定在一个低水平,并且每次新增依赖都能被及时拦截。
这篇文章给出的扫描命令、批量脚本和 CI 集成方式,可以直接作为参考模板落地。第一次做镜像安全治理时,不要急着追求把数量压到 0,先完成下面三轮动作:
第一轮:为当前所有线上镜像做一次全量扫描,统计 CRITICAL/HIGH 数量,归档 JSON 和 SBOM。 第二轮:选择业务影响最大的 1-2 个镜像,从基础镜像和语言依赖入手修复,跑通“扫描 -> 修复 -> 再扫描”闭环。 第三轮:把扫描动作接入 CI,同时配置阈值,确保新引入的漏洞无法进入发布分支。
如果这三轮都能稳定执行,镜像安全治理就算真正落地了。后续可以再扩展的方向包括:运行时容器逃逸检测、镜像仓库持续巡检、对 CI 构建后的镜像做签名验证、以及把扫描结果接入内部漏洞管理平台。NanoClaw 能清掉 1400 个 CVE,说明这条路是走得通的,接下来就看你自己的项目能从自己的仓库里扫出多少,又愿意花多少时间把它们清干净。