资讯动态

Trivy SBOM 生成与扫描实战:CycloneDX 与 SPDX 双格式完整指南

发布时间:2026/9/10 20:12:29 来源:尧图企业网站定制
Trivy SBOM 生成与扫描实战CycloneDX 与 SPDX 双格式完整指南【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivySBOM软件物料清单是供应链安全的核心资产。Trivy 同时扮演生成者与消费者两种角色既能把容器镜像、文件系统、VM 镜像等目标解析为标准 CycloneDX/SPDX 格式的 SBOM也能把 SBOM 文档作为输入进行漏洞与许可证扫描还能在镜像内部自动发现内嵌的 SBOM 文件包括 Bitnami 镜像。读完本文你将掌握 Trivy 的 SBOM 生成命令、两种格式的输出结构、--scanners vuln等关键参数以及用trivy sbom消费 SBOM 的完整闭环。一、Trivy 与 SBOM生成与消费的双向能力在 Trivy 的供应链安全体系中SBOM 能力分为两个方向生成Generating对扫描目标运行常规子命令image、fs、vm、rootfs等通过--format选项输出标准 SBOM支持CycloneDX与SPDX两大格式族扫描Scanning把 SBOM 文档本身作为扫描目标trivy sbom子命令或让 Trivy 在容器镜像内自动发现内嵌的 SBOM 文件并复用其中的包信息用于漏洞与许可证检测。从源码看pkg/sbom/sbom.go 是这两种能力的枢纽它定义了全部 SBOM 格式常量FormatCycloneDXJSON、FormatSPDXJSON、FormatSPDXTV、attestation 与 Sigstore bundle 等 8 种以上格式并实现了DetectFormat自动格式识别——按顺序尝试 CycloneDX JSON → CycloneDX XML → SPDX JSON → SPDX tag-value → in-toto attestation → Sigstore bundle最后将任意输入解码为统一的types.SBOM中间模型。二、生成 SBOMCLI 命令与 --format 选项生成 SBOM 无需专门子命令直接复用扫描子命令并指定--format与--output即可# 生成 SPDX JSON 格式 $ trivy image --format spdx-json --output result.json alpine:3.15 # 生成 CycloneDX 格式 $ trivy fs --format cyclonedx --output result.json /app/myprojectimage、fs、rootfs、vm等子命令均支持--format生成 SBOM--output指定输出文件路径不指定时输出到标准输出与漏洞扫描不同生成 SBOM 时若未显式开启漏洞扫描器默认只做包清单提取详见下文 CycloneDX 部分。支持的软件包范围SBOM 中的组件覆盖两类包与漏洞扫描的包检测逻辑完全一致OS 包由系统包管理器apk、dpkg、yum等安装的包语言特定包由pip、npm、gem、Go modules 等生态安装的库。Trivy 对包检测有一套专门逻辑直接决定 SBOM 组件的完整度详见漏洞扫描中的包检测章节。值得注意的是--pkg-types os|library这类过滤选项会直接裁剪包清单本身因此同样影响 SBOM 生成结果参见漏洞扫描文档中的说明同理--pkg-relationships因可能无法提供完整包列表不可与 SBOM 生成同时使用。三、CycloneDX 格式默认输出 SBOM可选叠加 BOVTrivy 生成 CycloneDX 版本遵循cyclonedx-go库的规范实现生成时使用的 spec 版本由该库决定示例输出中可见specVersion1.3/1.5 两代结构差异。使用常规子命令加--format cyclonedx即可$ trivy image --format cyclonedx --output result.json alpine:3.15SBOM 与 BOV 两种能力CycloneDX 规范可以将物料清单区分为两种能力SBOMSoftware Bill of Materials描述软件组件清单BOVBill of Vulnerabilities在组件之上叠加漏洞信息。默认情况下--format cyclonedx只生成SBOM不包含漏洞。执行时 Trivy 会给出提示$ trivy image --format cyclonedx --output result.json alpine:3.15 2022-07-19T07:47:27.624Z INFO --format cyclonedx disables security scanning. Specify --scanners vuln explicitly if you want to include vulnerabilities in the CycloneDX report.如需在 CycloneDX 输出中包含漏洞即生成 BOV显式开启漏洞扫描即可$ trivy image --scanners vuln --format cyclonedx --output result.json alpine:3.15输出结构详解附源码印证以alpine:3.15为例CycloneDX JSON 输出核心结构如下省略重复组件{ bomFormat: CycloneDX, specVersion: 1.3, serialNumber: urn:uuid:2be5773d-7cd3-4b4b-90a5-e165474ddace, version: 1, metadata: { timestamp: 2022-02-22T15:11:40.270597Z, tools: [ { vendor: aquasecurity, name: trivy, version: dev } ], component: { bom-ref: pkg:oci/alpinesha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300?repository_urlindex.docker.io%2Flibrary%2Falpinearchamd64, type: container, name: alpine:3.15, purl: pkg:oci/alpinesha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300?repository_urlindex.docker.io%2Flibrary%2Falpinearchamd64, properties: [ { name: aquasecurity:trivy:SchemaVersion, value: 2 }, { name: aquasecurity:trivy:ImageID, value: sha256:c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18 }, { name: aquasecurity:trivy:RepoDigest, value: alpinesha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300 }, { name: aquasecurity:trivy:DiffID, value: sha256:8d3ac3489996423f53d6087c81180006263b79f206d3fdec9e66f0e27ceb8759 }, { name: aquasecurity:trivy:RepoTag, value: alpine:3.15 } ] } }, components: [ { bom-ref: pkg:apk/alpine/alpine-baselayout3.2.0-r18?distro3.15.0, type: library, name: alpine-baselayout, version: 3.2.0-r18, licenses: [{ expression: GPL-2.0-only }], purl: pkg:apk/alpine/alpine-baselayout3.2.0-r18?distro3.15.0, properties: [ { name: aquasecurity:trivy:SrcName, value: alpine-baselayout }, { name: aquasecurity:trivy:SrcVersion, value: 3.2.0-r18 }, { name: aquasecurity:trivy:LayerDigest, value: sha256:59bf1c3509f33515622619af21ed55bbe26d24913cedbca106468a5fb37a50c3 }, { name: aquasecurity:trivy:LayerDiffID, value: sha256:8d3ac3489996423f53d6087c81180006263b79f206d3fdec9e66f0e27ceb8759 } ] }, ...(snip)... { bom-ref: 3da6a469-964d-4b4e-b67d-e94ec7c88d37, type: operating-system, name: alpine, version: 3.15.0, properties: [ { name: aquasecurity:trivy:Type, value: alpine }, { name: aquasecurity:trivy:Class, value: os-pkgs } ] } ], dependencies: [ { ref: 3da6a469-964d-4b4e-b67d-e94ec7c88d37, dependsOn: [ pkg:apk/alpine/alpine-baselayout3.2.0-r18?distro3.15.0, pkg:apk/alpine/busybox1.34.1-r3?distro3.15.0, pkg:apk/alpine/zlib1.2.11-r3?distro3.15.0 ] }, { ref: pkg:oci/alpinesha256:21a3deaa0d32a8057914f36584b5288d2e5ecc984380bc0118285c70fa8c9300?repository_urlindex.docker.io%2Flibrary%2Falpinearchamd64, dependsOn: [3da6a469-964d-4b4e-b67d-e94ec7c88d37] } ] }各区块含义与源码实现对应如下区块含义源码印证metadata.tools生成工具的厂商、名称与版本pkg/sbom/cyclonedx/marshal.go 中Metadata()方法写入aquasecurity/trivy及 Trivy 版本新版本中tools以components数组type: application形式呈现metadata.component扫描目标根组件如容器镜像附带aquasecurity:trivy:命名空间的自定义属性ImageID、RepoDigest、LayerDiffID 等MarshalRoot()从core.BOM.Root()取出根组件属性命名空间前缀aquasecurity:trivy:定义于同一文件的Namespace常量components包清单每个包带bom-refPURL、类型、版本、许可证表达式、文件哈希及 Trivy 私有属性marshalComponents()将内部组件模型转换为 CycloneDX 组件并按bom-ref排序dependencies依赖关系图marshalDependencies()基于组件间RelationshipDependsOn关系生成vulnerabilities漏洞清单仅开启--scanners vuln时出现marshalVulnerabilities()聚合同一漏洞影响的多个组件合并升级建议CVSSv2/v3/v4 分别映射评分方法见ratingV2/ratingV3/ratingV4开启漏洞扫描后vulnerabilities区块中的单个漏洞结构示例{ id: CVE-2021-42386, source: { name: alpine }, ratings: [ { source: { name: nvd }, score: 7.2, severity: high, method: CVSSv31, vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:H/I:H/A:H } ], cwes: [416], description: A use-after-free in Busyboxs awk applet..., advisories: [ { url: https://access.redhat.com/security/cve/CVE-2021-42386 } ], published: 2021-11-15 21:15:00 0000 UTC, updated: 2022-01-04 17:14:00 0000 UTC, affects: [ { ref: pkg:apk/alpine/busybox1.33.1-r3?distro3.14.2 } ] }局限XML 格式暂不支持目前 Trivy 生成与解析 CycloneDX 均只支持JSONXML 格式暂不支持pkg/sbom/sbom.go虽然定义了FormatCycloneDXXML用于识别既有 XML 文档但生成侧不输出 XML扫描侧也明确拒绝该格式。此外从pkg/report/cyclonedx/cyclonedx.go可看到输出由cdx.NewBOMEncoder编码为美化prettyJSON这也是结果便于阅读的原因。四、SPDX 格式tag-value 与 JSON 两种子格式Trivy 支持 SPDX 规范的两种序列化形式使用常规子命令加--format spdx或--format spdx-json指定# SPDX tag-value 格式 $ trivy image --format spdx --output result.spdx alpine:3.15 # SPDX JSON 格式 $ trivy image --format spdx-json --output result.spdx alpine:3.15从 pkg/report/spdx/spdx.go 可看到spdx-json使用json.MarshalIndent输出人类可读的多行 JSONspdx则通过tagvalue.Write写出 tag-value 文本。tag-value 格式示例SPDXVersion: SPDX-2.3 DataLicense: CC0-1.0 SPDXID: SPDXRef-DOCUMENT DocumentName: alpine:3.15 DocumentNamespace: http://trivy.dev/container_image/alpine:3.15-12db86e1-4aa4-40ec-900b-5aaa5d82461b Creator: Organization: aquasecurity Creator: Tool: trivy-0.58.0 Created: 2025-02-11T07:43:38Z ##### Package: alpine:3.15 PackageName: alpine:3.15 SPDXID: SPDXRef-ContainerImage-d8b2a386253047e7 PackageDownloadLocation: NONE PrimaryPackagePurpose: CONTAINER FilesAnalyzed: false ExternalRef: PACKAGE-MANAGER purl pkg:oci/alpinesha256%3A19b4bcc4f60e99dd5ebdca0cbce22c503bbcff197549d7e19dab4f22254dc864?archamd64repository_urlindex.docker.io%2Flibrary%2Falpine ##### Package: libretls PackageName: libretls SPDXID: SPDXRef-Package-343391d704e00fbd PackageVersion: 3.3.4-r3 PackageSupplier: NOASSERTION PackageDownloadLocation: NONE PrimaryPackagePurpose: LIBRARY FilesAnalyzed: false PackageChecksum: SHA1: 67dfefe5456c45192b60d76ade98c501b0ae814f PackageSourceInfo: built package from: libretls 3.3.4-r3 PackageLicenseConcluded: ISC AND BSD-3-Clause AND MIT PackageLicenseDeclared: ISC AND BSD-3-Clause AND MIT ExternalRef: PACKAGE-MANAGER purl pkg:apk/alpine/libretls3.3.4-r3?archx86_64distro3.15.11 ##### Relationships Relationship: SPDXRef-ContainerImage-d8b2a386253047e7 CONTAINS SPDXRef-OperatingSystem-c24750c3b737d897 Relationship: SPDXRef-DOCUMENT DESCRIBES SPDXRef-ContainerImage-d8b2a386253047e7 Relationship: SPDXRef-OperatingSystem-c24750c3b737d897 CONTAINS SPDXRef-Package-343391d704e00fbd Relationship: SPDXRef-Package-343391d704e00fbd DEPENDS_ON SPDXRef-Package-ee9b5186331e7a76要点解读文档头声明SPDX-2.3规范版本、CC0-1.0数据许可证Creator记录生成工具为aquasecuritytrivy-版本每个组件镜像、操作系统、库对应一个##### Package块通过SPDXID唯一标识ExternalRef携带 PURL组件间关系通过Relationship表达CONTAINS镜像包含 OS、OS 包含包与DEPENDS_ON包间依赖PrimaryPackagePurpose区分CONTAINER、OPERATING-SYSTEM、LIBRARY等用途。JSON 格式示例spdx-json输出等价信息的结构化 JSON顶层spdxVersion/dataLicense/SPDXID/documentNamespace声明文档元数据packages数组逐项给出名称、版本、supplier、checksumsSHA1、licenseConcluded/licenseDeclared、externalRefsPURL及annotationsTrivy 附加的 ImageID、RepoDigest、LayerDiffID、PkgType 等注释relationships数组以spdxElementId/relatedSpdxElement/relationshipType三元组表达与 tag-value 一致的关系图。SPDX 输出不含漏洞与 CycloneDX 可叠加漏洞不同SPDX 是纯 SBOM 输出不包含漏洞信息漏洞扫描与 SPDX 输出通常作为两步使用先出 SBOM再以 SBOM 为输入扫描见下文。五、扫描 SBOMtrivy sbom 子命令以 SBOM 文档为扫描目标Trivy 可以把 SBOM 文档直接作为扫描输入通过sbom子命令指定路径即可输入格式自动检测无需手工声明$ trivy sbom /path/to/sbom_file支持的输入格式详见SBOM 扫描目标文档CycloneDXJSONXML 暂不支持SPDX tag-value 与 SPDX JSONCycloneDX 类型的 in-toto attestationCycloneDX 格式的 KBOMKubernetes 物料清单默认执行漏洞扫描可通过--scanners组合或单独选择许可证扫描$ trivy sbom --scanners vuln,license /path/to/sbom_file $ trivy sbom --scanners license /path/to/sbom_file一个典型的生成 → 再扫描闭环$ trivy image --format spdx-json --output spdx.json alpine:3.16.0 $ trivy sbom spdx.json2022-09-15T21:32:27.1680300 INFO Vulnerability scanning is enabled 2022-09-15T21:32:27.1690300 INFO Detected SBOM format: spdx-json 2022-09-15T21:32:27.2100300 INFO Detected OS: alpine 2022-09-15T21:32:27.2110300 INFO Number of language-specific files: 0 spdx.json (alpine 3.16.0) Total: 5 (UNKNOWN: 0, LOW: 0, MEDIUM: 2, HIGH: 2, CRITICAL: 1)重要提示如果 SBOM 由其他工具生成而非 Trivy 产出检测结果可能不准确——因为 Trivy 的精确扫描依赖其写入 SBOM 的自定义属性如aquasecurity:trivy:前缀属性。源码中这一判断体现在 pkg/sbom/cyclonedx/unmarshal.go 的IsTrivySBOM()解析时若检测到metadata.tools中无 Trivy 工具标识会告警 Third-party SBOM may lead to inaccurate vulnerability detection。扫描 SBOM attestationTrivy 还支持扫描由 Sigstore/Cosign 生成的 CycloneDX 类型 in-toto attestation先经cosign verify-attestation取回再交给 Trivy$ cosign verify-attestation --key /path/to/cosign.pub --type cyclonedx IMAGE sbom.cdx.intoto.jsonl $ trivy sbom ./sbom.cdx.intoto.jsonl在pkg/sbom/sbom.go的Decode中attestation、Sigstore bundle 及旧版 Cosignv1 的legacy-cosign变体都会被逐层解包DSSE envelope → in-toto statement → SBOM转换为统一内部模型后扫描。关于如何用cosign attest为镜像附加 SBOM attestation可参考供应链 SBOM attestation 文档。六、目标内 SBOM 检测SBOM Discovery自动发现的文件扩展名扫描容器镜像等目标时Trivy 会自动搜索并解析镜像内嵌的 SBOM 文件识别以下扩展名.spdx.spdx.json.cdx.cdx.json该逻辑实现在 pkg/fanal/analyzer/sbom/sbom.go 的requiredSuffixes中每个命中文件都会先经sbom.DetectFormat做内容级格式探测再解码为包清单合并进扫描结果。同时该分析器对.dist-info/sboms/目录下的 PEP 770 内嵌 SBOM 做了排除由 Python packaging 分析器另行处理避免重复解析。Bitnami 镜像支持除通用扩展名外Trivy自动检测 Bitnami 镜像中的 SBOMBitnami 容器镜像会在/opt/bitnami/component/下内置命名为.spdx-component.spdx的 SPDX 文件。源码中当文件路径以opt/bitnami/开头时会调用handleBitnamiImages修正应用与包文件的相对路径。这使 Trivy 能够检出 Nginx 等非包管理器安装的主应用漏洞详见Bitnami 镜像支持文档。各目标启用情况内嵌 SBOM 检测并非所有目标默认开启各目标支持情况如下目标启用Container Image✓FilesystemRootfs✓Git RepositoryVM Image✓KubernetesAWSSBOM容器镜像的 SBOM Discovery扫描容器镜像时Trivy 还能基于镜像自身发现对应的 SBOM包括 OCI 镜像清单中关联的 SBOM artifact以及镜像层内嵌文件两种途径详见容器镜像扫描目标文档。这意味着即使你手上只有镜像、没有单独维护 SBOM 文件扫描链路也能完整复用物料清单信息。七、进阶用 trivy convert 离线转换报告如果你已有一份 JSON 报告希望再补一份 CycloneDX SBOM无需重新扫描可用convert子命令离线转换$ trivy image --format json -o result.json debian:11 $ trivy convert --format cyclonedx --output result.cdx result.jsonconvert同样支持--severity等过滤选项适合在 CI 中一次扫描、多格式产出详见报告配置文档。八、延伸阅读围绕 SBOM 主题仓库内可直接继续深挖的资源SBOM 扫描目标文档trivy sbom的全部输入格式、attestation 与 KBOM 扫描示例漏洞扫描文档OS 包与语言包检测、--detection-priority、--pkg-types对 SBOM 的影响SBOM attestation 文档Cosign 签名/无密钥签名与扫描闭环Bitnami 镜像支持文档镜像内嵌 SBOM 的解析细节与漏洞数据源核心实现pkg/sbom/sbom.go格式常量与自动检测、pkg/sbom/cyclonedx/marshal.goCycloneDX 生成、pkg/report/spdx/spdx.goSPDX 输出、pkg/fanal/analyzer/sbom/sbom.go镜像内 SBOM 发现。【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价