4. Trivy扫描文件系统

文件系统扫描是 Trivy 最基础也是最常用的功能之一。与镜像扫描不同,文件系统扫描直接对本地目录中的文件进行静态分析,无需运行容器或拉取镜像。本章将深入讲解如何对本地目录执行扫描、通过严重级别过滤结果,以及灵活切换三种输出格式(TABLE / JSON / SARIF),为后续门禁联动奠定数据基础。

4.1 文件系统扫描的核心原理

Trivy 的文件系统扫描器会遍历目标目录,识别其中的依赖清单文件(如 package-lock.json、go.sum、requirements.txt 等),并与内置的漏洞数据库进行比对。扫描过程不依赖网络(数据库已本地缓存),因此适合离线环境或 CI/CD 流水线中的安全门禁。

关键特性:
  • 支持 20+ 种编程语言和框架的依赖分析
  • 自动识别操作系统级软件包(如 APK、DEB、RPM)
  • 可扫描配置文件中的密钥泄露(配合 --security-checks)
  • 扫描结果包含 CVE 编号、严重级别、修复版本、PkgPath 等字段
文件系统扫描流程 本地目录 Trivy 扫描引擎 漏洞数据库 TABLE 格式 JSON 格式 SARIF 格式 --severity CRITICAL,HIGH 过滤

4.2 基本扫描命令与参数

执行文件系统扫描的基本命令格式如下:

trivy fs [flags] PATH

其中 PATH 可以是相对路径或路径。以下为最常用的参数组合:

参数 说明 示例值
--severity 按严重级别过滤,多个级别用逗号分隔 CRITICAL,HIGH
--format 输出格式,支持 table、json、sarif json
--output 将结果写入文件,而非标准输出 result.json
--ignore-unfixed 仅显示有修复版本的漏洞 (布尔标志)
--scanners 指定扫描器类型(vuln、secret、misconfig) vuln,secret
实践建议:在 CI/CD 门禁场景中,建议始终使用 --severity CRITICAL,HIGH 过滤,避免低危漏洞干扰流水线决策。同时配合 --ignore-unfixed 可减少因未发布补丁导致的误报。

4.3 指定严重级别过滤

Trivy 将漏洞严重级别分为四档:CRITICAL、HIGH、MEDIUM、LOW。通过 --severity 参数可以精确控制输出范围。

示例:仅扫描当前项目目录,只显示严重和高危漏洞:

trivy fs --severity CRITICAL,HIGH ./my-project

若需要排除低危和中危,同时输出到文件:

trivy fs --severity CRITICAL,HIGH --format json --output critical-high.json ./my-project
注意:严重级别过滤是在扫描完成后对结果进行筛选,而非跳过扫描过程。因此扫描时间不会因过滤而缩短。若需提升性能,可使用 --skip-dirs 或 --skip-files 排除无关目录。

4.4 三种输出格式详解

Trivy 支持三种主要输出格式,每种格式适用于不同的使用场景:

格式 适用场景 特点 门禁联动
TABLE 本地调试、人工审查 终端友好,彩色高亮,可读性强 不推荐,难以程序化解析
JSON CI/CD 流水线、自定义脚本 结构化数据,易于 jq 处理 推荐,可提取漏洞数量、级别、路径
SARIF GitHub Advanced Security、IDE 集成 标准静态分析交换格式 适合上传至 GitHub/SonarQube

4.4.1 TABLE 格式(默认)

不指定 --format 时,默认输出 TABLE 格式。适合在终端直接查看:

trivy fs --severity CRITICAL ./app

输出示例:

Total: 3 (CRITICAL: 3)

┌──────────┬────────────────┬──────────┬──────────────────┬───────────────┐
│  Library │ Vulnerability  │ Severity │ Installed Version│ Fixed Version │
├──────────┼────────────────┼──────────┼──────────────────┼───────────────┤
│ lodash   │ CVE-2023-1234  │ CRITICAL │ 4.17.20          │ 4.17.21       │
│ axios    │ CVE-2023-5678  │ CRITICAL │ 0.21.1           │ 0.21.2        │
│ express  │ CVE-2023-9012  │ CRITICAL │ 4.17.1           │ 4.18.0        │
└──────────┴────────────────┴──────────┴──────────────────┴───────────────┘

4.4.2 JSON 格式

JSON 格式是门禁联动的首选。通过 jq 可以快速提取关键指标:

trivy fs --severity CRITICAL,HIGH --format json ./app > result.json

# 提取高危漏洞数量
cat result.json | jq '.Results[].Vulnerabilities | length'

# 提取所有 CVE ID 和严重级别
cat result.json | jq '.Results[].Vulnerabilities[] | {CVE: .VulnerabilityID, Severity: .Severity}'

4.4.3 SARIF 格式

SARIF(Static Analysis Results Interchange Format)是 OASIS 标准,被 GitHub Code Scanning、Azure DevOps 等平台原生支持:

trivy fs --severity CRITICAL,HIGH --format sarif --output result.sarif ./app

生成的 SARIF 文件可直接上传至 GitHub:

gh api /repos/{owner}/{repo}/code-scanning/sarifs \
  -f sarif=@result.sarif \
  -f commit_sha="$(git rev-parse HEAD)"
格式选择建议:
  • 本地调试 → TABLE
  • 门禁脚本 / 自定义规则 → JSON
  • 平台集成(GitHub / Azure DevOps) → SARIF
三种输出格式对比 TABLE 终端友好 彩色高亮 人工审查 ❌ 不适合门禁 JSON 结构化数据 jq 可解析 自定义规则 ✅ 门禁首选 SARIF OASIS 标准 GitHub 原生 平台集成 ✅ 平台集成 门禁联动推荐使用 JSON 格式,平台集成推荐 SARIF

4.5 实战:完整扫描命令组合

以下是一个生产环境可用的扫描命令,集成了严重级别过滤、JSON 输出和忽略未修复漏洞:

trivy fs \
  --severity CRITICAL,HIGH \
  --format json \
  --output trivy-report.json \
  --ignore-unfixed \
  --scanners vuln,secret \
  --skip-dirs node_modules \
  --skip-dirs .git \
  ./my-application

参数说明:

  • --scanners vuln,secret:同时扫描漏洞和密钥泄露
  • --skip-dirs:跳过 node_modules 和 .git 目录,提升扫描速度
  • --ignore-unfixed:只显示已有修复版本的漏洞,减少噪音
性能优化:对于大型项目,建议先使用 --skip-dirs 排除构建产物和第三方依赖目录。首次扫描后,Trivy 会自动缓存数据库,后续扫描速度会显著提升。

4.6 常见问题与避坑

问题 原因 解决方案
扫描结果为空 目标目录没有可识别的依赖文件 确认目录包含 package.json、go.mod 等清单文件
严重级别过滤无效 参数拼写错误或大小写不正确 使用 --severity CRITICAL,HIGH(大写,逗号无空格)
JSON 输出过大 未使用 --severity 过滤,包含所有级别 添加 --severity CRITICAL,HIGH 缩小输出范围
SARIF 文件上传失败 缺少 commit_sha 或格式不匹配 确保使用 gh api 时传入正确的 commit SHA