
sbomlyze v0.3.5
git diff для вашего SBOM ,сравнивайте CycloneDX/SPDX/Syft списки материалов, выявляйте подделку и управляйте CI
sbomlyze
git diff для вашего SBOM. Сравните два SBOM (Software Bills of Materials) и узнайте, что изменилось между сборками, версиями и релизами.
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]
Узнайте, чем этот сигнал отличается от манифеста или обычного сравнения компонентов, в Разница между манифестом, SBOM-диффом и дрейфом целостности.
Генераторы создают SBOM, а сканеры находят CVE. sbomlyze показывает, что изменилось между двумя SBOM и можно ли этому доверять. Запускайте его после вашего генератора:
syft image:tag -o cyclonedx-json | sbomlyze - --compliance— анализирует и оценивает сгенерированный SBOM без временного файла. Сравните его с базовым, чтобы классифицировать дрейф и управлять пайплайном.
Краткое руководство по GitHub Action
Добавьте [SBOMlyze Diff из GitHub Marketplace][marketplace], чтобы сравнить включённый в репозиторий или отдельно сгенерированный SBOM с его базовым состоянием в git. Указанный ниже неизменяемый SHA — это опубликованное Action v0.5.1:```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
Действие по умолчанию записывает Job Summary и может применять политики, сообщать об отклонениях целостности, выгружать SARIF или поддерживать единый комментарий в pull request. Полное описание Action см. в [справочнике по Action](https://github.com/rezmoss/sbomlyze/blob/HEAD/ACTION.md): входные данные, выходные данные, разрешения и рекомендации по безопасности. Пример с проходящим обновлением зависимостей и блокированным изменением хеша без смены версии см. в [живом демонстрационном репозитории](https://github.com/rezmoss/sbomlyze-action-demo) — там доступны публичные запуски workflow и SARIF-свидетельства.
Для проверки на собственном примере (dogfood) применительно к конкретным форматам используйте публичные примеры [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-минутном бета-руководстве](https://github.com/rezmoss/sbomlyze/blob/HEAD/BETA.md) собраны четыре ключевых вопроса по активации и качеству сигналов.
Сгенерированные SBOM не обязательно коммитить: `baseline: workflow-artifact` получает самый свежий подходящий артефакт из успешного запуска на ветке по умолчанию. [Зафиксированный сопутствующий workflow для 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 (**diff**) | ✅ | базово | ❌ | ❌ |
| Отклонение **целостности / подмены** (хеш изменился без смены версии) | ✅ | ❌ | ❌ | ❌ |
| Дифф графа зависимостей + риск транзитивной глубины | ✅ | ❌ | ❌ | ❌ |
| Оценка соответствия **NTIA / CISA / BSI** | ✅ | ❌ | ✅ | ❌ |
| Конвертация форматов (Syft / CycloneDX / SPDX) | ✅ | ✅ | ❌ | частично |
| Обозреватели **TUI + Web UI** | ✅ | ❌ | ❌ | ❌ |
| Политический шлюз + SARIF / JUnit / Markdown / HTML / Patch | ✅ | частично | частично | частично |
## Возможности
- **Дифф SBOM**: Сравнивайте два SBOM и видите добавленные, удалённые и изменённые компоненты с первого взгляда
- **Классификация отклонений**: Отличайте версионные отклонения от **отклонений целостности** (хеш изменился без смены версии — признак подмены) и отклонений метаданных
- **Оценка соответствия**: Оценивайте любой SBOM по минимальным элементам **NTIA**, **CISA 2025** и **BSI TR-03183**
- **Дифф графа зависимостей**: Отслеживайте транзитивные зависимости и глубину цепочки поставок
- **Поддержка нескольких форматов**: Syft, CycloneDX, SPDX (JSON)
- **Конвертация форматов**: Преобразование между форматами CycloneDX, SPDX и Syft
- **Надёжное сопоставление идентификаторов**: Приоритет PURL → CPE → BOM-ref → namespace/name
- **Режим статистики**: Анализ отдельных SBOM по метрикам лицензий, зависимостей и целостности
- **Интерактивный TUI-режим**: Исследуйте SBOM с помощью навигации с клавиатуры и поиска
- **Режим Web UI**: Браузерный обозреватель SBOM с загрузкой через drag-and-drop
- **Политический движок**: Применение правил отклонений, лицензий и оценки соответствия в CI-пайплайнах
- **GitHub Marketplace Action**: Контролируйте pull request-ы на предмет отклонений SBOM с помощью Job Summary, SARIF и опционального комментария
- **Обнаружение дубликатов и коллизий**: Найдите несколько версий одного пакета и неоднозначные совпадения идентификаторов
- **Множество выходных форматов**: Text, JSON, SARIF, JUnit XML, Markdown, HTML, JSON Patch
- **Устойчивый парсинг**: Продолжение работы при ошибках со структурированными предупреждениями
## Установка
### Homebrew (macOS/Linux)```bash
brew install rezmoss/sbomlyze/sbomlyze
Installer Script
Скрипт установки загружает правильный бинарный файл для вашей ОС/архитектуры:```bash
Install to ./bin
curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sh
Install to /usr/local/bin (requires sudo)
curl -sSfL https://raw.githubusercontent.com/rezmoss/sbomlyze/main/install.sh | sudo sh -s -- -b /usr/local/bin
Install specific version
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. Проверьте загрузку независимо с помощью:```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
Сборка из исходного кода```bash
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)
📦 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 |
| **Горячие точки расположения** | Основные каталоги, где находятся компоненты |
| **Профиль лицензионного риска** | Разбивка процентов разрешительных/copyleft/неизвестных лицензий |
| **Предупреждения о качестве данных** | Предупреждения при низком покрытии лицензиями (<50%), хэшами (<50%) или PURL (<80%) |
| **Предупреждения о дубликатах** | Отмечает дублирующиеся группы компонентов |
| **Разбивка по каталогизаторам** | Основные сканеры/каталогизаторы, которые обнаружили компоненты (SBOM Syft) |
#### Метрики покрытия
Режим статистики вычисляет проценты покрытия для оценки качества данных:
| Метрика | Описание |
|--------|-------------|
| **Покрытие PURL** | Процент компонентов с Package URLs |
| **Покрытие CPE** | Процент компонентов с CPE (готовность к сканированию уязвимостей) |
| **Покрытие лицензиями** | Процент компонентов хотя бы с одной лицензией |
| **Покрытие хэшами** | Процент компонентов с хэшами целостности |
#### Категоризация лицензий
Лицензии автоматически категоризируются на:
| Категория | Примеры |
|----------|----------|
| **Копилефт** | GPL, LGPL, AGPL, MPL, EPL, CDDL |
| **Разрешительная** | MIT, BSD, Apache, ISC, Zlib, Unlicense |
| **Общественное достояние** | Посвящения в общественное достояние |
| **Неизвестно** | Нераспознанные или отсутствующие лицензии |
### Режим конвертации
Конвертируйте SBOM между форматами CycloneDX, SPDX и Syft JSON. Формат входного файла определяется автоматически.```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
Поддерживаемые целевые форматы
| Формат | Значение --to | Вывод |
|---|---|---|
| CycloneDX 1.5 | cyclonedx or cdx | CycloneDX JSON с метаданными, зависимостями и свойствами |
| SPDX 2.3 | spdx | SPDX JSON с пакетами, связями и внешними ссылками |
| Syft | syft | Syft JSON с артефактами, связями, источником и информацией о дистрибутиве |
Что сохраняется
При конвертации сохраняются имена компонентов, версии, PURLs, CPEs, лицензии, хэши, информация о поставщике и зависимости. Поля, специфичные для формата (например, язык Syft, foundBy, locations), переносятся через свойства CycloneDX при конвертации в CDX.
Режим сравнения (два файла)
Сравните два SBOM, чтобы увидеть, что изменилось между версиями.```bash 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 ⚠️
Ключевые выводы в режиме Diff
В режиме diff sbomlyze автоматически генерирует более детальные сведения, сравнивая оба SBOM:
| Вывод | Описание |
|---|---|
| Несоответствие контекста сканирования | Предупреждает, если версия схемы или область сканирования изменились между SBOM |
| Дельта поверхности атаки | Изменения количества пакетов, файлов и связей с процентами |
| Исчезнувшие/новые экосистемы | Типы пакетов, которые полностью появились или исчезли |
| Миграция ОС/дистрибутива | Обнаруживает изменения операционной системы между сканированиями |
| Анализ изменений версий | Подсчитывает обновления и понижения версий, классифицирует изменения как major/minor/patch |
| Понижения версий | Помечает понижения версий как сигнал безопасности с деталями компонентов |
| Контекст отклонений целостности | Разбивает отклонения целостности по типам пакетов с рекомендациями по рискам |
| Доминирующие паттерны путей | Сосредоточенные изменения по типу и пути файловой системы |
| Зоны удаления/добавления | Главные каталоги, затронутые изменениями |
| Стабильные типы | Типы пакетов с идентичным количеством (неизменное ядро) |
| Сдвиги категорий лицензий | Изменения баланса copyleft/пермиссивных лицензий |
| Пробелы каталогизаторов | Сканеры, которые нашли пакеты в Before, но ни одного в After |
Примеры пакетов по типам
Добавленные и удалённые компоненты группируются по типу пакета с примерами списков, что позволяет легко увидеть, что изменилось в каждой экосистеме.
Оценка соответствия
Оцените любой SBOM по трём основным фреймворкам минимальных элементов, чтобы ответить на вопрос, который постоянно задают аудиторы и закупочные команды: «Достаточно ли полон этот SBOM?»```bash
Score a single SBOM
sbomlyze image.json --compliance
Score alongside a diff
sbomlyze before.json after.json --compliance
As JSON for CI
sbomlyze image.json --compliance --json
### Оценённые фреймворки
| Фреймворк | Проверки | Ключевые требования |
|-----------|--------|----------------------|
| **NTIA Minimum Elements** (2021) | 7 | имя, версия, поставщик, уникальные идентификаторы (PURL/CPE), связи зависимостей, автор SBOM, отметка времени |
| **CISA 2025 Minimum Elements** (авг. 2025, черновик) | 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
}
Входной фрагмент пуст — нечего переводить.```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):
- 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-вывод для графа зависимостей```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 классифицирует изменения компонентов по трём типам расхождений, помогая отличить обычные обновления от потенциально подозрительных изменений.
Типы расхождений
| Тип | Индикатор | Описание | Серьёзность |
|---|---|---|---|
| Версия | 📦 | Изменён номер версии | Нормальная |
| Целостность | ⚠️ | Хеш изменён БЕЗ изменения версии | Высокая — требует проверки! |
| Метаданные | 📝 | Изменены только метаданные (лицензии и т. д.) | Низкая |
Расхождение целостности (сигнал безопасности)
Расхождение целостности возникает, когда хеш компонента изменяется, но его версия остаётся прежней. Это может указывать на:
- Атака на цепочку поставок: пакет был заменён вредоносной версией
- Пересборка без изменения версии: легитимно, но плохая практика
- Различное окружение сборки: проблемы воспроизводимости```bash
Example output with integrity drift
~ 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
Get drift summary
sbomlyze before.json after.json --json | jq '.diff.drift_summary'
Check for integrity drift in 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]
В режиме diff отслеживание изменений версий дубликатов включает:
- Новые дубликаты: компоненты, которые стали дублироваться в новом SBOM
- Устранённые дубликаты: группы дубликатов, которые были объединены
- Добавление/удаление версий: изменения версий в существующих группах дубликатов
Обнаружение коллизий
Коллизии — это неоднозначные совпадения идентификаторов, когда компоненты имеют один и тот же ID, но конфликтующие характеристики:
| Тип | Описание |
|---|---|
| Несовпадение имени | Разные имена компонентов, сопоставленные с одним и тем же идентификатором ID |
| Несовпадение хеша | Одна и та же версия компонента имеет разные хеши (возможное вмешательство) |
SBOMlyze SBOM Explorer (TUI)```bash
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 (Common Platform Enumeration)
- Список зависимостей
- Идентификаторы (ID, BOM-ref, SPDX-ID)
## Режим веб-интерфейса
Запустите браузерный обозреватель SBOM с загрузкой файлов методом перетаскивания:```bash
# Start web server on default port 8080
sbomlyze -web
# Start on custom port
sbomlyze -web --port 3000
Затем откройте http://localhost:8080 в браузере.
Возможности веб-интерфейса
| Функция | Описание |
|---|---|
| Загрузка перетаскиванием | Перетащите любой файл SBOM (Syft, CycloneDX, SPDX) на страницу (до 500 МБ) |
| Дерево зависимостей | Интерактивное дерево с навигацией разворачивания/сворачивания (постраничное для >5000 компонентов) |
| Сведения о компонентах | Просмотр лицензий, хэшей, зависимостей, информации о поставщике, количества файлов |
| Просмотр необработанного JSON | JSON с подсветкой синтаксиса для каждого компонента |
| Глубокий поиск | Поиск по всем полям, включая необработанные JSON-данные |
| Панель статистики | Метрики покрытия, категории лицензий, распределение языков |
| Обозреватель файловой системы | Просмотр файлов внутри SBOM с навигацией по каталогам, поиском и фильтрацией по слоям |
Отображаемая статистика
Веб-интерфейс показывает полную статистику, включая:
- Количество компонентов по типу пакета (npm, apk, pypi и т.д.)
- Распределение лицензий с разбивкой по категориям (копилефт, пермиссивные, общественное достояние)
- Метрики покрытия с визуальными индикаторами выполнения:
- Покрытие PURL (наличие URL пакета)
- Покрытие CPE (готовность к сканированию уязвимостей)
- Покрытие лицензий
- Покрытие хэшей/целостности
- Разбивка по языкам (для SBOM, созданных Syft)
- Статистика связей (contains, dependency-of, evident-by)
- Предупреждения об обнаружении дубликатов
Варианты использования
Проверка безопасности
- Загрузите SBOM и изучите полное дерево зависимостей
- Проверьте покрытие CPE, чтобы убедиться, что сканирование уязвимостей работает
- Просмотрите компоненты без лицензий или хэшей
Аудит соответствия
- Ищите конкретные лицензии по всем компонентам
- Просмотрите распределение по категориям лицензий (копилефт против пермиссивных)
- Экспортируйте необработанный JSON для документации
Отладка разработки
- Изучите, какие пакеты включены в ваш образ
- Проверьте транзитивные зависимости
- Убедитесь, что метаданные пакета корректны
Обозреватель файловой системы
Веб-интерфейс включает полноценный обозреватель файловой системы для изучения файлов в SBOM (особенно полезен для SBOM, созданных Syft, с метаданными файлов):
- Навигация по дереву каталогов с хлебными крошками
- Поиск файлов с поддержкой подстрок и glob-шаблонов (например,
*.so,/usr/lib/**/*.conf) - Фильтрация по слоям для SBOM образов контейнеров (просмотр файлов по слою образа)
- Связи компонентов с файлами (какой компонент владеет какими файлами)
- Статистика файлов по типу, MIME-типу, расширению и слою
- Обнаружение файлов без владельца (файлы, не связанные ни с одним компонентом)
Параметры
-i (Интерактивный режим)
Запустите терминальный TUI-обозреватель для навигации по SBOM с помощью клавиатуры.```bash sbomlyze image.json -i
Features: навигация по дереву, сведения о компонентах, поиск, проверка лицензий/хэшей.
### `-web` (Режим веб-сервера)
Запустите веб-сервер для просмотра SBOM через браузер.```bash
# Default port 8080
sbomlyze -web
# Custom port
sbomlyze -web --port 3000
Веб-интерфейс предоставляет загрузку перетаскиванием, интерактивное дерево, глубокий поиск и панель статистики.
--compliance
Оцените SBOM на соответствие фреймворкам минимальных элементов NTIA, CISA 2025 и BSI TR-03183. См. Оценка соответствия.```bash sbomlyze image.json --compliance sbomlyze image.json --compliance --json
### `--format` / `-f`
Выберите выходной формат. Доступно семь форматов:
| Формат | Флаг | Описание | Лучше всего для |
|--------|------|-------------|----------|
| **text** | `--format text` (по умолчанию) | Человекочитаемый вывод в терминал | Локальный просмотр |
| **json** | `--json` или `--format json` | Структурированный JSON | CI-конвейеры, скрипты |
| **sarif** | `--format sarif` | SARIF 2.1.0 для GitHub Code Scanning | Интеграция с GitHub |
| **junit** | `--format junit` | Результаты тестов JUnit XML | CI-панели тестирования |
| **markdown** | `--format markdown` | Markdown-отчёт, готовый для PR-комментариев | Комментарии к Pull request |
| **html** | `--format html` | Автономный HTML-отчёт (встроенные CSS/JS) | Аудиторы, отчёты для распространения |
| **patch** | `--format patch` | Операции JSON Patch (RFC 6902) | Программное применение патчей |```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
Формат SARIF
Формирует отчёт SARIF 2.1.0, подходящий для GitHub Code Scanning. Определяемые правила включают:
integrity-drift(ошибка): хэш изменён без изменения версииdeep-dependency(предупреждение): новая зависимость на глубине 3+new-component/removed-component(примечание): добавление/удаление компонентовversion-change(примечание): обновление версий компонентовpolicy-violation(ошибка/предупреждение): нарушения правил политики
Формат JUnit
Формирует JUnit XML с тестовыми случаями для проверки:
- отсутствия дрейфа целостности
- отсутствия глубоких транзитивных зависимостей (глубина 3+)
- соответствия политике (по одному тестовому случаю на каждое нарушение)
- сводки различий SBOM
Формат Markdown
Формирует отчёт в формате Markdown со следующими элементами:
- таблица сравнения SBOM бок о бок (файл, размер, ОС, метрики покрытия)
- детали контекста сканирования
- ключевые выводы
- добавленные/удалённые пакеты, сгруппированные по типу (в сворачиваемых разделах)
- сводка дрейфа, глубина зависимостей и нарушения политики
Формат HTML
Формирует один автономный HTML-файл (встроенные CSS и JavaScript, без внешних ресурсов), который удобно отправлять аудиторам по электронной почте или прикреплять к релизу. Он включает панель статистики, дерево зависимостей, сводку дрейфа, а при установке --compliance — также встроенный отчёт о соответствии.
Формат Patch
Формирует массив операций RFC 6902 JSON Patch (add, remove, replace), представляющих различия.
--json
Сокращение для --format json. Выводит результаты в формате JSON для программного использования.```bash
Stats as JSON
sbomlyze image.json --json
Diff as 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](#policy-engine) для подробностей.
### `--strict`
Немедленно завершать работу при любой ошибке разбора.```bash
sbomlyze broken.json --strict
# Error parsing broken.json: unknown SBOM format
# exit status 1
--tolerant (по умолчанию)
Продолжать обработку при ошибках, собирать предупреждения.```bash sbomlyze broken.json --tolerant
📦 SBOM Statistics
==================
Total Components: 0
...
⚠️ Parse Warnings (1):
[broken.json] unknown SBOM format
Предупреждения при разборе включают структурированную информацию: исходный файл, человекочитаемое сообщение и, опционально, поле, вызвавшее проблему.
### `--no-pager`
Отключает автоматический постраничный вывод. Полезно при передаче вывода в другую команду или при работе в неинтерактивных средах.```bash
sbomlyze image.json --no-pager
sbomlyze before.json after.json --no-pager | head -20
Policy Engine
Создавайте политики для применения правил в конвейерах CI/CD. sbomlyze завершает работу с кодом 1 при возникновении нарушений.
Формат файла политики```json
{ "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 }
### Правила политики
| Правило | Тип | Описание |
|------|------|-------------|
| `max_added` | int | Максимальное количество новых компонентов (0 = без ограничений) |
| `max_removed` | int | Максимальное количество удалённых компонентов (0 = без ограничений) |
| `max_changed` | int | Максимальное количество изменённых компонентов (0 = без ограничений) |
| `deny_licenses` | []string | Список запрещённых идентификаторов лицензий |
| `require_licenses` | bool | Требовать, чтобы все *добавленные* компоненты имели лицензии (в режиме diff проверяются только новые компоненты) |
| `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 (namespace) |
| 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
Подробнее см. в режиме преобразования.
Межформатное сравнение
sbomlyze может сравнивать SBOM в разных форматах:```bash
Compare Syft output with CycloneDX
sbomlyze syft-output.json cyclonedx-output.json
Compare SPDX with Syft
sbomlyze spdx-output.json syft-output.json
**Примечание:** Различные форматы SBOM извлекают разные уровни детализации. Межформатный diff может показывать изменения, отражающие различия форматов (например, доступность полей), а не реальные изменения системы. Система ключевых результатов предупредит о несоответствиях контекста сканирования при их обнаружении.
## Сопоставление идентификаторов компонентов
Компоненты сопоставляются с помощью системы идентификации, основанной на приоритете:
| Priority | Identifier | Example | Description |
|----------|------------|---------|-------------|
| 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` | Группа/namespace и имя |
| 5 | Name | `simple-package` | Запасной вариант — только имя |
## Интеграция с CI/CD
### GitHub Actions
SBOMlyze поставляется как JavaScript Action без зависимостей. Он сравнивает сохранённый в репозитории
или созданный отдельно head SBOM с файлом в git-базе pull request,
публикует 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
Действие никогда не запускает команды генератора. Создавайте головной SBOM на отдельном,
проверенном этапе или фиксируйте его в репозитории. comment и sarif по умолчанию имеют значение
false; PR из форков по-прежнему получают полную сводку задания, когда
недоступно разрешение на комментирование. См. справочник Action для получения информации обо всех
входных/выходных параметрах, SHA-pinning, загрузке SARIF, разрешениях и поведении безопасности.
GitLab CI```yaml
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
Предупреждение о глубоких зависимостях```bash
Alert on new deep transitive dependencies
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.
Примеры
Сравнение Docker-образов```bash
Generate SBOMs
syft nginx:1.25-alpine -o json > nginx-125.json syft nginx:1.26-alpine -o json > nginx-126.json
Compare
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
Обнаружение дрейфа зависимостей```bash
Detect any changes (strict mode for no drift)
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
Конвертация форматов SBOM```bash
Convert a Syft SBOM to CycloneDX for tools that require it
syft alpine:latest -o json > alpine-syft.json sbomlyze convert alpine-syft.json --to cyclonedx -o alpine-cdx.json
Convert CycloneDX to SPDX for compliance workflows
sbomlyze convert vendor-sbom.cdx.json --to spdx > vendor-sbom.spdx.json
Pipe conversion output directly
sbomlyze convert input.json --to spdx | jq '.packages | length'
### Explore SBOM in Browser```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
Интерактивное исследование терминала```bash
Explore with keyboard navigation
sbomlyze alpine.json -i
Navigate with arrow keys, search with '/', view details with Enter
## Разработка
### Запуск тестов```bash
make test
# or
go test -v ./...
Линт```bash
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```bash
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
## Contributing
Вклад приветствуется! Задачи для первого вклада помечены меткой [`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 или обсуждение, чтобы предложить изменения.
[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
