rezmoss/sbomlyze

GitHub: rezmoss/sbomlyze

一个支持多格式转换、依赖图审计及完整性漂移检测的 SBOM 差异分析工具,专为软件供应链安全与 CI/CD 策略强制执行而设计。

Stars: 16 | Forks: 1

# sbomlyze 一个快速、可靠的 SBOM 差异分析和工具。比较跨版本的软件物料清单 (Software Bill of Materials),检测更改,并在 CI/CD 流水线中执行策略。 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/a9a9f9914d145707.svg)][ci] [![GitHub Release](https://img.shields.io/github/v/release/rezmoss/sbomlyze)][release] [![Go Report Card](https://goreportcard.com/badge/github.com/rezmoss/sbomlyze)][go-report] [![Go Doc](https://pkg.go.dev/badge/github.com/rezmoss/sbomlyze.svg)][go-doc] [![License: Apache-2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)][license] [![Go version](https://img.shields.io/github/go-mod/go-version/rezmoss/sbomlyze.svg)][gover] [![CodeQL](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/25fa0f0612145709.svg)][codeql] [![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/rezmoss/sbomlyze/badge)][scorecard] [![Downloads](https://img.shields.io/github/downloads/rezmoss/sbomlyze/total)][download] ![demo](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/f3ebfe75d3145714.gif) ## 功能特性 - **多格式支持**:Syft、CycloneDX、SPDX (JSON) - **格式转换**:在 CycloneDX、SPDX 和 Syft 格式之间转换 - **强身份匹配**:PURL → CPE → BOM-ref → namespace/name 优先级 - **漂移检测**:将更改分类为版本、完整性或元数据漂移 - **依赖图差异**:跟踪传递性依赖项和供应链深度 - **统计模式**:分析单个 SBOM 的许可证、依赖项和完整性指标 - **交互式 TUI 模式**:使用键盘导航和搜索探索 SBOM - **Web UI 模式**:基于浏览器的 SBOM 资源管理器,支持拖放上传 - **策略引擎**:在 CI 流水线中执行规则 - **重复与冲突检测**:查找同一软件包的多个版本和歧义的身份匹配 - **多种输出格式**:Text、JSON、SARIF、JUnit XML、Markdown、JSON Patch - **容错解析**:遇到错误时继续执行,并输出结构化警告 ## 安装说明 ### 安装脚本(推荐) 安装脚本会下载适合您的操作系统/架构的二进制文件: ``` # 安装到 ./bin curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sh # 安装到 /usr/local/bin(需要 sudo) 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.2.0 ``` **安装程序选项:** | 选项 | 描述 | |--------|-------------| | `-b ` | 安装目录(默认:`./bin`) | | `-d` | 启用调试输出 | | `-v ` | 安装特定版本(默认:latest) | ### Debian / Ubuntu (apt) ``` # 添加仓库 echo "deb [trusted=yes] https://rezmoss.github.io/sbomlyze/deb stable main" | sudo tee /etc/apt/sources.list.d/sbomlyze.list # 安装 sudo apt update sudo apt install sbomlyze ``` ### RHEL / Fedora / CentOS (dnf/yum) ``` # 添加仓库 sudo tee /etc/yum.repos.d/sbomlyze.repo << 'EOF' [sbomlyze] name=sbomlyze baseurl=https://rezmoss.github.io/sbomlyze/rpm/packages enabled=1 gpgcheck=0 EOF # 安装 sudo dnf install sbomlyze # or: sudo yum install sbomlyze ``` ### Alpine (apk) ``` # 下载并安装 wget https://github.com/rezmoss/sbomlyze/releases/latest/download/sbomlyze_VERSION_linux_amd64.apk sudo apk add --allow-untrusted sbomlyze_*_linux_amd64.apk ``` ### Homebrew (macOS/Linux) ``` brew install rezmoss/sbomlyze/sbomlyze ``` ### Go Install ``` go install github.com/rezmoss/sbomlyze/cmd/sbomlyze@latest ``` ### 从二进制版本安装 从 [GitHub Releases](https://github.com/rezmoss/sbomlyze/releases) 下载最新的二进制文件。 **macOS 用户:** 下载后移除隔离标志: ``` 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 ``` ## 快速开始 ``` # 分析单个 SBOM sbomlyze image.json # 比较两个 SBOM sbomlyze before.json after.json # 交互式 TUI 探索器 sbomlyze image.json -i # Web UI(打开浏览器) sbomlyze -web # 在 SBOM 格式之间转换 sbomlyze convert syft.json --to spdx sbomlyze convert cdx.json --to syft -o output.json # 用于 CI 集成的 JSON 输出 sbomlyze before.json after.json --json # 用于 GitHub Code Scanning 的 SARIF 输出 sbomlyze before.json after.json --format sarif # 用于 PR 评论的 Markdown 报告 sbomlyze before.json after.json --format markdown # 应用策略检查 sbomlyze before.json after.json --policy policy.json ``` ## 使用说明 ``` sbomlyze [sbom2] [options] sbomlyze convert --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 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, patch --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 以获取有关组件、许可证和依赖项的洞察。 ``` 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) 📦 SBOM Statistics ================== 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%)进行报告 | | **文件系统占用** | 文件系统上跟踪的文件数量 | | **关系密度** | 包含 (containment) 和依赖 (dependency-of) 关系的计数 | | **位置热点** | 发现组件的顶级目录 | | **许可证风险概况** | 宽松/版权左/未知许可证百分比的细分 | | **数据质量警告** | 当许可证 (<50%)、哈希 (<50%) 或 PURL (<80%) 覆盖率较低时发出警报 | | **重复警告** | 标记重复的组件组 | | **编目器细分** | 检测到组件的顶级扫描器/编目器 | #### 覆盖率指标 统计模式会计算数据质量评估的覆盖率百分比: | 指标 | 描述 | |--------|-------------| | **PURL 覆盖率** | 具有 Package URL 的组件百分比 | | **CPE 覆盖率** | 具有 CPE 的组件百分比(漏洞扫描准备情况) | | **许可证覆盖率** | 至少具有一个许可证的组件百分比 | | **哈希覆盖率** | 具有完整性哈希的组件百分比 | #### 许可证分类 许可证会自动归类为: | 类别 | 示例 | |----------|----------| | **Copyleft** | GPL、LGPL、AGPL、MPL、EPL、CDDL | | **Permissive** | MIT、BSD、Apache、ISC、Zlib、Unlicense | | **Public Domain** | 公共领域声明 | | **Unknown** | 无法识别或缺失的许可证 | ### 转换模式 在 CycloneDX、SPDX 和 Syft JSON 格式之间转换 SBOM。输入格式会自动检测。 ``` # CycloneDX 到 SPDX sbomlyze convert image.cdx.json --to spdx # Syft 到 CycloneDX(cdx 是 cyclonedx 的别名) sbomlyze convert syft-output.json --to cdx # SPDX 到 Syft,写入到文件 sbomlyze convert spdx-output.json --to syft -o converted.json ``` #### 支持的目标格式 | 格式 | `--to` 值 | 输出 | |--------|-------------|--------| | CycloneDX 1.5 | `cyclonedx` 或 `cdx` | 包含元数据、依赖项和属性的 CycloneDX JSON | | SPDX 2.3 | `spdx` | 包含软件包、关系和外部引用的 SPDX JSON | | Syft | `syft` | 包含工件、关系、源代码和发行版信息的 Syft JSON | #### 保留内容 转换会保留组件名称、版本、PURL、CPE、许可证、哈希、供应商信息和依赖关系。特定于格式的字段(例如 Syft language、foundBy、locations)在转换为 CDX 时会通过 CycloneDX 属性传递。 ### 差异模式(两个文件) 比较两个 SBOM 以查看版本之间发生了什么变化。 ``` sbomlyze v1.0.json v2.0.json ``` #### 差异概览 差异首先从并排的元数据比较(文件名、大小、操作系统信息、工具信息、组件计数)开始,然后在可用时显示扫描上下文详细信息。 #### 输出 ``` 📊 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 ⚠️ ``` #### 差异关键发现 在差异模式下,sbomlyze 会自动生成更丰富的洞察来比较两个 SBOM: | 发现 | 描述 | |---------|-------------| | **扫描上下文不匹配** | 如果 SBOM 之间的 schema 版本或扫描范围发生变化,则发出警告 | | **攻击面增量** | 软件包、文件和关系计数的变化及百分比 | | **消失/新增的生态系统** | 完全出现或消失的软件包类型 | | **操作系统/发行版迁移** | 检测扫描之间的操作系统变化 | | **版本变更分析** | 统计升级与降级,将更改分类为 major/minor/patch | | **版本降级** | 将降级标记为带有组件详细信息的安全信号 | | **完整性漂移上下文** | 按软件包类型细分完整性漂移并提供风险指导 | | **主导路径模式** | 按类型和文件系统路径集中的更改 | | **移除/添加热点** | 受更改影响最大的目录 | | **稳定类型** | 计数相同的软件包类型(未更改的核心) | | **许可证类别偏移** | Copyleft/Permissive 平衡的变化 | | **编目器缺口** | 在 Before 中找到软件包但在 After 中未找到的扫描器 | #### 按类型列出的软件包示例 添加和删除的组件按软件包类型分组并附有示例列表,可以轻松查看每个生态系统中发生了什么变化。 ## 依赖图差异 sbomlyze 超越了简单的组件列表差异,能够分析完整的依赖图,检测通过传递性依赖引入的供应链风险。 ### 功能特性 | 功能 | 描述 | |---------|-------------| | **边差异** | 添加/删除的直接依赖 (A depends on B) | | **传递可达性** | 通过图出现的新间接依赖 | | **传递丢失跟踪** | 被删除的传递性依赖 | | **路径跟踪** | 显示确切如何到达每个新的传递依赖 | | **深度跟踪** | 每个新依赖距离您的代码有多少跳 | | **风险摘要** | 深度为 3+ 的依赖被标记为高风险 | ### 为什么深度很重要 在图中引入更深的依赖项: - 更难审计和审查 - 通常在没有明确批准的情况下被引入 - 供应链攻击的常见载体(例如 event-stream 事件) 深度摘要有助于确定审查优先级: | 深度 | 风险等级 | 描述 | |-------|------------|-------------| | **1** | 低 | 直接依赖(您选择了这些) | | **2** | 中 | 您的依赖的依赖 | | **3+** | 高 ⚠️ | 深层传递依赖 - 仔细审查 | ### 示例:检测深层传递依赖 ``` # 之前:app -> express (simple, 1 dep) # 之后:app -> express -> lodash -> underscore -> deep-lib (chain of 4) sbomlyze before.json after.json ``` 输出: ``` 🔗 New transitive dependencies (3): + lodash (depth 2) via: [app express lodash] + underscore (depth 3) via: [app express lodash underscore] + deep-lib (depth 4) via: [app express lodash underscore deep-lib] 📊 New deps by depth: Depth 2: 1 Depth 3+ (risky): 2 ⚠️ ``` ### 依赖图的 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 将组件更改分为三种漂移类型,帮助您区分正常更新和潜在的可疑更改。 ### 漂移类型 | 类型 | 指标 | 描述 | 严重性 | |------|-----------|-------------|----------| | **Version** | 📦 | 版本号已更改 | 正常 | | **Integrity** | ⚠️ | 哈希已更改但版本未变 | 高 - 请调查! | | **Metadata** | 📝 | 仅元数据(许可证等)已更改 | 低 | ### 完整性漂移(安全信号) 当组件的哈希更改但其版本保持不变时,会发生完整性漂移。这可能表明: - **供应链攻击**:软件包被替换为恶意版本 - **未升级版本的重建**:合法但做法不佳 - **不同的构建环境**:可复现性问题 ``` # 显示完整性差异的示例输出 ~ suspicious-pkg ⚠️ [INTEGRITY] hash[SHA256]: abc123 -> def456 ``` **建议**:始终调查完整性漂移。它可能是良性的,但它是供应链安全的关键信号。 ### 漂移的 JSON 输出 漂移摘要位于 `diff` 对象内: ``` { "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 } } } ``` **提取漂移摘要:** ``` # 获取差异摘要 sbomlyze before.json after.json --json | jq '.diff.drift_summary' # 在 CI 中检查完整性差异 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] ``` 在差异模式下,重复版本差异跟踪: - **新重复**:在新 SBOM 中变成重复的组件 - **已解决重复**:已合并的重复组 - **版本添加/删除**:现有重复组内的版本更改 ### 冲突检测 冲突是身份匹配不明确的情况,即组件共享相同的 ID 但具有冲突的特征: | 类型 | 描述 | |------|-------------| | **名称不匹配** | 不同的组件名称映射到相同的身份 ID | | **哈希不匹配** | 组件的同一版本具有不同的哈希(可能被篡改) | ## SBOMlyze SBOM 资源管理器 (TUI) ``` sbomlyze sbom.json -i ``` ![interactive-sbom](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/355c6b855d145718.gif) ### TUI 键盘快捷键 #### 导航 | 按键 | 动作 | |-----|--------| | `↑` / `k` | 向上移动 | | `↓` / `j` | 向下移动 | | `PgUp` / `Ctrl+u` | 向上翻半页 | | `PgDn` / `Ctrl+d` | 向下翻半页 | | `Home` / `g` | 跳转到顶部 | | `End` / `G` | 跳转到底部 | | `Enter` | 查看组件详细信息 | | `Esc` / `Backspace` | 返回 | | `q` / `Ctrl+c` | 退出 | #### 搜索与过滤 | 按键 | 动作 | |-----|--------| | `/` | 深度搜索所有字段(名称、PURL、许可证、原始 JSON) | | `t` | 按软件包类型过滤 | | `c` | 清除所有活动过滤器 | #### 视图 | 按键 | 上下文 | 动作 | |-----|---------|--------| | `j` | 详情视图 | 查看带有语法高亮的原始组件 JSON | | `d` | JSON 视图 | 切换回详情视图 | | `Enter` | JSON 视图 | 将组件 JSON 导出到文件 | | `?` | 任意视图 | 显示包含所有键绑定的帮助 | ### 组件详情视图 详情视图显示全面的组件信息: - 软件包信息(名称、版本、PURL、namespace、供应商) - 带有可视指示器的许可证 - 完整性哈 - CPE(通用平台枚举) - 依赖列表 - 标识符(ID、BOM-ref、SPDX-ID) ## Web UI 模式 启动基于浏览器的 SBOM 资源管理器,支持拖放文件上传: ``` # 在默认端口 8080 上启动 Web 服务器 sbomlyze -web # 在自定义端口启动 sbomlyze -web --port 3000 ``` 然后在浏览器中打开 http://localhost:8080。 Screenshot 2026-02-06 at 17 08 13 ### Web UI 功能 | 功能 | 描述 | |---------|-------------| | **拖放上传** | 将任何 SBOM 文件拖放到页面上(最大 500MB) | | **依赖树** | 带有展开/折叠导航的交互式树状视图(> 5000 个组件时分页) | | **组件详情** | 查看许可证、哈希、依赖、供应商信息、文件计数 | | **原始 JSON 视图** | 每个组件的语法高亮 JSON | | **深度搜索** | 搜索包括原始 JSON 数据在内的所有字段 | | **统计仪表板** | 覆盖率指标、许可证类别、语言分布 | | **文件系统浏览器** | 通过目录导航、搜索和层过滤浏览 SBOM 中的文件 | ### 显示的统计数据 Web UI 显示全面的统计数据,包括: - 按软件包类型(npm、apk、pypi 等)的**组件计数** - 带有类别细分的**许可证分布**(copyleft、permissive、public domain) - 带有可视进度条的**覆盖率指标**: - PURL 覆盖率(package URL 存在) - CPE 覆盖率(漏洞扫描准备情况) - 许可证覆盖率 - 哈希/完整性覆盖率 - **语言细分**(针对 Syft 生成的 SBOM) - **关系统计**(contains、dependency-of、evident-by) - **重复检测**警告 ### 用例 **安全审查** - 上传 SBOM 并探索完整的依赖树 - 检查 CPE 覆盖率以确保漏洞扫描有效 - 审查没有许可证或哈希的组件 **合规审计** - 在所有组件中搜索特定许可证 - 查看许可证类别分布(copyleft 与 permissive) - 导出原始 JSON 用于文档记录 **开发调试** - 探索您的镜像中包含哪些软件包 - 检查传递性依赖 - 验证软件包元数据是否正确 ### 文件系统浏览器 Web UI 包括一个完整的文件系统浏览器,用于探索 SBOM 内的文件(对于带有文件元数据的 Syft 生成的 SBOM 特别有用): - 带有面包屑导航的**目录树导航** - 支持子字符串和 glob 模式的**文件搜索**(例如 `*.so`、`/usr/lib/**/*.conf`) - 用于容器镜像 SBOM 的**层过滤**(按镜像层浏览文件) - **组件到文件的关系**(哪个组件拥有哪些文件) - 按类型、MIME 类型、扩展名和层统计的**文件统计** - **未拥有文件检测**(未与任何组件关联的文件) ## 选项 ### `-i`(交互模式) 启动基于终端的 TUI 资源管理器,用于通过键盘控制导航 SBOM。 ``` sbomlyze image.json -i ``` 功能:树导航、组件详情、搜索、许可证/哈希检查。 ### `-web`(Web 服务器模式) 启动 Web 服务器以进行基于浏览器的 SBOM 探索。 ``` # 默认端口 8080 sbomlyze -web # 自定义端口 sbomlyze -web --port 3000 ``` Web UI 提供拖放上传、交互式树视图、深度搜索和统计仪表板。 ### `--format` / `-f` 选择输出格式。有六种格式可用: | 格式 | 标志 | 描述 | 最适用于 | |--------|------|-------------|----------| | **text** | `--format text`(默认) | 人类可读的终端输出 | 本地检查 | | **json** | `--json` 或 `--format json` | 结构化 JSON | CI 流水线、脚本 | | **sarif** | `--format sarif` | 用于 GitHub Code Scanning 的 SARIF 2.1.0 | GitHub 集成 | | **junit** | `--format junit` | JUnit XML 测试结果 | CI 测试仪表板 | | **markdown** | `--format markdown` | 适用于 PR 评论的 Markdown 报告 | Pull request 评论 | | **patch** | `--format patch` | RFC 6902 JSON Patch 操作 | 程序化补丁 | ``` # 用于 GitHub Code Scanning 的 SARIF 输出 sbomlyze before.json after.json --format sarif > results.sarif # 用于 CI 测试仪表板的 JUnit 输出 sbomlyze before.json after.json --format junit > results.xml # 用于 PR 评论的 Markdown 报告 sbomlyze before.json after.json --format markdown > report.md # JSON Patch 操作 sbomlyze before.json after.json --format patch > changes.json ``` #### SARIF 格式 生成适用于 GitHub Code Scanning 的 [SARIF 2.1.0](https://sarifweb.azurewebsites.net/) 报告。检测到的规则包括: - `integrity-drift`(错误)—— 哈希已更改但版本未变 - `deep-dependency`(警告)—— 深度 3+ 的新依赖 - `new-component` / `removed-component`(注释)—— 组件添加/删除 - `version-change`(注释)—— 组件版本更新 - `policy-violation`(错误/警告)—— 策略规则违规 #### JUnit 格式 生成包含以下测试用例的 JUnit XML: - 无完整性漂移 - 无深层传递依赖(深度 3+) - 策略合规性(每个违规一个测试用例) - SBOM 差异摘要 #### Markdown 格式 生成包含以下内容的 Markdown 报告: - 并排 SBOM 比较表(文件、大小、操作系统、覆盖率指标) - 扫描上下文详细信息 - 关键发现 - 按类型分组的添加/删除软件包(在可折叠部分) - 漂移摘要、依赖深度和策略违规 #### Patch 格式 生成一个 RFC 6902 JSON Patch 操作数组(`add`、`remove`、`replace`),表示差异。 ### `--json` `--format json` 的简写。以 JSON 格式输出结果供程序化使用。 ``` # 统计信息为 JSON sbomlyze image.json --json # 差异信息为 JSON sbomlyze before.json after.json --json ``` **Stats 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 ` 应用策略规则,如果违规则导致 CI 失败。 ``` sbomlyze before.json after.json --policy policy.json ``` 详情请参阅 [Policy Engine](#policy-engine)。 ### `--strict` 遇到任何解析错误时立即失败。 ``` sbomlyze broken.json --strict # 解析 broken.json 时出错:未知的 SBOM 格式 # exit status 1 ``` ### `--tolerant`(默认) 遇到错误时继续处理,收集警告。 ``` sbomlyze broken.json --tolerant # 📦 SBOM 统计信息 # ================== # 总组件数:0 # ... # ⚠️ 解析警告 (1): # [broken.json] 未知的 SBOM 格式 ``` 解析警告包括结构化信息:源文件、人类可读的消息,以及可选的导致问题的字段。 ### `--no-pager` 禁用自动输出分页。在将输出通过管道传递给另一个命令或在非交互式环境中运行时非常有用。 ``` 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 } ``` ### 策略规则 | 规则 | 类型 | 描述 | |------|------|-------------| | `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 | 对任何新的传递依赖发出警告(不失败) | ### 示例:严格策略 ``` { "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 } ``` ### 策略违规输出 ``` !! 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 (native) | JSON 键 `"artifacts"` + `"source"`、`"distro"` 或 `"descriptor"` 之一 | PURL、CPE、名称 | | CycloneDX | JSON 键 `"bomFormat"` = `"CycloneDX"` 或 `"$schema"` 包含 `cyclonedx` | PURL、CPE、BOM-ref、group (namespace) | | SPDX | JSON 键 `"spdxVersion"` 以 `"SPDX-"` 开头 | PURL、CPE、SPDXID | 所有格式必须是 JSON。目前不支持 XML。 ### 格式转换 sbomlyze 可以在三种支持的任何格式之间转换: ``` 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 ``` 详情请参阅 [Convert Mode](#convert-mode)。 ### 跨格式比较 sbomlyze 可以比较不同格式的 SBOM: ``` # 比较 Syft 输出与 CycloneDX sbomlyze syft-output.json cyclonedx-output.json # 比较 SPDX 与 Syft sbomlyze spdx-output.json syft-output.json ``` **注意:** 不同的 SBOM 格式提取不同级别的详细信息。跨格式差异可能会显示反映格式差异(例如,字段可用性)而不是实际系统变化的更改。当检测到扫描上下文不匹配时,关键发现系统会发出警告。 ## 组件身份匹配 组件使用基于优先级的身份系统进行匹配: | 优先级 | 标识符 | 示例 | 描述 | |----------|------------|---------|-------------| | 1 | PURL | `pkg:npm/lodash` | Package URL(已去除版本) | | 2 | CPE | `cpe:vendor:product` | CPE vendor:product(已去除版本) | | 3 | BOM-ref / SPDXID | `ref:component-123` | CycloneDX bom-ref 或 SPDX 标识符 | | 4 | Namespace + Name | `com.example/mypackage` | Group/namespace 与名称 | | 5 | Name | `simple-package` | 回退到仅名称 | ## CI/CD 集成 ### GitHub Actions ``` name: SBOM Check on: [pull_request] jobs: sbom-diff: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Generate SBOM run: syft . -o json > current.json - name: Download baseline SBOM run: curl -o baseline.json ${{ vars.BASELINE_SBOM_URL }} - name: Compare SBOMs run: | go install github.com/rezmoss/sbomlyze@latest sbomlyze baseline.json current.json --policy policy.json ``` #### GitHub Code Scanning (SARIF) ``` - name: SBOM Diff (SARIF) run: sbomlyze baseline.json current.json --format sarif > results.sarif continue-on-error: true - name: Upload SARIF uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif ``` #### 使用 Markdown 报告进行 PR 评论 ``` - name: Generate Markdown Report run: sbomlyze baseline.json current.json --format markdown > report.md continue-on-error: true - name: Comment on PR uses: marocchino/sticky-pull-request-comment@v2 with: path: report.md ``` ### GitLab CI ``` 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 ``` ### 完整性漂移警报 ``` # 在任何完整性差异时发出警报(CI 示例) 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 ``` ## 退出代码 | 代码 | 含义 | |------|---------| | 0 | 成功,无差异或违规 | | 1 | 发现差异(任何添加/删除/更改的组件)、策略违规或错误 | **注意:** 在差异模式下,只要检测到任何组件更改,就会返回退出代码 1,即使没有策略文件也是如此。这使得它可以用作 CI 中一个简单的“是否有任何变化?”关卡。 ## 示例 ### 比较 Docker 镜像 ``` # 生成 SBOM 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 ``` ### 许可证审计 ``` # 检查新依赖项中的 GPL 许可证 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 ``` ### 转换 SBOM 格式 ``` # 将 Syft SBOM 转换为 CycloneDX 以供需要的工具使用 syft alpine:latest -o json > alpine-syft.json sbomlyze convert alpine-syft.json --to cyclonedx -o alpine-cdx.json # 将 CycloneDX 转换为 SPDX 用于合规工作流 sbomlyze convert vendor-sbom.cdx.json --to spdx > vendor-sbom.spdx.json # 直接管道转换输出 sbomlyze convert input.json --to spdx | jq '.packages | length' ``` ### 在浏览器中探索 SBOM ``` # 生成 SBOM 并在 Web UI 中探索 syft alpine:latest -o json > alpine.json # 启动 Web 服务器 sbomlyze -web # 然后打开 http://localhost:8080 并拖放 alpine.json ``` ### 交互式终端探索 ``` # 使用键盘导航探索 sbomlyze alpine.json -i # 使用箭头键导航,使用 '/' 搜索,使用 Enter 查看详情 ``` ## 开发 ### 运行测试 ``` make test # 或 go test -v ./... ``` ### Lint ``` make lint # runs go vet + golangci-lint + staticcheck make vulncheck # runs govulncheck for known CVEs ``` ### 构建 ``` make build-quick # 或 go build -o sbomlyze ./cmd/sbomlyze ``` ### Make 命令 ``` 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 ```
标签:CPE, CycloneDX, DevSecOps, Diff工具, EVTX分析, Go语言, Lerna, PURL, SARIF, SBOM, SPDX, Syft, TCP SYN 扫描, TUI, WebSocket, Web UI, 上游代理, 云安全监控, 代码分析, 传递性依赖, 依赖分析, 依赖图, 凭证管理, 多模态安全, 安全合规, 完整性漂移检测, 开源框架, 持续集成, 数据可视化, 日志审计, 格式转换, 版本对比, 硬件无关, 程序破解, 策略执行, 网络代理, 许可证合规, 跌倒检测, 软件供应链安全, 软件物料清单, 远程方法调用, 静态分析