使用 Grype 扫描容器镜像
概述
Grype 是 Anchore 开源的漏洞扫描器,用于检查容器镜像、文件系统和 SBOM 中的已知 CVE。它利用 Syft 生成的 SBOM,将软件包与多个漏洞数据库进行匹配,包括 NVD、GitHub Advisory 和特定操作系统的漏洞数据源。
前置条件
- 已安装 Docker 或 Podman
- 已安装 Grype CLI(
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin) - Syft CLI(可选,用于生成 SBOM)
- 网络访问权限(用于拉取漏洞数据库)
核心命令
安装 Grype
# 通过脚本安装
curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin
# 验证安装
grype version
# 通过 Homebrew 安装(macOS/Linux)
brew install grype
扫描容器镜像
# 扫描 Docker Hub 镜像
grype nginx:latest
# 从 Docker daemon 扫描
grype docker:myapp:1.0
# 扫描本地存档
grype docker-archive:image.tar
# 扫描 OCI 目录
grype oci-dir:path/to/oci/
# 扫描 Singularity 镜像
grype sif:image.sif
# 扫描本地目录/文件系统
grype dir:/path/to/project
输出格式
# 默认表格输出
grype alpine:3.18
# JSON 格式输出(用于流水线处理)
grype alpine:3.18 -o json > results.json
# CycloneDX SBOM 输出
grype alpine:3.18 -o cyclonedx
# SARIF 格式输出(用于 GitHub Security 标签页)
grype alpine:3.18 -o sarif > grype.sarif
# 基于模板的自定义输出
grype alpine:3.18 -o template -t /path/to/template.tmpl
过滤与阈值
# 发现达到或超过指定严重性时失败
grype nginx:latest --fail-on critical
# 仅显示有修复版本的漏洞
grype nginx:latest --only-fixed
# 仅显示无修复版本的漏洞
grype nginx:latest --only-notfixed
# 按严重性过滤
grype nginx:latest --only-fixed -o json | jq '[.matches[] | select(.vulnerability.severity == "High")]'
# 解释特定 CVE
grype nginx:latest --explain --id CVE-2024-1234
使用 SBOM
# 用 Syft 生成 SBOM 后扫描
syft nginx:latest -o spdx-json > nginx-sbom.json
grype sbom:nginx-sbom.json
# 扫描 CycloneDX SBOM
grype sbom:bom.json
配置文件(.grype.yaml)
# .grype.yaml
check-for-app-update: false
fail-on-severity: "high"
output: "json"
scope: "squashed" # 或 "all-layers"
quiet: false
ignore:
- vulnerability: CVE-2023-12345
reason: "误报 - 在我们的环境中不可利用"
- vulnerability: CVE-2023-67890
fix-state: unknown
db:
auto-update: true
cache-dir: "/tmp/grype-db"
max-allowed-built-age: 120h # 5 天
match:
java:
using-cpes: true
python:
using-cpes: true
javascript:
using-cpes: false
CI/CD 集成
# GitHub Actions
- name: 使用 Grype 扫描镜像
uses: anchore/scan-action@v4
with:
image: "myregistry/myapp:${{ github.sha }}"
fail-build: true
severity-cutoff: high
output-format: sarif
id: scan
- name: 上传 SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.scan.outputs.sarif }}
# GitLab CI
container_scan:
stage: test
image: anchore/grype:latest
script:
- grype ${CI_REGISTRY_IMAGE}:${CI_COMMIT_SHA} --fail-on high -o json > grype-report.json
artifacts:
reports:
container_scanning: grype-report.json
数据库管理
# 检查数据库状态
grype db status
# 手动更新漏洞数据库
grype db update
# 删除缓存的数据库
grype db delete
# 列出支持的数据库提供者
grype db list
关键漏洞数据源
| 数据源 | 覆盖范围 |
|---|---|
| NVD | 所有生态系统的 CVE |
| GitHub Advisories | 开源软件包漏洞 |
| Alpine SecDB | Alpine Linux 软件包 |
| Amazon Linux ALAS | Amazon Linux AMI |
| Debian Security Tracker | Debian 软件包 |
| Red Hat OVAL | RHEL、CentOS |
| Ubuntu Security | Ubuntu 软件包 |
| Wolfi SecDB | Wolfi/Chainguard 镜像 |
最佳实践
- 固定镜像标签 - 始终扫描特定摘要,而非
latest - 设置严重性失败阈值 - 在 CI 门控中设置
--fail-on high或critical - 使用 SBOM - 用 Syft 生成 SBOM 以实现可复现的扫描
- 抑制误报 - 使用带记录原因的
.grype.yaml忽略规则 - 扫描所有层 - 使用
--scope all-layers捕获中间层中的漏洞 - 自动化数据库更新 - 在 CI runner 中保持漏洞数据库为最新
- 比较扫描结果 - 随时间追踪漏洞数量变化以检测回归