适用于您的 SBOM 的 git diff。 比较两份软件物料清单 (SBOM),查看构建、版本和发布之间发生了什么变化。
sbomlyze 比较组件哈希,而不仅仅是版本字符串。当攻击者在未升级版本的情况下替换软件包时,sbomlyze 会将其标记出来。生成器和漏洞扫描器会错过这一点。
[![CI][ci-img]][ci] [![GitHub Marketplace][marketplace-img]][marketplace] [![GitHub Release][release-img]][release] [![Go Report Card][go-report-img]][go-report] [![OpenSSF Scorecard][scorecard-img]][scorecard] [![License: Apache-2.0][license-img]][license] [![Downloads][download-img]][download]
在清单差异 vs. SBOM 差异 vs. 完整性漂移中了解为什么该信号与清单或普通组件差异不同。
生成器生成 SBOM,扫描器发现 CVE。sbomlyze 告诉你两份 SBOM 之间发生了什么变化,以及是否值得信任。 在生成器之后运行它:
syft image:tag -o cyclonedx-json | sbomlyze - --compliance可在不创建临时文件的情况下分析并评分生成的 SBOM。将其与基线进行比较,以对漂移进行分类并为你流水线设置门控。
添加 [来自 GitHub Marketplace 的 SBOMlyze Diff][marketplace],以将已检入或单独生成的 SBOM 与其 git 基线进行比较。下面的不可变 SHA 是已发布的 v0.5.1 Action:```yaml
steps:
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0
uses: rezmoss/sbomlyze@31503690611fda8ebba4ed2bd186eda000442594 # v0.5.1 with: sbom-path: build/sbom.cdx.json
默认情况下,Action 会写入 Job Summary,并可强制执行策略、报告
完整性漂移、上传 SARIF,或维护单条拉取请求评论。请参阅
[完整 Action 参考](https://github.com/rezmoss/sbomlyze/blob/HEAD/ACTION.md) 了解输入、输出、权限,
以及安全指南。请参阅
[在线演示仓库](https://github.com/rezmoss/sbomlyze-action-demo)
查看通过依赖更新和受阻的同版本哈希变更,其中包含
公开工作流运行记录和 SARIF 证据。
如需按特定格式进行自测,请使用公共
[Go + SPDX](https://github.com/rezmoss/sbomlyze-go-spdx-demo),
[Node + CycloneDX](https://github.com/rezmoss/sbomlyze-node-cyclonedx-demo),或
[container](https://github.com/rezmoss/sbomlyze-container-demo) 示例。每个
示例都包含五个可复现的审查场景。
[10 分钟 Beta 指南](https://github.com/rezmoss/sbomlyze/blob/HEAD/BETA.md) 汇总了四个重点的激活与信号
质量问题。
生成的 SBOM 无需提交:`baseline: workflow-artifact`
会从一次成功的默认分支
运行中检索最新的匹配工件。一个 [固定的 Syft 伴生工作流](https://github.com/rezmoss/sbomlyze/blob/HEAD/examples/workflows/syft-companion.yml)
展示了生成和基线发布,而 SBOMlyze 仍负责
审查和策略。
## 为什么选择 sbomlyze?
许多工具都能生成 SBOM。只有少数工具会进行比较,更少的工具能告诉你某个变更是常规更新还是供应链危险信号。sbomlyze 填补了这一空白。
| 能力 | **sbomlyze** | cyclonedx-cli | sbomqs | syft / trivy |
|---|:---:|:---:|:---:|:---:|
| SBOM 到 SBOM **差异** | ✅ | 基础 | ❌ | ❌ |
| **完整性 / 篡改**漂移(哈希变化但版本未变) | ✅ | ❌ | ❌ | ❌ |
| 依赖图差异 + 传递深度风险 | ✅ | ❌ | ❌ | ❌ |
| **NTIA / CISA / BSI** 合规评分 | ✅ | ❌ | ✅ | ❌ |
| 格式转换(Syft / CycloneDX / SPDX) | ✅ | ✅ | ❌ | 部分 |
| **TUI + Web UI** 探索器 | ✅ | ❌ | ❌ | ❌ |
| 策略门禁 + SARIF / JUnit / Markdown / HTML / Patch | ✅ | 部分 | 部分 | 部分 |
## 功能特性
- **SBOM 差异比较**:比较两个 SBOM,一目了然地查看新增、移除和变更的组件
- **漂移分类**:区分版本漂移与**完整性漂移**(哈希值在版本未变时发生变化,可能表明被篡改)以及元数据漂移
- **合规评分**:根据 **NTIA**、**CISA 2025** 和 **BSI TR-03183** 最低要素对任意 SBOM 进行评分
- **依赖图差异**:追踪传递依赖和供应链深度
- **多格式支持**:Syft、CycloneDX、SPDX(JSON)
- **格式转换**:在 CycloneDX、SPDX 和 Syft 格式之间转换
- **强身份匹配**:PURL → CPE → BOM-ref → 命名空间/名称优先级
- **统计模式**:分析单个 SBOM 的许可证、依赖和完整性指标
- **交互式 TUI 模式**:通过键盘导航和搜索浏览 SBOM
- **Web UI 模式**:基于浏览器的 SBOM 探索器,支持拖放上传
- **策略引擎**:在 CI 流水线中强制执行漂移、许可证和合规评分规则
- **GitHub Marketplace Action**:通过 Job Summary、SARIF 和可选评论输出,在 SBOM 漂移上对拉取请求进行门控
- **重复与冲突检测**:发现同一包的多个版本以及模糊的身份匹配
- **多种输出格式**:Text、JSON、SARIF、JUnit XML、Markdown、HTML、JSON Patch
- **容错解析**:出错时继续运行,并给出结构化警告
## 安装
### Homebrew (macOS/Linux)```bash
brew install rezmoss/sbomlyze/sbomlyze
安装脚本会根据你的操作系统/架构下载对应的二进制文件:```bash
curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sh
curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sudo sh -s -- -b /usr/local/bin
curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sh -s -- -v 0.4.0
**安装程序选项:**
| 选项 | 描述 |
|------|------|
| `-b <dir>` | 安装目录(默认:`./bin`) |
| `-d` | 启用调试输出 |
| `-v <ver>` | 安装特定版本(默认:最新) |
安装程序始终验证发行版的校验和。当安装了兼容的 GitHub CLI 时,它还会验证发行版的构建来源,如果验证未成功,则会安全终止。
### Go 安装```bash
go install github.com/rezmoss/sbomlyze/cmd/sbomlyze@latest
从 GitHub Releases 下载最新的二进制文件。
从 v0.3.7 开始,发布归档会随附 GitHub 工件证明(artifact attestations)。如需独立验证下载,请使用:```bash
gh attestation verify ./sbomlyze_0.4.0_Linux_x86_64.tar.gz
--repo rezmoss/sbomlyze
--signer-workflow rezmoss/sbomlyze/.github/workflows/release.yml
未签名的 apt、rpm 和 apk 仓库说明已被移除,直到
这些仓库支持包管理器原生的签名验证为止。
**macOS 用户:** 下载后请移除隔离标志:```bash
xattr -d com.apple.quarantine ./sbomlyze
chmod +x ./sbomlyze
git clone https://github.com/rezmoss/sbomlyze.git cd sbomlyze go build -o sbomlyze ./cmd/sbomlyze
## 快速开始```bash
# Compare two SBOMs (the headline use case)
sbomlyze before.json after.json
# Analyze a single SBOM
sbomlyze image.json
# Read an SBOM from standard input
syft image:tag -o cyclonedx-json | sbomlyze -
# Use standard input on either side of a diff
syft image:tag -o cyclonedx-json | sbomlyze baseline.json -
# Score an SBOM against NTIA / CISA / BSI minimum elements
sbomlyze image.json --compliance
# Interactive TUI explorer
sbomlyze image.json -i
# Web UI (opens browser)
sbomlyze -web
# Convert between SBOM formats
sbomlyze convert syft.json --to spdx
sbomlyze convert cdx.json --to syft -o output.json
# JSON output for CI integration
sbomlyze before.json after.json --json
# SARIF output for GitHub Code Scanning
sbomlyze before.json after.json --format sarif
# Markdown report for PR comments
sbomlyze before.json after.json --format markdown
# Apply policy checks
sbomlyze before.json after.json --policy policy.json
sbomlyze <sbom1|-> [sbom2|-] [options] sbomlyze convert <sbom|-> --to [-o output]
Modes: Single file: sbomlyze [--json] Show statistics Interactive: sbomlyze -i Interactive explorer Convert: sbomlyze convert --to Convert SBOM format Web server: sbomlyze -web [--port 8080] Web UI explorer Two files: sbomlyze [...] Show diff
Use - in place of one SBOM path to read it from standard input.
Options: -i, --interactive Interactive TUI explorer -web, --web Start web UI server --port Web server port (default 8080) --json Output in JSON format (shortcut for --format json) --format Output format: text, json, sarif, junit, markdown, html, patch --compliance Show NTIA/CISA/BSI compliance scoring --policy Policy file for CI checks --strict Fail on parse warnings --tolerant Continue on parse warnings (default) --no-pager Disable automatic paging of output --to Target format for convert: cyclonedx (cdx), spdx, syft -o, --output Output file for convert (default: stdout) --version, -v Show version information --help, -h Show this help message
## 命令
### 统计模式(单个文件)
分析 SBOM 以获取有关组件、许可证和依赖项的见解。```bash
sbomlyze image.json
输出包括扫描上下文、自动检测的关键发现和统计信息:``` Scan Context: Tool: syft 1.40.1 Schema: 16.0.18 Scan Scope: all-layers Source Type: image Source: alpine:latest
Key Findings: 💻 OS/Distro: Alpine Linux v3.21 📦 Dominated by apk: 71 of 71 packages (100.0%) 📂 8,542 files tracked on filesystem 🔗 Relationships: 71 containment + 64 dependency 📜 License profile: 72% permissive, 20% copyleft ⚠️ Low hash coverage: 0.0% (71 of 71 missing) 🔍 Top catalogers: apkdb-cataloger (71)
Total Components: 71
By Package Type: apk 71
Licenses: With license: 71 Without license: 0
Top Licenses: MIT 17 BSD-3-Clause 8 GPL-2.0-only 8
Integrity: With hashes: 0 Without hashes: 71
Dependencies: Components with deps: 65 Total dep relations: 176
#### 主要发现
sbomlyze 会自动生成有关您的 SBOM 的洞察。对于单文件分析,这些洞察包括:
| 发现 | 描述 |
|---------|-------------|
| **操作系统/发行版检测** | 从 SBOM 元数据中识别操作系统或发行版 |
| **主导生态系统** | 当一种包类型占主导地位(超过所有包的 60%)时进行报告 |
| **文件系统占用** | 文件系统上被跟踪文件的数量 |
| **关系密度** | 包含关系和依赖关系的计数 |
| **位置热点** | 组件所在的顶级目录 |
| **许可证风险概况** | 宽松/著佐权/未知许可证百分比的细分 |
| **数据质量警告** | 当许可证(<50%)、哈希(<50%)或 PURL(<80%)覆盖率较低时发出警报 |
| **重复警告** | 标记重复的组件组 |
| **目录器细分** | 检测组件的顶级扫描仪/目录器(Syft SBOM) |
#### 覆盖率指标
统计模式计算用于数据质量评估的覆盖率百分比:
| 指标 | 描述 |
|--------|-------------|
| **PURL 覆盖率** | 具有软件包 URL 的组件百分比 |
| **CPE 覆盖率** | 具有 CPE 的组件百分比(漏洞扫描就绪度) |
| **许可证覆盖率** | 至少具有一个许可证的组件百分比 |
| **哈希覆盖率** | 具有完整性哈希的组件百分比 |
#### 许可证分类
许可证会自动分类为:
| 类别 | 示例 |
|----------|----------|
| **著佐权** | GPL, LGPL, AGPL, MPL, EPL, CDDL |
| **宽松** | MIT, BSD, Apache, ISC, Zlib, Unlicense |
| **公共领域** | 公共领域奉献 |
| **未知** | 未识别或缺失的许可证 |
### 转换模式
在 CycloneDX、SPDX 和 Syft JSON 格式之间转换 SBOM。输入格式会自动检测。```bash
# CycloneDX to SPDX
sbomlyze convert image.cdx.json --to spdx
# Syft to CycloneDX (cdx is an alias for cyclonedx)
sbomlyze convert syft-output.json --to cdx
# SPDX to Syft, writing to a file
sbomlyze convert spdx-output.json --to syft -o converted.json
转换会保留组件名称、版本、PURL、CPE、许可证、哈希、供应商信息和依赖关系。格式特定字段(例如 Syft 的 language、foundBy、locations)在转换为 CDX 时会通过 CycloneDX 属性传递。
比较两个 SBOM,查看版本之间发生了哪些变化。```bash sbomlyze v1.0.json v2.0.json
#### Diff 概览
diff 以并排的元数据比较开始(文件名、大小、操作系统信息、工具信息、组件数量),随后在可用时提供扫描上下文详细信息。
#### 输出```
📊 Drift Summary:
📦 Version drift: 58 components
⚠️ Integrity drift: 1 component (hash changed without version change!)
📝 Metadata drift: 2 components
🔑 Key Findings:
📈 Attack surface: +5 packages (7.0%), +120 files (3.2%)
🚨 2 version downgrades detected: openssl 3.1.4→3.0.2, curl 8.5.0→8.4.0
🔄 56 version upgrades (2 major, 12 minor, 42 patch) among 65 shared packages
⚠️ Integrity drift (1 total): 1 npm (review recommended)
❌ python ecosystem entirely removed (15 → 0 packages)
➕ New ecosystem: golang (8 packages)
✅ Core system packages stable: apk (71) unchanged
+ Added (2):
+ libgcrypt 1.10.3-r0
+ libgpg-error 1.49-r0
- Removed (3):
- libapk 3.0.3-r1
- libgcc 15.2.0-r2
- nghttp3 1.13.1-r0
~ Changed (58):
~ nginx
version: 1.29.4-r1 -> 1.27.3-r1
~ suspicious-pkg ⚠️ [INTEGRITY]
hash[SHA256]: abc123 -> def456
>> Added dependencies:
pkg:apk/alpine/libxslt: +[so:libgcrypt.so.20]
<< Removed dependencies:
pkg:apk/alpine/libcurl: -[so:libnghttp3.so.9]
🔗 New transitive dependencies (3):
+ pkg:npm/lodash (depth 2)
via: [pkg:npm/my-app pkg:npm/express pkg:npm/lodash]
+ pkg:npm/underscore (depth 3)
via: [pkg:npm/my-app pkg:npm/express pkg:npm/lodash pkg:npm/underscore]
📊 New deps by depth:
Depth 2: 1
Depth 3+ (risky): 2 ⚠️
在 diff 模式下,sbomlyze 会自动生成更丰富的洞察,对两个 SBOM 进行比较:
新增和移除的组件按包类型分组,并附带样本列表,便于查看每个生态系统中发生的变化。
根据三大最低要素框架对任意 SBOM 进行评分,以回答审计师和采购团队一直追问的问题:"这个 SBOM 足够完整吗?"```bash
sbomlyze image.json --compliance
sbomlyze before.json after.json --compliance
sbomlyze image.json --compliance --json
### Frameworks Evaluated
| 框架 | 检查项 | 值得注意的要求 |
|-----------|--------|----------------------|
| **NTIA Minimum Elements** (2021) | 7 | 名称、版本、供应商、唯一 ID(PURL/CPE)、依赖关系、SBOM 作者、时间戳 |
| **CISA 2025 Minimum Elements**(2025 年 8 月草案) | 10 | 在 NTIA 基础上增加了软件生产者、许可证信息、**组件哈希**和工具名称 |
| **BSI TR-03183-2** (v2.1.0, 2025) | 9 | 要求提供组件创建者联系方式、**SHA-512 哈希**、SPDX 格式许可证和 SBOM 创建者联系方式 |
### 评分展示
每个框架都会报告一个百分比(通过的检查项 / 总检查项)以及一个总体得分(各框架的平均值),并带有状态指示器:
| 指示器 | 得分 |
|-----------|-------|
| 🟢 | ≥ 90% |
| 🟡 | 70–89% |
| 🟠 | 50–69% |
| 🔴 | < 50% |
JSON 输出(`--compliance --json`)包含完整的报告,并带有逐项检查的通过/失败详情;HTML 格式则将合规性报告嵌入报告页面。
### CI 中的合规性门控
通过[策略引擎](#policy-engine)强制执行合规性阈值。设置任何阈值都会触发合规性评估,无需使用 `--compliance` 标志:```json
{
"min_ntia_score": 85,
"min_cisa_score": 70,
"min_bsi_score": 80,
"min_overall_compliance": 75
}
未提供待翻译的 Markdown 内容。请补充输入。```bash sbomlyze image.json --policy compliance-policy.json
## 依赖图差异
sbomlyze 不仅分析简单的组件列表差异,还会分析完整的依赖图,检测通过传递依赖引入的供应链风险。
### 功能
| 功能 | 描述 |
|---------|-------------|
| **边差异** | 新增/移除的直接依赖(A 依赖 B) |
| **传递可达性** | 通过依赖图出现的新间接依赖 |
| **传递依赖丢失跟踪** | 被移除的传递依赖 |
| **路径跟踪** | 精确显示每个新传递依赖是如何被引入的 |
| **深度跟踪** | 每个新依赖距离你的代码有多少跳 |
| **风险摘要** | 深度 3 级及以上的依赖被标记为更高风险 |
### 为什么深度很重要
在依赖图中更深层引入的依赖:
- 更难以审计和审查
- 通常未经明确批准就会被引入
- 供应链攻击的常见载体(例如 event-stream 事件)
深度摘要有助于确定审查的优先级:
| 深度 | 风险等级 | 描述 |
|-------|------------|-------------|
| **1** | 低 | 直接依赖(你自己选择的) |
| **2** | 中 | 你依赖项的依赖项 |
| **3+** | 高 ⚠️ | 深层传递依赖 - 请仔细审查 |
### 示例:检测深层传递依赖```bash
# Before: app -> express (simple, 1 dep)
# After: app -> express -> lodash -> underscore -> deep-lib (chain of 4)
sbomlyze before.json after.json
输出:``` 🔗 New transitive dependencies (3):
📊 New deps by depth: Depth 2: 1 Depth 3+ (risky): 2 ⚠️
### 依赖图的 JSON 输出```json
{
"dependencies": {
"added_deps": {
"pkg:npm/express": ["pkg:npm/lodash", "pkg:npm/body-parser"]
},
"removed_deps": {},
"transitive_new": [
{
"target": "pkg:npm/underscore",
"via": ["pkg:npm/my-app", "pkg:npm/express", "pkg:npm/lodash", "pkg:npm/underscore"],
"depth": 3
}
],
"transitive_lost": [],
"depth_summary": {
"depth_1": 0,
"depth_2": 2,
"depth_3_plus": 2
}
}
}
sbomlyze 将组件变更分为三种漂移类型,帮助您区分正常更新和潜在的可疑变更。
当组件的哈希发生变化但其版本保持不变时,就会发生完整性漂移。这可能表明:
~ suspicious-pkg ⚠️ [INTEGRITY] hash[SHA256]: abc123 -> def456
**建议**:始终调查完整性漂移。它可能是良性的,但它是供应链安全的关键信号。
### 漂移的 JSON 输出
漂移摘要位于 `diff` 对象中:```json
{
"diff": {
"changed": [
{
"id": "pkg:npm/suspicious-pkg",
"name": "suspicious-pkg",
"changes": ["hash[SHA-256]: abc123 -> def456"],
"drift": {
"type": "integrity",
"hash_changes": {
"changed": {
"SHA-256": {"before": "abc123", "after": "def456"}
}
}
}
}
],
"drift_summary": {
"version_drift": 55,
"integrity_drift": 1,
"metadata_drift": 2
}
}
}
提取漂移摘要:```bash
sbomlyze before.json after.json --json | jq '.diff.drift_summary'
sbomlyze before.json after.json --json | jq -e '.diff.drift_summary.integrity_drift > 0'
## 重复与冲突检测
### 重复检测
sbomlyze 识别 SBOM 中具有相同身份但不同版本的组件:```
⚠️ Duplicates Found: 2
lodash: [4.17.20, 4.17.21]
express: [4.18.0, 4.19.2]
在 diff 模式下,重复版本的差异跟踪包括:
冲突是指组件共享相同的 ID 但具有冲突特征的模糊身份匹配:
| 类型 | 描述 |
|---|---|
| 名称不匹配 | 不同组件名称映射到同一身份 ID |
| 哈希不匹配 | 同一组件版本具有不同的哈希(可能存在篡改) |
sbomlyze sbom.json -i

### TUI 键盘快捷键
#### 导航
| 按键 | 操作 |
|-----|--------|
| `↑` / `k` | 上移 |
| `↓` / `j` | 下移 |
| `PgUp` / `Ctrl+u` | 上半页 |
| `PgDn` / `Ctrl+d` | 下半页 |
| `Home` / `g` | 跳转到顶部 |
| `End` / `G` | 跳转到底部 |
| `Enter` | 查看组件详情 |
| `Esc` / `Backspace` | 返回 |
| `q` / `Ctrl+c` | 退出 |
#### 搜索与过滤
| 按键 | 操作 |
|-----|--------|
| `/` | 在所有字段中深度搜索(名称、PURL、许可证、原始 JSON) |
| `t` | 按包类型过滤(npm、apk、golang、pypi 等) |
| `c` | 清除所有活动过滤器 |
#### 视图
| 按键 | 上下文 | 操作 |
|-----|---------|--------|
| `j` | 详情视图 | 查看带语法高亮的原始组件 JSON |
| `d` | JSON 视图 | 切换回详情视图 |
| `Enter` | JSON 视图 | 将组件 JSON 导出到文件 |
| `?` | 任意视图 | 显示包含所有按键绑定的帮助 |
### 组件详情视图
详情视图显示完整的组件信息:
- 包信息(名称、版本、PURL、命名空间、供应商)
- 带视觉指示器的许可证
- 完整性哈希
- CPE(通用平台枚举)
- 依赖列表
- 标识符(ID、BOM-ref、SPDX-ID)
## Web UI 模式
启动基于浏览器的 SBOM 资源管理器,支持拖放文件上传:```bash
# Start web server on default port 8080
sbomlyze -web
# Start on custom port
sbomlyze -web --port 3000
然后,在浏览器中打开 http://localhost:8080。
Web UI 显示全面统计信息,包括:
安全审查
合规审计
开发调试
Web UI 包含一个完整的文件系统浏览器,用于探索 SBOM 中的文件(对于带有文件元数据的 Syft 生成的 SBOM 尤其有用):
*.so、/usr/lib/**/*.conf)-i(交互模式)启动基于终端的 TUI 浏览器,通过键盘控制浏览 SBOM。```bash sbomlyze image.json -i
Features: tree navigation, component details, search, license/hash inspection.
### `-web`(Web服务器模式)
启动一个Web服务器,用于基于浏览器的SBOM浏览。```bash
# Default port 8080
sbomlyze -web
# Custom port
sbomlyze -web --port 3000
Web UI 提供拖放上传、交互式树视图、深度搜索和统计仪表板。
--compliance对照 NTIA、CISA 2025 和 BSI TR-03183 最小元素框架对 SBOM 进行评分。参见 合规性评分。```bash sbomlyze image.json --compliance sbomlyze image.json --compliance --json
### `--format` / `-f`
选择输出格式。共有七种格式可用:
| 格式 | 标志 | 描述 | 最佳用途 |
|--------|------|-------------|----------|
| **text** | `--format text`(默认) | 人类可读的终端输出 | 本地检查 |
| **json** | `--json` 或 `--format json` | 结构化 JSON | CI 流水线、脚本编写 |
| **sarif** | `--format sarif` | 用于 GitHub 代码扫描的 SARIF 2.1.0 | GitHub 集成 |
| **junit** | `--format junit` | JUnit XML 测试结果 | CI 测试仪表盘 |
| **markdown** | `--format markdown` | 适合直接用作 PR 评论的 Markdown 报告 | 拉取请求评论 |
| **html** | `--format html` | 自包含的 HTML 报告(内联 CSS/JS) | 审计人员、可共享报告 |
| **patch** | `--format patch` | RFC 6902 JSON Patch 操作 | 程序化补丁 |```bash
# SARIF output for GitHub Code Scanning
sbomlyze before.json after.json --format sarif > results.sarif
# JUnit output for CI test dashboards
sbomlyze before.json after.json --format junit > results.xml
# Markdown report for PR comments
sbomlyze before.json after.json --format markdown > report.md
# Self-contained HTML report
sbomlyze before.json after.json --format html > report.html
# JSON Patch operations
sbomlyze before.json after.json --format patch > changes.json
生成适合 GitHub 代码扫描的 SARIF 2.1.0 报告。检测到的规则包括:
integrity-drift(错误):哈希发生变化但版本未变deep-dependency(警告):深度 3 级及以上的新依赖new-component / removed-component(备注):组件的添加/移除version-change(备注):组件版本更新policy-violation(错误/警告):策略规则违规生成带有以下测试用例的 JUnit XML:
生成 Markdown 报告,包含:
生成一个独立的 HTML 文件(内联 CSS 和 JavaScript,无外部资源),适合通过电子邮件发送给审计人员或附加到发布版本。当设置 --compliance 时,它包含统计仪表板、依赖树、漂移摘要以及嵌入式合规报告。
生成一个由 RFC 6902 JSON Patch 操作(add、remove、replace)组成的数组,表示差异。
--json--format json 的简写。以 JSON 格式输出结果,供程序化使用。```bash
sbomlyze image.json --json
sbomlyze before.json after.json --json
**统计 JSON 结构:**```json
{
"stats": {
"total_components": 71,
"by_type": {"apk": 71},
"by_license": {"MIT": 17, "BSD-3-Clause": 8},
"without_license": 0,
"with_hashes": 0,
"without_hashes": 71,
"total_dependencies": 176,
"with_dependencies": 65,
"duplicate_count": 0,
"by_language": {"go": 45, "python": 12},
"by_found_by": {"apk-db-cataloger": 71},
"license_categories": {
"copyleft": 8,
"permissive": 55,
"public_domain": 0,
"unknown": 8
},
"with_cpes": 71,
"without_cpes": 0,
"with_purl": 71,
"without_purl": 0
},
"warnings": []
}
--policy <file>应用策略规则,若违反则导致 CI 失败。```bash sbomlyze before.json after.json --policy policy.json
参见[策略引擎](#policy-engine)了解详情。
### `--strict`
遇到任何解析错误时立即失败。```bash
sbomlyze broken.json --strict
# Error parsing broken.json: unknown SBOM format
# exit status 1
--tolerant (默认)遇到错误时继续处理,收集警告。```bash sbomlyze broken.json --tolerant
解析警告包含结构化信息:源文件、人类可读的消息,以及(可选)导致问题的字段。
### `--no-pager`
禁用自动输出分页。当将输出通过管道传递给其他命令或在非交互式环境中运行时非常有用。```bash
sbomlyze image.json --no-pager
sbomlyze before.json after.json --no-pager | head -20
创建策略以在 CI/CD 管道中强制执行规则。当发生违规时,sbomlyze 以退出码 1 退出。
{ "max_added": 10, "max_removed": 5, "max_changed": 100, "deny_licenses": ["GPL-3.0", "AGPL-3.0"], "require_licenses": true, "deny_duplicates": true, "deny_integrity_drift": true, "max_depth": 3, "warn_supplier_change": true, "warn_new_transitive": true, "min_ntia_score": 85, "min_cisa_score": 70, "min_bsi_score": 80, "min_overall_compliance": 75 }
### Policy Rules
| Rule | Type | Description |
|------|------|-------------|
| `max_added` | int | 允许新增的最大组件数(0 = 无限制) |
| `max_removed` | int | 允许删除的最大组件数(0 = 无限制) |
| `max_changed` | int | 允许变更的最大组件数(0 = 无限制) |
| `deny_licenses` | []string | 禁止的许可证标识符列表 |
| `require_licenses` | bool | 要求所有*新增*组件具有许可证(在差异模式下仅检查新增组件) |
| `deny_duplicates` | bool | 如果结果中存在重复包则失败 |
| `deny_integrity_drift` | bool | 如果组件哈希在版本未变更时发生变化则失败(供应链风险) |
| `max_depth` | int | 如果深度 >= N 的新传递依赖失败(0 = 无限制) |
| `warn_supplier_change` | bool | 如果组件供应商/作者变更则警告(不失败) |
| `warn_new_transitive` | bool | 对任何新的传递依赖发出警告(不失败) |
| `min_ntia_score` | int | 如果 NTIA 合规分数低于此值则失败(0-100,0 = 禁用) |
| `min_cisa_score` | int | 如果 CISA 合规分数低于此值则失败(0-100,0 = 禁用) |
| `min_bsi_score` | int | 如果 BSI 合规分数低于此值则失败(0-100,0 = 禁用) |
| `min_overall_compliance` | int | 如果整体合规分数低于此值则失败(0-100,0 = 禁用) |
> 设置任何 `min_*_score` 阈值都会自动触发合规性评估,即使没有 `--compliance` 标志也是如此。
### 示例:严格策略```json
{
"max_added": 5,
"max_removed": 3,
"max_changed": 20,
"deny_licenses": ["GPL-3.0", "AGPL-3.0", "SSPL-1.0"],
"require_licenses": true,
"deny_duplicates": true,
"deny_integrity_drift": true,
"max_depth": 3,
"warn_supplier_change": true,
"warn_new_transitive": true,
"min_overall_compliance": 80
}
!! Policy Violations (3): [max_added] too many components added: 10 > 5 [max_removed] too many components removed: 7 > 3 [deny_licenses] component foo has denied license: GPL-3.0
## 支持的 SBOM 格式
| 格式 | 文件检测 | 提取的标识符 |
|--------|----------------|----------------------|
| Syft(原生) | JSON 键 `"artifacts"` + `"source"`、`"distro"`、`"descriptor"` 之一 | PURL、CPE、name |
| CycloneDX | JSON 键 `"bomFormat"` = `"CycloneDX"`,或 `"$schema"` 包含 `cyclonedx` | PURL、CPE、BOM-ref、group(命名空间) |
| SPDX | JSON 键 `"spdxVersion"` 以 `"SPDX-"` 开头 | PURL、CPE、SPDXID |
所有格式必须为 JSON。目前不支持 XML。
### 格式转换
sbomlyze 可以在这三种受支持格式之间进行转换:```bash
sbomlyze convert input.json --to spdx # any format → SPDX 2.3
sbomlyze convert input.json --to cyclonedx # any format → CycloneDX 1.5
sbomlyze convert input.json --to syft # any format → Syft JSON
See 转换模式 for details.
sbomlyze 可以比较不同格式的 SBOM:```bash
sbomlyze syft-output.json cyclonedx-output.json
sbomlyze spdx-output.json syft-output.json
**注意:** 不同的 SBOM 格式提取的详细程度不同。跨格式 diff 可能会显示反映格式差异(例如字段可用性)的变化,而非实际系统变化。关键发现系统在检测到扫描上下文不匹配时会发出警告。
## 组件身份匹配
组件使用基于优先级的身份系统进行匹配:
| 优先级 | 标识符 | 示例 | 描述 |
|----------|------------|---------|-------------|
| 1 | PURL | `pkg:npm/lodash` | 软件包 URL(已去除版本号) |
| 2 | CPE | `cpe:vendor:product` | CPE 供应商:产品(已去除版本号) |
| 3 | BOM-ref / SPDXID | `ref:component-123` | CycloneDX bom-ref 或 SPDX 标识符 |
| 4 | 命名空间 + 名称 | `com.example/mypackage` | 包含名称的组/命名空间 |
| 5 | 名称 | `simple-package` | 仅回退到名称 |
## CI/CD 集成
### GitHub Actions
SBOMlyze 以无依赖的 JavaScript Action 形式发布。它将已签入或单独生成的 head SBOM 与拉取请求的 git 基础版本中的文件进行比较,发布 Job Summary,并可选择生成 SARIF 或更新一条 PR 评论。```yaml
name: SBOM Check
on:
pull_request:
permissions:
contents: read
jobs:
sbom-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- id: sbomlyze
uses: rezmoss/sbomlyze@31503690611fda8ebba4ed2bd186eda000442594 # v0.5.1
with:
sbom-path: build/sbom.cdx.json
policy: .github/sbom-policy.json
fail-on: policy
该 Action 从不运行生成器命令。请在单独的、经过审查的步骤中生成 head SBOM,或将其提交到仓库中。comment 和 sarif 均默认为 false;当评论权限不可用时,fork 的 PR 仍会收到完整的 Job Summary。有关所有输入/输出、SHA 固定、SARIF 上传、权限和安全行为,请参阅 Action 参考。
sbom-diff: stage: test script: - syft . -o json > current.json - sbomlyze baseline.json current.json --policy policy.json --json > sbom-report.json - sbomlyze baseline.json current.json --format junit > sbom-junit.xml artifacts: paths: - sbom-report.json reports: junit: sbom-junit.xml when: always
### 完整性漂移警报```bash
# Alert on any integrity drift (CI example)
if sbomlyze baseline.json current.json --json | jq -e '.diff.drift_summary.integrity_drift > 0' > /dev/null; then
echo "⚠️ INTEGRITY DRIFT DETECTED - Investigate immediately!"
exit 1
fi
if sbomlyze baseline.json current.json --json | jq -e '.diff.dependencies.depth_summary.depth_3_plus > 0' > /dev/null; then echo "⚠️ New deep transitive dependencies detected - Review required!" fi
### 合规门禁```bash
# Fail the build if the SBOM doesn't meet minimum-element requirements
sbomlyze current.json --policy compliance-policy.json
# where compliance-policy.json sets min_overall_compliance / min_ntia_score / etc.
| 代码 | 含义 |
|---|---|
| 0 | 成功,无差异或违规 |
| 1 | 发现差异(任何添加/移除/更改的组件)、策略违规或错误 |
注意: 在 diff 模式下,只要检测到任何组件变更,即使没有策略文件,也会返回退出代码 1。这使其可在 CI 中用作简单的“是否有任何更改?”门禁。
syft nginx:1.25-alpine -o json > nginx-125.json syft nginx:1.26-alpine -o json > nginx-126.json
sbomlyze nginx-125.json nginx-126.json
### 许可证审计```bash
# Check for GPL licenses in new dependencies
cat > audit-policy.json << EOF
{
"deny_licenses": ["GPL-2.0", "GPL-3.0", "LGPL-2.1", "LGPL-3.0"],
"require_licenses": true
}
EOF
sbomlyze old.json new.json --policy audit-policy.json
cat > no-drift.json << EOF { "max_added": 0, "max_removed": 0, "max_changed": 0 } EOF
sbomlyze baseline.json current.json --policy no-drift.json
### 合规性检查```bash
# Score an SBOM and enforce a minimum
sbomlyze image.json --compliance
cat > compliance-policy.json << EOF
{
"min_ntia_score": 90,
"min_overall_compliance": 80
}
EOF
sbomlyze image.json --policy compliance-policy.json
syft alpine:latest -o json > alpine-syft.json sbomlyze convert alpine-syft.json --to cyclonedx -o alpine-cdx.json
sbomlyze convert vendor-sbom.cdx.json --to spdx > vendor-sbom.spdx.json
sbomlyze convert input.json --to spdx | jq '.packages | length'
### 在浏览器中探索 SBOM```bash
# Generate SBOM and explore in web UI
syft alpine:latest -o json > alpine.json
# Start web server
sbomlyze -web
# Then open http://localhost:8080 and drag-drop alpine.json
sbomlyze alpine.json -i
## 开发
### 运行测试```bash
make test
# or
go test -v ./...
make lint # runs go vet + golangci-lint + staticcheck make vulncheck # runs govulncheck for known CVEs
### 构建```bash
make build-quick
# or
go build -o sbomlyze ./cmd/sbomlyze
make all # Run test, lint, and build make test # Run all tests with race detector make lint # Run go vet, golangci-lint, and staticcheck make vulncheck # Run govulncheck for known vulnerabilities make build # Build with goreleaser (snapshot) make build-quick # Quick build for development make snapshot-test # Run snapshot tests only make update-snapshot # Update snapshot golden files make clean # Remove build artifacts
## 贡献
欢迎贡献!好的入门问题带有 [`good first issue`](https://github.com/rezmoss/sbomlyze/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) 标签。如果存在,请参阅 [CONTRIBUTING.md](https://github.com/rezmoss/sbomlyze/blob/HEAD/CONTRIBUTING.md),并随时打开 issue 或 discussion 来提议更改。
[ci]: https://github.com/rezmoss/sbomlyze/actions/workflows/ci.yml
[ci-img]: https://github.com/rezmoss/sbomlyze/actions/workflows/ci.yml/badge.svg
[marketplace]: https://github.com/marketplace/actions/sbomlyze-diff
[marketplace-img]: https://img.shields.io/badge/Marketplace-SBOMlyze%20Diff-blue?logo=github
[release]: https://github.com/rezmoss/sbomlyze/releases
[release-img]: https://img.shields.io/github/v/release/rezmoss/sbomlyze
[go-report]: https://goreportcard.com/report/github.com/rezmoss/sbomlyze
[go-report-img]: https://goreportcard.com/badge/github.com/rezmoss/sbomlyze
[license]: https://raw.githubusercontent.com/rezmoss/sbomlyze/main/LICENSE
[license-img]: https://img.shields.io/badge/License-Apache%202.0-blue.svg
[download]: https://github.com/rezmoss/sbomlyze/releases
[download-img]: https://img.shields.io/github/downloads/rezmoss/sbomlyze/total
[scorecard]: https://scorecard.dev/viewer/?uri=github.com/rezmoss/sbomlyze
[scorecard-img]: https://api.scorecard.dev/projects/github.com/rezmoss/sbomlyze/badge
| 格式 | --to 值 | 输出 |
|---|
| CycloneDX 1.5 | cyclonedx 或 cdx | 包含元数据、依赖关系和属性的 CycloneDX JSON |
| SPDX 2.3 | spdx | 包含包、关系和外部引用的 SPDX JSON |
| Syft | syft | 包含工件、关系、来源和发行版信息的 Syft JSON |
| Finding | Description |
|---|
| 扫描上下文不匹配 | 警告两个 SBOM 之间的架构版本或扫描范围发生变化 |
| 攻击面增量 | 包、文件和关系计数的变化及百分比 |
| 消失/新增的生态系统 | 完全出现或消失的包类型 |
| 操作系统/发行版迁移 | 检测两次扫描之间操作系统的变化 |
| 版本变更分析 | 统计升级与降级次数,并将变更分类为主/次/补丁(major/minor/patch) |
| 版本降级 | 将降级标记为安全信号,并附带组件详情 |
| 完整性漂移上下文 | 按包类型细分完整性漂移,并提供风险指导 |
| 主要路径模式 | 按类型和文件系统路径集中展示变更 |
| 移除/新增热点 | 受变更影响的主要目录 |
| 稳定类型 | 计数相同的包类型(核心未变) |
| 许可证类别变化 | copyleft 与 permissive 许可之间的平衡变化 |
| 目录生成器缺口 | 在 Before 中发现包但在 After 中未发现任何包的扫描器 |
| 类型 | 指示 | 描述 | 严重性 |
|---|
| 版本 | 📦 | 版本号已更改 | 正常 |
| 完整性 | ⚠️ | 哈希更改但版本未更改 | 高 - 需调查! |
| 元数据 | 📝 | 仅元数据(许可证等)已更改 | 低 |
| 功能 | 描述 |
|---|
| 拖放上传 | 将任意 SBOM 文件(Syft、CycloneDX、SPDX)拖放到页面中(最大 500MB) |
| 依赖树 | 支持展开/折叠导航的交互式树状视图(超过 5000 个组件时分页显示) |
| 组件详情 | 查看许可证、哈希、依赖项、供应商信息、文件数量 |
| 原始 JSON 视图 | 每个组件的语法高亮 JSON |
| 深度搜索 | 在所有字段中搜索,包括原始 JSON 数据 |
| 统计仪表板 | 覆盖率指标、许可证类别、语言分布 |
| 文件系统浏览器 | 在 SBOM 内浏览文件,支持目录导航、搜索和层过滤 |