Trivy 报告输出实战指南:扫描格式、输出目标与 JSON 格式转换
本指南围绕 Trivy 的 Reporting 能力展开,讲解扫描完成后结果可以 --format 输出的全部格式(Table、JSON、SARIF、Template、SBOM、GitHub dependency snapshot)、结果的落地方式(文件与输出插件),以及如何通过 trivy convert 把已生成的 JSON 报告二次转换成其他格式。读完本文,你将能够根据 CI/CD、安全平台上报或人工排查等不同场景,正确选用 Trivy 的报告格式与相关参数,并理解这些参数在源码层面的校验与实现逻辑。本文主体对应 docs/guide/configuration/reporting.md,源码细节引用当前仓库为证。
支持的输出格式概览
Trivy 对每一次扫描都可以输出为以下格式:
- Table(终端表格,默认)
- JSON
- SARIF(Static Analysis Results Interchange Format)
- Template(基于 Go template 的自定义模板)
- SBOM(CycloneDX / SPDX,详见下文 SBOM 小节)
- GitHub dependency snapshot(GitHub 依赖快照)
在源码中,这些格式被集中定义在 pkg/types/report.go 与 SupportedFormats 列表中,除文档列举的几种外,还包括 cyclonedx、spdx、spdx-json、cosign-vuln 等用于 SBOM 场景的格式:
FormatTable Format = "table"
FormatJSON Format = "json"
FormatTemplate Format = "template"
FormatSarif Format = "sarif"
FormatCycloneDX Format = "cyclonedx"
FormatSPDX Format = "spdx"
FormatSPDXJSON Format = "spdx-json"
FormatGitHub Format = "github"
FormatCosignVuln Format = "cosign-vuln"
注意,不同格式对四种 Scanner(Vulnerability 漏洞、Misconfiguration 错误配置、Secret 密钥、License 许可证)的支持范围并不相同,下面各小节会分别用表格标注。
--format(简写 -f)这个 flag 的默认值是 table,它与其他报告相关参数(--report、--template、--dependency-tree、--list-all-pkgs、--output、--severity、--table-mode 等)统一封装在 ReportFlagGroup 中,定义见 pkg/flag/report_flags.go。所有写入动作最终都汇聚到 pkg/report/writer.go 的 report.Write,它先按 option.Format 选择对应的 Writer,再执行写入:
| 格式 | 对应 Writer |
|---|---|
table |
table.NewWriter |
json |
JSONWriter |
github |
github.Writer |
cyclonedx |
cyclonedx.NewWriter |
spdx / spdx-json |
spdx.NewWriter |
template |
NewTemplateWriter(向后兼容的 sarif.tpl 除外) |
sarif |
SarifWriter |
cosign-vuln |
predicate.NewVulnWriter |
Table 格式(默认)
Table 是 Trivy 默认的人类可读输出格式,对四类 Scanner 全部支持:
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License | ✓ |
默认用法:
$ trivy image -f table golang:1.22.11-alpine3.20
输出结果先是一个"Report Summary"总览表格,随后按 Target 分别给出详细表格。下面是一个节选的真实输出形态:
Report Summary
┌─────────────────────────────────────────────┬──────────┬─────────────────┬─────────┐
│ Target │ Type │ Vulnerabilities │ Secrets │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ golang:1.22.11-alpine3.20 (alpine 3.20.5) │ alpine │ 6 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ usr/local/go/bin/go │ gobinary │ 1 │ - │
├─────────────────────────────────────────────┼──────────┼─────────────────┼─────────┤
│ ... │ │ │ │
└─────────────────────────────────────────────┴──────────┴─────────────────┴─────────┘
Legend:
- '-': Not scanned
- '0': Clean (no security findings detected)
golang:1.22.11-alpine3.20 (alpine 3.20.5)
Total: 6 (UNKNOWN: 2, LOW: 0, MEDIUM: 2, HIGH: 2, CRITICAL: 0)
┌────────────┬────────────────┬──────────┬────────┬───────────────────┬───────────────┬─────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │
├────────────┼────────────────┼──────────┼────────┼───────────────────┼───────────────┼─────────────────────────────────────────────────────────────┤
│ libcrypto3 │ CVE-2024-12797 │ HIGH │ fixed │ 3.3.2-r1 │ 3.3.3-r0 │ openssl: RFC7250 handshakes with unauthenticated servers ... │
│ ├────────────────┼──────────┤ │ ├───────────────┼─────────────────────────────────────────────────────────────┤
│ │ CVE-2024-13176 │ MEDIUM │ │ │ 3.3.2-r2 │ openssl: Timing side-channel in ECDSA signature computation │
└────────────┴────────────────┴──────────┴────────┴───────────────────┴───────────────┴─────────────────────────────────────────────────────────────┘
在终端中直接运行时,严重级别会按颜色区分,从上到下依次为:UNKNOWN(青色)、LOW(蓝色)、MEDIUM(黄色)、HIGH(亮红)、CRITICAL(红色),映射关系定义在 pkg/report/table/table.go。同时 IsOutputToTerminal 会检测输出是否真的指向终端(而不是管道/文件),决定是否启用 ANSI 颜色与粗体样式。
Table 的两种模式:summary 与 detailed
EXPERIMENTAL(实验特性):该特性可能在不保证向后兼容的情况下变更,仅作实验用途。
Table 格式内部细分为两种模式,默认全部开启:
| Mode | Enabled by default |
|---|---|
| summary | ✓ |
| detailed | ✓ |
可以使用 --table-mode 参数单独开关某一种模式,例如只输出总览表或只输出明细表:
# 只显示 Summary 总览
$ trivy image --format table --table-mode summary golang:1.22.11-alpine3.20
# 只显示每个 Target 的详细漏洞表
$ trivy image --format table --table-mode detailed golang:1.22.11-alpine3.20
summary 与 detailed 两个常量、以及 SupportedTableModes 都定义在 pkg/types/report.go。而校验逻辑在 pkg/flag/report_flags.go:--table-mode 只能配合 --format table 使用,否则直接返回错误。底层渲染由 pkg/report/table/table.go 的 Write 完成——依次判断 TableModes 中是否包含 summary 与 detailed,按需渲染汇总表与每个 Target 的明细表。
Summary 总览表
Summary 表给出本次扫描的整体信息,其内容有以下语义约定:
- 表格的列只包含本次已启用的 scanner。请用
--scanners参数来开关具体扫描器。 - 同一个 Target 若被不同扫描器处理,会在表格中单独成行。
-:表示该扫描器没有扫描这个 Target。0:表示该扫描器扫描了这个 Target,但没有发现任何安全问题。
一个包含多 Target、多扫描器的示例输出形态:
┌───────────────────────┬────────────┬─────────────────┬───────────────────┬─────────┬──────────┐
│ Target │ Type │ Vulnerabilities │ Misconfigurations │ Secrets │ Licenses │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ test (alpine 3.20.3) │ alpine │ 2 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ Java │ jar │ 2 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ app/Dockerfile │ dockerfile │ - │ 2 │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ requirements.txt │ text │ 0 │ - │ - │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ requirements.txt │ text │ - │ - │ 1 │ - │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ OS Packages │ - │ - │ - │ - │ 1 │
├───────────────────────┼────────────┼─────────────────┼───────────────────┼─────────┼──────────┤
│ Java │ - │ - │ - │ - │ 0 │
└───────────────────────┴────────────┴─────────────────┴───────────────────┴─────────┴──────────┘
有一个值得注意的细节:对 Secret 与 License 扫描器而言,Trivy 的报告中只包含"发现项"本身。因此 Trivy 无法判断某个 Target 到底是被扫描过但没有问题,还是根本没有被扫描。正因如此,只要这两个扫描器没有发现项,Summary 表统一显示 -(而不是 0)。该语义在源码中同样有印证——pkg/report/table/summary.go 的 Scanner 接口约定:Count 方法返回发现数量,但如果该扫描器不适用于当前结果,则返回 -1(即渲染成 -)。
另外注意:在 convert 模式下若想让 Summary 表正常显示,需要重新启用 JSON 报告生成时所使用的那几个 scanner(对应 flag 默认值行为见下文 convert 部分)。
Detailed 明细表
明细表针对每个 Target 展示找到的安全问题详情(CVE 编号、严重级别、已装版本、修复版本、标题等):
usr/local/go/bin/go (gobinary)
Total: 1 (UNKNOWN: 0, LOW: 0, MEDIUM: 1, HIGH: 0, CRITICAL: 0)
┌─────────┬────────────────┬──────────┬────────┬───────────────────┬──────────────────────────────┬──────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Status │ Installed Version │ Fixed Version │ Title │
├─────────┼────────────────┼──────────┼────────┼───────────────────┼──────────────────────────────┼──────────────────────────────────────────────────────────────┤
│ stdlib │ CVE-2025-22866 │ MEDIUM │ fixed │ v1.22.11 │ 1.22.12, 1.23.6, 1.24.0-rc.3 │ crypto/internal/nistec: golang: Timing sidechannel ... │
└─────────┴────────────────┴──────────┴────────┴───────────────────┴──────────────────────────────┴──────────────────────────────────────────────────────────────┘
渲染时,pkg/report/table/table.go 会根据结果的 Class 分派给不同的渲染器:OS 包与语言包漏洞走 vulnerabilityRenderer,错误配置走 misconfigRenderer,Secret 走 secretRenderer,包许可证与文件许可证分别走 pkgLicenseRenderer 与 fileLicenseRenderer。
展示漏洞依赖的来源路径(--dependency-tree)
现代软件开发重度依赖第三方库,而这些第三方库还会再依赖更多库,因此依赖关系本质上是一张"依赖图"。不少漏洞并不是被直接依赖引入的,而是经由一整条间接依赖链带入,排查时必须分析整棵依赖树。
EXPERIMENTAL(实验特性):该特性可能在不保证向后兼容的情况下变更,仅作实验用途。
Trivy 通过 --dependency-tree 参数来展示"漏洞依赖的来源树(Dependency Origin Tree)",该参数仅在与 --format table 配合时有效:
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | |
| Secret | |
| License |
目前已支持以下 OS 包管理器:
| OS Package Managers |
|---|
| apk |
| dpkg |
| rpm |
目前已支持以下语言的锁文件 / 二进制:
| Language | File |
|---|---|
| Node.js | package-lock.json / pnpm-lock.yaml / yarn.lock |
| .NET | packages.lock.json |
| Python | poetry.lock / uv.lock |
| Ruby | Gemfile.lock |
| Rust | cargo-auditable binaries |
| Go | go.mod |
| PHP | composer.lock |
| Java | pom.xml / *gradle.lockfile / *.sbt.lock |
| Dart | pubspec.lock |
DependencyTreeFlag 的定义位于 pkg/flag/report_flags.go。在解析阶段(pkg/flag/report_flags.go),若 --dependency-tree 与 --format table 之外的其他格式连用,会打印警告 "--dependency-tree" can be used only with "--format table"。
需要强调的是,这棵"来源树"是依赖图的反向结果:它不是告诉你"某个包依赖了谁",而是告诉你"某个有漏洞的间接依赖,是被谁一路带进来的"。当你想修复某个间接依赖的漏洞时,正是需要这种反向视角,才能定位到真正应该升级的那个顶层包。
命令行示例(仅显示 HIGH/CRITICAL 的漏洞并展示来源树):
$ trivy fs --severity HIGH,CRITICAL --dependency-tree /path/to/your_node_project
package-lock.json (npm)
=======================
Total: 2 (HIGH: 1, CRITICAL: 1)
┌──────────────────┬────────────────┬──────────┬───────────────────┬───────────────┬────────────────────────────────────────────────────────────┐
│ Library │ Vulnerability │ Severity │ Installed Version │ Fixed Version │ Title │
├──────────────────┼────────────────┼──────────┼───────────────────┼───────────────┼────────────────────────────────────────────────────────────┤
│ follow-redirects │ CVE-2022-0155 │ HIGH │ 1.14.6 │ 1.14.7 │ follow-redirects: Exposure of Private Personal Information │
├──────────────────┼────────────────┼──────────┼───────────────────┼───────────────┼────────────────────────────────────────────────────────────┤
│ glob-parent │ CVE-2020-28469 │ CRITICAL │ 3.1.0 │ 5.1.2 │ nodejs-glob-parent: Regular expression denial of service │
└──────────────────┴────────────────┴──────────┴───────────────────┴───────────────┴────────────────────────────────────────────────────────────┘
Dependency Origin Tree (Reversed)
=================================
package-lock.json
├── follow-redirects@1.14.6, (HIGH: 1, CRITICAL: 0)
│ └── axios@0.21.4
└── glob-parent@3.1.0, (HIGH: 0, CRITICAL: 1)
└── chokidar@2.1.8
└── watchpack-chokidar2@2.0.1
└── watchpack@1.7.5
└── webpack@4.46.0
└── cra-append-sw@2.7.0
读法要点:
- 有漏洞的包出现在树的最顶层;
- 下面的每一层展示"这个漏洞是被谁引入的"。
- 上例中,axios@0.21.4 是项目直接依赖,它直接引入了有漏洞的 follow-redirects@1.14.6;
- 而带漏洞的 glob-parent@3.1.0 则经过一条由 cra-append-sw@2.7.0 引入的完整依赖链才被带入项目。
据此你可以制定升级方案:升级 axios@0.21.4 以解决 follow-redirects 的漏洞;升级 cra-append-sw@2.7.0(或其替换)以解决 glob-parent 的漏洞,而不必盲目地逐个升级深层间接依赖。
JSON 格式
JSON 是机器可读、可二次处理的首选格式,四类 Scanner 全部支持:
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License | ✓ |
$ trivy image -f json -o results.json alpine:latest
-o 会把结果写入 results.json 文件而不是打印到标准输出。生成的 JSON 遵循统一的报告结构(顶层含 SchemaVersion、CreatedAt、ArtifactName、ArtifactType、Metadata、Results 等字段)。SchemaVersion 常量在源码中被定义为 2,见 pkg/report/writer.go。下面节选展示关键结构(省略了部分重复内容):
{
"SchemaVersion": 2,
"CreatedAt": "2024-12-26T21:58:15.943876+05:30",
"ArtifactName": "alpine:latest",
"ArtifactType": "container_image",
"Metadata": {
"OS": {
"Family": "alpine",
"Name": "3.20.3"
},
"ImageID": "sha256:511a44083d3a23416fadc62847c45d14c25cbace86e7a72b2b350436978a0450",
"DiffIDs": [
"sha256:651d9022c23486dfbd396c13db293af6845731cbd098a5f5606db4bc9f5573e8"
],
"RepoTags": [
"alpine:latest"
],
"RepoDigests": [
"alpine@sha256:1e42bbe2508154c9126d48c2b8a75420c3544343bf86fd041fb7527e017a4b4a"
]
},
"Results": [
{
"Target": "alpine:latest (alpine 3.20.3)",
"Class": "os-pkgs",
"Type": "alpine",
"Vulnerabilities": [
{
"VulnerabilityID": "CVE-2024-9143",
"PkgID": "libcrypto3@3.3.2-r0",
"PkgName": "libcrypto3",
"PkgIdentifier": {
"PURL": "pkg:apk/alpine/libcrypto3@3.3.2-r0?arch=aarch64&distro=3.20.3",
"UID": "f705555b49cd2259"
},
"InstalledVersion": "3.3.2-r0",
"FixedVersion": "3.3.2-r1",
"Status": "fixed",
"Severity": "LOW",
"CweIDs": ["CWE-787"],
"VendorSeverity": {
"amazon": 3,
"redhat": 1,
"ubuntu": 1
},
"CVSS": {
"redhat": {
"V3Vector": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:L",
"V3Score": 3.7
}
},
"PublishedDate": "2024-10-16T17:15:18.13Z",
"LastModifiedDate": "2024-11-08T16:35:21.58Z"
}
]
}
]
}
字段语义说明:
Vulnerabilities数组中的VulnerabilityID、PkgName、InstalledVersion、Severity总是会被填充,而其余字段(如Description、References、CVSS、CweIDs等)可能为空。Metadata.ImageConfig.history记录了镜像构建历史(含 BuildKit 注解与empty_layer标记),可用于追溯漏洞所在的构建层。Results[].Vulnerabilities[].Layer.DiffID标识该漏洞涉及文件所在的层。
另一个与 JSON 紧密相关的参数是 --list-all-pkgs:它默认值为 true,表示在 JSON 报告中无论是否有漏洞都列出全部软件包。在 pkg/flag/report_flags.go 中 ListAllPkgsFlag 定义其默认值为 true;同时解析逻辑(pkg/flag/report_flags.go)会对"显式指定 --list-all-pkgs 但格式不是 json"的情况给出提示——该选项对 JSON 之外格式无效,因为非 JSON 格式会自动包含包列表。对应实现为 pkg/report/writer.go 中的 JSONWriter。
SARIF 格式
SARIF(Static Analysis Results Interchange Format,静态分析结果交换格式)可以让 Trivy 的发现结果接入各类"代码扫描 / 静态分析"平台:
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License | ✓ |
$ trivy image --format sarif -o report.sarif golang:1.12-alpine
生成的 SARIF 文件遵循 SARIF 2.1.0 OASIS 标准。在 pkg/report/sarif.go 中可以看到实现确实以 sarif.New(sarif.Version210) 创建 SARIF 2.1.0 报告,并把 Trivy 版本写入 run.Tool.Driver。同时,对文件系统/仓库类型的扫描(ArtifactType 为 filesystem 或 repository),pkg/report/writer.go 还会把目标路径写入 SARIF 结果,方便在代码扫描 UI 中定位到具体文件。
生成的 SARIF 文件可以上传到多种平台,包括:
- GitHub code scanning(配合 Trivy 官方 GitHub Action 可自动化"扫描→上传 SARIF"的流程);
- SonarQube(在其"导入外部问题 / SARIF 报告"功能中使用)。
每个 SARIF 结果中都包含漏洞的 severity、受影响的包、修复版本、描述与帮助链接等富文本信息(见 pkg/report/sarif.go),便于在目标平台内直接阅读与跟进。
GitHub dependency snapshot 格式
如果希望把扫描得到的依赖清单同步进 GitHub 仓库的 Dependency Graph(依赖图),可以使用 GitHub 依赖快照格式:
Trivy 支持生成以下两类包来源的快照:
- OS packages(操作系统软件包)
- Language-specific packages(语言相关软件包)
(这两类包的具体检测范围可参考 scanner/vulnerability 文档 中的 OS 包与语言包章节。)
$ trivy image --format github -o report.gsbom alpine
得到的快照文件(report.gsbom)可以通过 GitHub Dependency Submission API 提交到你的 GitHub 仓库,从而让仓库的依赖图收录 Trivy 扫描到的依赖。该格式的 Writer 实现位于 pkg/report/github 目录。
Template 模板格式
Template 格式允许你完全自定义输出内容,非常适合对接内部系统、生成自定义格式的报告。四类 Scanner 全部支持:
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License | ✓ |
内联自定义模板
--format template 配合 --template "..." 可以把结果按给定 Go template 渲染。模板的数据源是扫描结果的 Results 数组,因此可以用 {{ range . }} 逐 Target 遍历:
$ trivy image --format template --template "{{ range . }} {{ .Target }} {{ end }}" golang:1.12-alpine
对应输出类似(首行为日志,其后每行一个 Target):
2020-01-02T18:02:32.856+0100 INFO Detecting Alpine vulnerabilities...
golang:1.12-alpine (alpine 3.10.2)
模板渲染由 pkg/report/template.go 的 TemplateWriter 负责,其中两处关键实现:
- 内置 Sprig 函数库:模板可调用 sprig 提供的全部函数(
add、sum、字符串处理等),见 pkg/report/template.go。 - 额外注入的专用函数:源码在 Sprig 基础上额外注册了
escapeXML、endWithPeriod、escapeString、sourceID、appVersion等帮助函数(pkg/report/template.go),供 JUnit/HTML 等模板转义与元数据填充使用。
例如,用 Sprig 的算术函数在模板内统计各类安全问题的数量:
$ trivy image --format template --template '{{- $critical := 0 }}{{- $high := 0 }}{{- range . }}{{- range .Vulnerabilities }}{{- if eq .Severity "CRITICAL" }}{{- $critical = add $critical 1 }}{{- end }}{{- if eq .Severity "HIGH" }}{{- $high = add $high 1 }}{{- end }}{{- end }}{{- end }}Critical: {{ $critical }}, High: {{ $high }}' golang:1.12-alpine
输出:
Critical: 0, High: 2
从文件加载模板
模板较长时更适合写在文件里,用 @ 前缀指向模板文件路径:
$ trivy image --format template --template "@/path/to/template.tpl" golang:1.12-alpine
模板文件必须以 .tpl 作为扩展名,这一点有强制的扩展名校验逻辑(见 pkg/flag/report_flags.go),不满足会直接报错 template file must have .tpl extension。同时 report.Write 中保留了对旧版 sarif.tpl 的向后兼容处理(pkg/report/writer.go),会在检测到该模板时提示改用 --format sarif 并打印弃用警告。
内置默认模板
如果 Trivy 是通过 rpm 包安装的,官方默认模板会位于 /usr/local/share/trivy/templates。此外,仓库中的 contrib 目录也随源码附带了一批可直接复用的官方模板,包括 junit.tpl、html.tpl、asff.tpl、gitlab.tpl、gitlab-codequality.tpl。
JUnit
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License | ✓ |
使用仓库自带的 contrib/junit.tpl 可以生成 JUnit XML,便于接入 Jenkins 等以 JUnit 为标准的 CI 测试报告系统:
$ trivy image --format template --template "@contrib/junit.tpl" -o junit-report.xml golang:1.12-alpine
ASFF(AWS Security Hub)
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | ✓ |
| License |
Trivy 还提供将发现结果上报到 AWS Security Hub 的 ASFF 模板(contrib/asff.tpl)。完整的端到端集成步骤(IAM 配置、区域与模板参数、与 AWS CLI 的配合等)请参考 tutorials/integrations/aws-security-hub.md。
HTML
| Scanner | Supported |
|---|---|
| Vulnerability | ✓ |
| Misconfiguration | ✓ |
| Secret | |
| License |
使用 contrib/html.tpl 生成带样式的 HTML 报告,适合通过邮件或 Web 页面分发人工审阅:
# 使用仓库源码自带的模板
$ trivy image --format template --template "@contrib/html.tpl" -o report.html golang:1.12-alpine
如果使用 rpm 安装的 Trivy,也可以用默认安装路径下的模板:
$ trivy image --format template --template "@/usr/local/share/trivy/templates/html.tpl" -o report.html golang:1.12-alpine
SBOM 格式
SBOM(软件物料清单)格式同样作为 Trivy 的输出格式之一被支持。由于 SBOM 的生成涉及较多专有概念(CycloneDX / SPDX、相关 flag、与 VEX 的配合等),完整的介绍见 supply-chain/sbom.md。在源码中,SupportedSBOMFormats(pkg/types/report.go)列出了 cyclonedx、spdx、spdx-json、github 四种可用于 SBOM 场景的格式。
输出目标:文件与输出插件
Trivy 支持两种结果落点:
- File(文件)
- Plugin(输出插件)
写入文件
通过 --output <file_path>(简写 -o)即可把报告写入指定文件。例如:
$ trivy image --format json --output result.json debian:12
底层实现位于 pkg/flag/options.go 的 OutputWriter:未指定 --output 时结果写到 os.Stdout;指定了普通路径时用 os.Create 创建文件并把清理函数绑定到文件关闭;如果文件创建失败会立即报错。
输出插件(Experimental)
EXPERIMENTAL(实验特性):该特性可能在不保证向后兼容的情况下变更,仅作实验用途。
若某插件支持从标准输入接收 Trivy 的扫描结果(这类插件被称为"output plugin"),就可以用 --output 参数以 plugin=<name> 的形式直接调用它,让 Trivy 把结果通过管道喂给插件:
$ trivy <target> [--format <format>] --output plugin=<plugin_name> [--output-plugin-arg <plugin_flags>] <target_name>
这种模式适用于两类场景:一是想把 Trivy 结果转换为自定义格式,二是想把结果直接发送到某个外部系统(消息队列、告警平台、内部 API 等)。--output-plugin-arg 用于把额外参数透传给插件(多个参数会被按 shell 语法切分,见 pkg/flag/report_flags.go)。
插件的具体开发与使用方式,请参考 plugin/user-guide.md。实现层面,pkg/flag/options.go 的 outputPluginWriter 通过 io.Pipe() 建立管道,Trivy 写入管道写端,插件进程从读端读取,待报告写完后再关闭管道并等待插件进程退出(wait()),从而保证插件完整消费输出。
使用 convert 子命令转换报告
有时你需要同时产出多份不同格式的报告。最经济的方式是:先扫描一次并保存 JSON 报告,然后用 convert 子命令把它二次转换为其他格式,无需再次执行扫描:
# 1. 首次扫描,输出并保存 JSON 报告
$ trivy image --format json -o result.json debian:11
# 2. 将 JSON 报告转换为 CycloneDX SBOM
$ trivy convert --format cyclonedx --output result.cdx result.json
过滤选项(例如 --severity)在 convert 中同样可用。因此你可以把"全量 JSON"作为单一事实来源,再按不同接收方生成不同视角的报告:
# 输出包含所有严重级别的 JSON 报告
$ trivy image --format json -o result.json debian:11
# 只输出 CRITICAL 级别问题的表格报告
$ trivy convert --format table --severity CRITICAL result.json
注意:来自
trivy k8s的 JSON 报告目前尚未被 convert 支持。从源码看,pkg/commands/convert/run.go 会通过ArtifactName/ArtifactType是否为空来判断报告来源,若为空则直接报错 "AWS and Kubernetes scanning reports are not yet supported"——即 AWS 与 Kubernetes 扫描生成的报告都无法用于 convert。
convert 的实现流程(pkg/commands/convert/run.go)可以总结为:
- 打开并
json.Decode目标文件到types.Report; - 调用
compat做版本兼容——为旧版 JSON 中缺失的包 UID 补齐dependency.UID(pkg/commands/convert/run.go),使新老版本的报告都能被正确过滤与引用; - 按用户传入的过滤条件(
--severity、--scanners等)对结果执行result.Filter; - 若目标格式为 table 且启用了 summary 模式,但未显式启用任何 scanner,则会提示 "To display the summary table, enable the scanners used during JSON report generation.",并自动移除 summary 模式(这正对应上文 Summary 表的 [^1] 注释);
- 调用
report.Write输出结果,最后根据是否存在失败项决定进程退出码。
小结与格式选型建议
- 人工排查、日常快速查看:使用默认的
table格式;需要聚焦总览就--table-mode summary,需要逐条核对就用detailed;要定位间接依赖引入的漏洞时加上--dependency-tree。 - 机器处理 / 存档 / 二次转换:使用
json,配合-o落盘,后续用trivy convert按需产出 CycloneDX、SPDX 或 table 等其他格式。 - 接入代码扫描平台:使用
sarif对接 GitHub code scanning 与 SonarQube。 - 同步依赖图:使用
github格式生成依赖快照并提交到 GitHub Dependency Graph。 - 对接内部系统 / 自定义报告:使用
template,可内联模板或@加载.tpl文件,并复用仓库 contrib 目录下的 JUnit、HTML、ASFF 等官方模板。 - 结果不落盘、直接投递:使用输出插件
--output plugin=<name>。
上述所有报告 flag 的默认值、取值范围与校验规则都收敛在 pkg/flag/report_flags.go,格式分发与写入在 pkg/report/writer.go,是进一步深挖 Trivy 报告行为的两个最佳入口。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00