Frmwrk-GmbH/sbom-scanner

GitHub: Frmwrk-GmbH/sbom-scanner

跨生态系统的SBOM生成与依赖分析工具,支持CVE扫描并输出交互式HTML报告和CycloneDX标准格式

Stars: 0 | Forks: 0

# SBOM 扫描器 一款通用的软件项目 SBOM 和 HTML 报告生成器。生成包含所有依赖(包括传递依赖)的 [CycloneDX 1.6](https://cyclonedx.org/) SBOM,以及带有 CVE 扫描和版本分析的交互式 HTML 报告。 ## 功能 - **多生态系统** — npm, PyPI, Dart/Flutter, Maven/Gradle, Rust/Cargo, yarn - **多根目录 / Monorepo** — 每个生态系统支持多个 lockfile,包含标签和标记 - **Gradle 子项目** — 自动检测并扫描所有子模块 - **自动检测** — 从 lockfile 自动发现生态系统 - **自动配置器** — 递归扫描项目并以交互方式生成配置(精美 TUI 或简单文本模式) - **CVE 扫描** — 可插拔扫描器架构,内置 [grype](https://github.com/anchore/grype) 和 [osv-scanner](https://github.com/google/osv-scanner) - **最新版本检查** — 并行查询 npm, PyPI, crates.io, Maven Central, Google Maven - **HTML 报告** — 选项卡、搜索、过滤器(依赖类型、模块、状态)、深色模式、打印样式 - **依赖树** — 可展开、动画效果、过时后代冒泡显示、按生态系统/模块分选项卡 - **PDF 导出** — 通过 weasyprint、Chrome headless 或 wkhtmltopdf - **两种报告模式** — 交互式(选项卡/JS),带 `--simple` 回退(扁平、无 JS) - **完全模块化** — 新生态系统或 CVE 扫描器 = 一个文件 + 注册条目,无需修改报告生成器 - **库 API** — 可直接导入 (`from sbom_scanner import generate_sbom, generate_report`) - **i18n** — 默认英语,包含德语翻译 (`--lang de`) - **可安装** — `pip install` 后提供三个 CLI 命令 ## 快速开始 ``` # 安装 pip install sbom-scanner[all] # 1. 生成配置(交互式 — 扫描项目并询问) sbom configure --project-dir /path/to/project # 2. 生成 SBOM sbom scan --project-dir /path/to/project # 3. 生成 HTML 报告 sbom report --project-dir /path/to/project # 打开报告 open /path/to/project/sbom-report.html ``` 第 1 步是可选的 —— 如果没有配置文件,生态系统将使用默认路径自动检测。对于 Monorepo 或子目录布局,建议使用配置。 ## 安装 ``` # 从 PyPI(发布后) pip install sbom-scanner[all] # 从仓库 pip install .[all] # 用于开发 pip install -e .[all] ``` **可选扩展:** | 扩展 | 安装内容 | 何时需要 | |---|---|---| | `yaml` | PyYAML | YAML 配置和 Dart/Flutter | | `python` | pipdeptree | 传递 Python 依赖和依赖图 | | `pdf` | weasyprint | PDF 导出(替代方案:Chrome headless) | | `tui` | rich, InquirerPy | 精美交互式配置器 | | `all` | PyYAML + pipdeptree + rich + InquirerPy | 推荐 | **外部工具(可选):** | 工具 | 何时需要 | |---|---| | [grype](https://github.com/anchore/grype) | CVE 扫描 | | [osv-scanner](https://github.com/google/osv-scanner) | CVE 扫描 | | Google Chrome / Chromium | PDF 导出(weasyprint 的替代方案) | | `dart` CLI | Dart/Flutter 过时检查 | ## 配置 在项目目录中创建 `sbom.config.yaml`(或让 `sbom configure` 生成): ### 最小配置 ``` project: name: my-app version: "1.0.0" ``` ### 完整配置 ``` project: name: my-app version: "2.0.0" description: "My application" # 仅在路径与默认值不同时指定。 # 省略 = 使用默认路径自动检测。 sources: npm: package_json: package.json # default lockfile: package-lock.json # default (also supports yarn.lock) pypi: requirements: requirements.txt # default (pip-compile or plain) pub: pubspec_yaml: pubspec.yaml # default pubspec_lock: pubspec.lock # default maven: gradle_dir: . # default (root with build.gradle) configuration: runtimeClasspath # default cargo: cargo_toml: Cargo.toml # default lockfile: Cargo.lock # default output: sbom: sbom.cyclonedx.json report: sbom-report.html options: skip_cve: false pdf: false simple: false workers: 20 ``` ### 子目录路径 当 lockfile 不在项目根目录时: ``` project: name: my-fullstack-app version: "1.0.0" sources: pypi: requirements: backend/requirements.txt npm: package_json: frontend/package.json lockfile: frontend/package-lock.json ``` ### 多根目录 / Monorepo 同一生态系统的多个实例以列表形式配置: ``` project: name: my-monorepo version: "3.0.0" sources: npm: - label: frontend package_json: apps/frontend/package.json lockfile: apps/frontend/package-lock.json tags: [web, react] - label: admin package_json: apps/admin/package.json lockfile: apps/admin/package-lock.json tags: [internal] cargo: cargo_toml: services/api/Cargo.toml lockfile: services/api/Cargo.lock ``` - **`label`** — 报告中的显示名称。回退:当存在多个条目时从目录路径派生。 - **`tags`** — 作为 [CycloneDX tags](https://cyclonedx.org/docs/1.6/json/#components_items_tags) 应用于每个组件。在报告中显示为徽章,并在 SBOM JSON 中提供以供自动化使用。 ### Gradle 子项目 带有子模块的 Gradle 项目会被自动检测。所有子项目(`:client`、`:server`、`:common` 等)都会被单独扫描。模块过滤器和依赖树子选项卡会出现在报告中。 ``` sources: maven: gradle_dir: . configuration: runtimeClasspath # optional, default: runtimeClasspath ``` ## 自动配置器 无需手动编写配置: ``` sbom configure --project-dir /path/to/project ``` 安装 `rich` + `InquirerPy` 后,您将获得带有光标导航、状态表和选项子菜单的精美 TUI。如果没有这些依赖,将使用简单的文本菜单作为回退(`--simple` 强制使用)。 功能: - 递归扫描,跳过 `node_modules`、`target`、`.venv` 等 - 从目录名称建议标签 - 从清单文件读取项目名称/版本 - 加载现有配置以进行编辑 - 选项子菜单:CVE 扫描、PDF、简单报告、工作线程数 - `--non-interactive` 接受所有默认值 ## CLI 参考 ### sbom configure ``` sbom configure [--project-dir DIR] [--output FILE] [--non-interactive] [--simple] [--lang LANG] ``` | 标志 | 默认值 | 描述 | |---|---|---| | `--project-dir` | `.` | 要扫描的项目目录 | | `--output` | `sbom.config.yaml` | 输出路径(相对于 project-dir) | | `--non-interactive` | `false` | 接受所有默认值 | | `--simple` | `false` | 强制使用简单文本菜单(无 TUI) | | `--lang` | `en` | 语言 (`en`, `de`) | ### sbom scan ``` sbom scan [--project-dir DIR] [--config FILE] [--output FILE] [--lang LANG] ``` | 标志 | 默认值 | 描述 | |---|---|---| | `--project-dir` | `.` | 项目目录 | | `--config` | `sbom.config.yaml` | 配置文件(在 project-dir 中) | | `--output` | 来自配置或 `sbom.cyclonedx.json` | 输出路径 | | `--lang` | `en` | 语言 (`en`, `de`) | ### sbom report ``` sbom report [--project-dir DIR] [--config FILE] [--sbom FILE] [--output FILE] [--skip-cve] [--pdf] [--simple] [--lang LANG] ``` | 标志 | 默认值 | 描述 | |---|---|---| | `--project-dir` | `.` | 项目目录 | | `--config` | `sbom.config.yaml` | 配置文件 | | `--sbom` | 来自配置或 `sbom.cyclonedx.json` | 输入 SBOM | | `--output` | 来自配置或 `sbom-report.html` | 输出路径 | | `--skip-cve` | `false` | 跳过 CVE 扫描 | | `--pdf` | `false` | 额外生成 PDF(使用简单报告) | | `--simple` | `false` | 无选项卡、搜索和过滤器的简单报告 | | `--lang` | `en` | 语言 (`en`, `de`) | ## 库 API 可直接在 Python 中导入: ``` from pathlib import Path from sbom_scanner import generate_sbom, generate_report, load_config project = Path("../my-project") config = load_config(project / "sbom.config.yaml") sbom_path = project / "sbom.cyclonedx.json" # 生成 SBOM generate_sbom(project, config, sbom_path) # 生成 HTML 报告 generate_report(sbom_path, project / "sbom-report.html", skip_cve=True) ``` ## 支持的生态系统 | 生态系统 | Lockfile | Registry | 检测方式 | |---|---|---|---| | npm | `package-lock.json` (v1/v2/v3), `yarn.lock` (v1) | npmjs.org | `package.json` + lockfile | | PyPI | `requirements.txt` (pip-compile 或普通) | pypi.org | `requirements.txt` | | Dart/Flutter | `pubspec.lock` | pub.dev | `pubspec.yaml` + `pubspec.lock` | | Maven/Gradle | `build.gradle` / `build.gradle.kts` | Maven Central + Google Maven | `build.gradle` + `gradlew` | | Rust/Cargo | `Cargo.lock` | crates.io | `Cargo.toml` + `Cargo.lock` | **PyPI 注意事项:** - pip-compile 格式(带 `# via` 注释) — 自动检测直接依赖与传递依赖 - 普通 `requirements.txt` — 所有包视为直接依赖,传递依赖通过 `pipdeptree` 获取(如已安装) **Maven/Gradle 注意事项:** - 子项目会被自动检测并单独扫描 - 模块成员资格(`:client`、`:server` 等)在报告中显示为过滤器 - 也支持预计算的 `gradle-dependencies.json`(自定义 Gradle 任务) ## 添加新生态系统 只需一个文件 + 注册条目。**无需修改报告生成器。** 1. 创建一个新文件,例如 `src/sbom_scanner/ecosystems/composer.py`: ``` from .base import Ecosystem class ComposerEcosystem(Ecosystem): # Identification name = "composer" display_name = "PHP/Composer" cdx_prefix = "cdx:composer" purl_type = "composer" # Report configuration package_url_template = "https://packagist.org/packages/{name}" dep_property = "cdx:composer:dependency" latest_property = "cdx:composer:latestVersion" dep_labels = {"direct main": "direct", "transitive": "transitive"} has_group_column = False # Auto-configurator pattern def scan_pattern(self): return { "detect_files": ["composer.lock"], "companion_files": ["composer.json"], "config_keys": {"composer.lock": "lockfile", "composer.json": "composer_json"}, "icon": "🐘", } # Required methods def detect(self, project_dir, config): ... def parse(self, project_dir, config): ... def fetch_latest_versions(self, packages, workers=20): ... def build_component(self, pkg, latest): ... def get_direct_purls(self, packages): ... # Optional def parse_dependency_graph(self, project_dir, config, packages): return [] ``` 2. 在 `src/sbom_scanner/ecosystems/__init__.py` 中注册: ``` from .composer import ComposerEcosystem REGISTRY: list = [ ... ComposerEcosystem(), ] ``` 就是这样。报告生成器从类中读取所有属性 —— 选项卡、过滤器、徽章、树均可自动工作。自动配置器通过 `scan_pattern()` 发现它。 ## 添加新 CVE 扫描器 相同的架构 —— 一个文件 + 注册条目。 1. 创建 `src/sbom_scanner/scanners/trivy.py`: ``` from .base import Scanner class TrivyScanner(Scanner): name = "trivy" targets = ["*"] # or ["npm", "pypi"] for specific ecosystems def is_available(self): ... def scan(self, sbom_path, lockfiles, project_dir): ... ``` 2. 在 `src/sbom_scanner/scanners/__init__.py` 中注册。 **内置扫描器:** | 扫描器 | 类型 | 目标 | 描述 | |---|---|---|---| | grype | 基于 SBOM | `*` | 扫描 CycloneDX SBOM | | osv | 基于 Lockfile | `*` | 对照 OSV 数据库扫描 lockfile | ## 项目结构 ``` sbom-scanner/ ├── pyproject.toml ├── README.md ├── LICENSE # MIT ├── CONTRIBUTING.md ├── sbom.config.yaml # Example config └── src/ └── sbom_scanner/ ├── __init__.py # Version + library API ├── i18n.py # Internationalization (gettext) ├── configure.py # sbom configure (TUI + simple fallback) ├── generate_sbom.py # sbom scan (ecosystem-agnostic) ├── generate_sbom_report.py # sbom report (ecosystem-agnostic) ├── ecosystems/ │ ├── __init__.py # Registry │ ├── base.py # Base class (Ecosystem) │ ├── npm.py # npm + yarn │ ├── pypi.py # PyPI + pipdeptree │ ├── pub.py # Dart/Flutter │ ├── maven.py # Maven/Gradle + subprojects │ └── cargo.py # Rust/Cargo ├── scanners/ │ ├── __init__.py # Registry │ ├── base.py # Base class (Scanner) │ ├── grype.py # grype (SBOM-based) │ └── osv.py # osv-scanner (lockfile-based) └── locales/ └── de/LC_MESSAGES/ # German translation (.po/.mo) ``` ## CI/CD 集成 GitLab CI 示例: ``` sbom: stage: test script: - pip install sbom-scanner[all] - sbom scan --project-dir . - sbom report --project-dir . --skip-cve artifacts: paths: - sbom.cyclonedx.json - sbom-report.html ``` 带 CVE 扫描: ``` sbom: stage: test image: python:3.13 before_script: - pip install sbom-scanner[all] - curl -sSfL https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh -s -- -b /usr/local/bin script: - sbom scan --project-dir . - sbom report --project-dir . artifacts: paths: - sbom.cyclonedx.json - sbom-report.html ``` ## 许可证 MIT — © 2026 Frmwrk GmbH
标签:Angular, Cargo, CycloneDX, Dart, DevSecOps, Flutter, Gradle, Grype, HTML报告, Maven, Monorepo支持, npm, OSV-Scanner, PDF导出, PyPI, Python安全工具, Rust, SBOM生成器, 上游代理, 云安全监控, 交互式报告, 依赖树分析, 多模态安全, 多生态系统支持, 文档安全, 漏洞测试, 漏洞验证, 版本审计, 组件漏洞, 网络流量审计, 逆向工具, 静态分析