Skip to main content

SBOM Generator & Formatter — full Python pipeline (no shell)

Project description

repo size last commit commit activity open PRs contributors

CI Docker Hub PyPI Python License GitHub Package

Инструмент для безопасной генерации, анализа и форматирования Software Bill of Materials (SBOM). runhelp

Навигация

Документация (docs/):

Разделы README:

Что делает:

  • Генерирует SBOM двумя генераторами (cdxgen + syft) и объединяет результат — из локальной директории, Git-репозитория (GitHub / GitLab) или контейнерного образа
  • Дедуплицирует компоненты по PURL и уязвимости по CVE+компонент
  • Создаёт два подписанных SBOM: без уязвимостей и с ними
  • Сканирует уязвимости параллельно через Trivy, OWASP Dependency-Check, Clair
  • Встраивает найденные уязвимости в SBOM (CycloneDX 1.5)
  • Опционально обогащает уязвимости идентификаторами БДУ ФСТЭК
  • Экспортирует читаемые отчёты: Excel (.xlsx), Word (.docx), ODT (.odt)
  • Готовит SBOM под требования ФСТЭК (secsbom cert — поля GOST)

Main CLI

mainhelp


Установка

PyPI:

pip install sbom-pipeline

GitHub Packages:

pip install sbom-pipeline \
  --index-url https://${GITHUB_TOKEN}@pypi.pkg.github.com/geminishkv/

Исходники:

git clone https://github.com/geminishkv/sbom_genform.git
cd sbom_genform
python3 -m venv venv && source venv/bin/activate
pip install -e ".[dev]"

Запуск утилиты

После установки доступна помощь:

secsbom --help

📖 Полное пошаговое руководство со всеми командами, сценариями и переменными окружения — в docs/USAGE.md.

Утилиту нужно запускать от обычного пользователя. Запуск с правами администратора/root завершается ошибкой, чтобы не выполнять сканеры и Docker-команды с лишними привилегиями.

Быстрый старт

Полный пайплайн генерирует SBOM, дедуплицирует компоненты, подписывает SBOM, сканирует уязвимости и экспортирует отчёты:

# локальный демо-проект
secsbom run

# указание локального проекта из примеров
secsbom run --path examples/project_inject

# удалёный репозиторий github с токеном
secsbom run --url https://github.com/org/repo --token ghp_... 

# удалёный репозиторий gitlab с токеном
secsbom run --url https://gitlab.com/org/repo --token glpat-... 

По умолчанию артефакты пишутся в secgensbom_out, отчёты — в secgensbom_reports.

Основные режимы

Сгенерировать и подписать SBOM без этапа сканирования уязвимостей:

secsbom gen-sbom --path examples/project_inject

Просканировать уже готовый SBOM (и/или контейнерный образ) и сформировать отчёты только по уязвимостям:

# путь к папке проекта + готовый SBOM
secsbom scan secgensbom_out/app-bom-dedup-signed.json --path examples/project_inject

# только готовый SBOM
secsbom scan secgensbom_out/app-bom-dedup-signed.json

# только контейнерный образ
secsbom scan --clair --image nginx:latest

Отформатировать готовые SBOM JSON в Excel/Word/ODT:

secsbom format --sbom-dir secgensbom_out --report-dir secgensbom_reports

Проверить подпись SBOM:

secsbom verify secgensbom_out/merged-bom-signed.json

Примечание: SHA-256-подпись — это контрольная сумма целостности (защита от случайной порчи), а не криптографическая подпись: она не подтверждает аутентичность источника, поскольку хэш и .sig пересчитываются после любого изменения файла. Для аутентичности и неотрекаемости используйте внешнюю подпись (cosign / sigstore).

Посмотреть краткую информацию по SBOM:

secsbom info secgensbom_out/merged-bom-signed.json

Проверить наличие внешних инструментов:

secsbom status

Сравнить два SBOM:

secsbom diff old-bom.json new-bom.json

Добавить поля GOST для отчёта по требованиям ФСТЭК:

secsbom cert sbom.json \
  --component-name "My Product" \
  --component-version "1.0.0" \
  --manufacturer "My Company"

Полезные флаги и переменные

secsbom run --no-cdxgen          # не использовать cdxgen
secsbom run --no-syft            # не использовать syft
secsbom run --bdu                # включить BDU-обогащение
secsbom run --clair --image nginx:latest
secsbom run -o secgensbom_out --reports-dir secgensbom_reports

Те же настройки можно передавать через переменные окружения:

export PROJECT_DIR=examples/project_inject
export OUTPUT_DIR=secgensbom_out
export REPORTS_DIR=secgensbom_reports
export BDU=true
export NVD_API_KEY=<token>

secsbom run

Для scan используются кэши внешних данных:

  • .dependency-check-data / DEP_CHECK_DATA — база NVD для OWASP Dependency-Check
  • .bdu_cache / BDU_CACHE_DIR — соответствия CVE -> BDU ID

Сами этапы scan при повторном запуске выполняются заново, кэшируются именно базы и справочные ответы внешних инструментов.


Выходные артефакты

SBOM JSON

Файл Описание
secgensbom_out/app-bom-cdxgen.json SBOM от cdxgen
secgensbom_out/app-bom-syft.json SBOM от syft
secgensbom_out/app-bom-merged.json Объединённый SBOM (cdxgen + syft)
secgensbom_out/app-bom-dedup.json После дедупликации компонентов
secgensbom_out/app-bom-dedup-signed.json Подписанный SBOM без уязвимостей
secgensbom_out/app-bom-dedup-signed.sig SHA-256 контрольная сумма (без уязв.)
secgensbom_out/merged-bom-signed.json Подписанный SBOM с уязвимостями
secgensbom_out/merged-bom-signed.sig SHA-256 контрольная сумма (с уязв.)
secgensbom_out/vulns-normalized.json Нормализованные уязвимости
<sbom>(cert).json SBOM с полями GOST/ФСТЭК (команда cert)

Если включено BDU-обогащение, в merged-bom-signed.json идентификатор БДУ записывается в vulnerabilities[].properties[] как свойство с именем ru.fstec.bdu:id.

Отчёты сканеров

Путь Сканер
secgensbom_out/trivy/trivy-fs.json Trivy — файловая система
secgensbom_out/trivy/sbom-vulns.json Trivy — анализ SBOM
secgensbom_out/dependency-check/ OWASP Dependency-Check
secgensbom_out/clair/ Clair (если включён)

Reports

Путь Формат Содержимое
secgensbom_reports/excel/*.xlsx Excel Лист 1: компоненты, Лист 2: уязвимости
secgensbom_reports/docx/*.docx Word Таблица компонентов + таблица уязвимостей
secgensbom_reports/odt/*.odt ODT То же самое

Лист «Компоненты»

Колонка Источник
№ п/п порядковый номер
Наименование компонента components[].name из SBOM
Версия компонента components[].version из SBOM
Тип пакета / тип компонента тип экосистемы из PURL (pypi, maven, npm, apk, …)
PURL / технический идентификатор компонента components[].purl из SBOM
Язык (языки) определяется по PURL-типу (dependency.py)
Признак принадлежности к поверхности атаки свойство компонента CycloneDX: attack-surface / attackSurface / isAttackSurface / GOST: attack_surface
Признак выполнения функций безопасности свойство компонента CycloneDX: security-function / securityFunction / isSecurityFunction / GOST: security_function
Принадлежность к контейнерному образу metadata.component.name (только если type = "container")
Роль компонента в составе контейнерного образа свойство компонента: container-role / containerRole / cdx:docker:layer / layer
Адрес веб-ресурса реестровый URL, вычисленный по PURL

Лист «Уязвимости»

Колонка Источник
Компонент имя пакета из сканера
Версия версия при сканировании
CVE / ID идентификатор уязвимости
CVSS оценка CVSS v3 / v2
Критичность CRITICAL / HIGH / MEDIUM / LOW / UNKNOWN
Описание первые 200 символов описания
Сканер trivy / clair / dependency-check
Исправлено в версии версия с исправлением (если известна)
Рекомендация / компенсирующая мера Trivy: PrimaryURL → «Обновить до X»; Clair: Links[0]; Dependency-Check: notesreferences[].url
Статус допустимости в рассматриваемой конфигурации Trivy: поле Status (fixed, affected, will_not_fix, end_of_life, …)

Если пайплайн запущен с --bdu или BDU=true, во всех форматах отчётов уязвимостей появляется отдельная колонка BDU / ID. Если BDU-обогащение выключено, эта колонка не выводится.


Примеры результатов

Подробные примеры итогового SBOM, vulns-normalized.json и экспортируемых таблиц вынесены в docs/RESULT_EXAMPLES.md.

Короткий пример структуры после полного запуска:

secgensbom_out/
├── app-bom-dedup-signed.json
├── merged-bom-signed.json
├── vulns-normalized.json
├── dependency-check/
├── trivy/
└── clair/
secgensbom_reports/
├── excel/merged-bom-signed.xlsx
├── docx/merged-bom-signed.docx
└── odt/merged-bom-signed.odt

BDU Enrichment

Обогащение идентификаторами БДУ ФСТЭК выключено по умолчанию.

Включение через CLI:

secsbom run --bdu

Включение через переменную окружения:

export BDU=true
secsbom run

При включённом BDU пайплайн:

  • запрашивает соответствия CVE -> BDU ID через bdu.fstec.ru
  • добавляет BDU ID в итоговый CycloneDX SBOM как свойство уязвимости
  • выводит BDU ID в экспортируемые отчёты

Пример фрагмента SBOM:

{
  "id": "CVE-2023-1234",
  "properties": [
    {
      "name": "ru.fstec.bdu:id",
      "value": "BDU:2023-01813"
    }
  ]
}

Docker

Образ включает Python, Syft, Trivy, Docker CLI и Node.js/npx (cdxgen для non-Python проектов). OWASP Dependency-Check запускается внутри утилиты через docker run (Docker-in-Docker), его Java-зависимость утяжелила бы основной образ на ~400 МБ. Clair требует отдельного работающего HTTP-сервера — поэтому он вынесен в docker-compose.yml.

Безопасность образа: контейнер работает от непривилегированного пользователя sbom (uid 1001) — secsbom отказывается запускаться от root. В docker-compose.yml сервисам secgensbom / scan заданы security_opt: no-new-privileges и cap_drop: ALL. В образ встроен HEALTHCHECK, OCI-метки указывают лицензию Apache-2.0.

Docker Hub (только Trivy, без Clair/Dependency-Check)

docker pull geminishkv/sbom-pipeline:latest

docker run --rm \
  -v "$(pwd)/examples/project_inject:/app/project_inject" \
  -v "$(pwd)/secgensbom_out:/app/secgensbom_out" \
  -v "$(pwd)/secgensbom_reports:/app/secgensbom_reports" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  geminishkv/sbom-pipeline:latest

Docker Compose (Trivy + Dependency-Check + Clair)

Полный стек с OWASP Dependency-Check и Clair v4 запускается через docker-compose.yml.

Всё одной командой (компоненты + контейнеры + SBOM + отчёты)

Поднимает Clair, собирает SBOM по исходному коду, сканирует уязвимости (Trivy + Dependency-Check + Clair) и контейнерный образ, обогащает БДУ ФСТЭК и выгружает отчёты — NVD-ключ не нужен:

SKIP_CLAIR=false BDU=true IMAGE_NAME=nginx:latest docker compose up --build
  • Код проекта берётся из ./examples/project_inject — замените содержимое этой папки на свой проект (или переопределите volume secgensbom в docker-compose.yml).
  • IMAGE_NAME — контейнерный образ для сканирования через Clair (по умолчанию postgres:14).
  • SKIP_CLAIR=false включает анализ контейнерного образа; BDU=true добавляет идентификаторы БДУ ФСТЭК.
  • Без NVD_API_KEY база NVD для Dependency-Check скачается автоматически при первом запуске (~220 МБ, несколько минут; она кэшируется в ./.dependency-check-data и переиспользуется далее). Clair на первом запуске прогревает updater'ы до ~10 минут.
  • Результат: ./secgensbom_out/ (SBOM-артефакты) + ./secgensbom_reports/{excel,docx,odt}/ (отчёты по компонентам и уязвимостям).

Минимальный запуск (только демо-проект, без сканирования образа):

docker compose up --build

Порядок запуска:

  1. clair-db (Postgres) — база данных Clair, ожидает healthcheck
  2. clair — HTTP-сервер уязвимостей Clair v4, ожидает готовности БД
  3. secgensbom — основной пайплайн, стартует после того, как Clair пройдёт healthcheck

Что происходит внутри secgensbom:

  • Trivy запускается напрямую (встроен в образ)
  • OWASP Dependency-Check запускается через docker run owasp/dependency-check (Docker-in-Docker через /var/run/docker.sock)
  • Clair сканирует образ через clairctl, подключаясь к http://clair:8080

Переменные окружения:

Переменная По умолчанию Описание
SOURCE local Источник проекта: local, github, gitlab
PROJECT_DIR /app/project_inject Путь к проекту внутри контейнера
SKIP_CLAIR false Отключить сканирование Clair (true/false)
CLAIR_ENDPOINT http://clair:8080 Адрес Clair API
IMAGE_NAME Docker-образ для сканирования Clair
BDU false Включить обогащение идентификаторами БДУ ФСТЭК
DEP_CHECK_DATA /app/.dependency-check-data Кэш NVD для Dependency-Check
NVD_CACHE_DIR $DEP_CHECK_DATA/nvd-api-cache Кэш ответов NVD API для повторного CVSS lookup
SBOM_COMPONENT_NETWORK false Разрешить сетевые уточнения языков/URL при экспорте компонентов

Примечание: Если IMAGE_NAME не задан, шаг Clair пропускается автоматически.

NVD_CACHE_DIR хранит ответы NVD API по CVE и используется Clair fallback при заполнении пустого CVSS. Повторный запуск берёт оценку из уже сохранённого ответа и не делает новый HTTP-запрос. По умолчанию экспорт компонентов не ходит в npm/NuGet/Debian/GitHub за уточнениями; для максимально быстрых и воспроизводимых отчётов язык и URL вычисляются из PURL.

Troubleshooting

Частые ошибки запуска, сетевых лимитов NVD, Docker/Clair и пустых отчётных колонок собраны в docs/TROUBLESHOOTING.md.


CI/CD

GitHub Actions

Workflow Триггер Назначение
ci.yml push / PR → main lint + mypy + pytest (3.11–3.13)
secgensbom.yml push → securitycheck, вручную запуск пайплайна, сохранение SBOM и отчётов
publish.yml тег v*.*.* GitHub Packages + PyPI + Docker Hub + GitHub Release

Публикация новой версии — один тег запускает всё:

git tag v2.2.0 -m "Release v2.2.0"
git push origin v2.2.0

Shared template

Файл secgensbom/secgensbom.yml — это переиспользуемый шаблон CI для GitLab. Любой другой проект в GitLab может подключить готовый SBOM-шаг одной строкой, не копируя конфигурацию:


Архитектура

Пайплайн secsbom run

flowchart TD
    IN(["Источник\nlocal / github / gitlab / образ"]) --> STEP1

    subgraph pipeline["secsbom run — этапы"]
        subgraph STEP1["1 · Генерация SBOM"]
            direction TB
            CDXGEN["cdxgen\napp-bom-cdxgen.json"]
            SYFT["syft\napp-bom-syft.json"]
            GEN["generate.py — merge\napp-bom-merged.json"]
            CLAIR_SCAN["clair.py — run_scan_report()\nclair-*.json\nполучение пакетов образа"]
            CLAIR_ENRICH["clair.py — enrich_sbom_with_clair_packages()\nдобавление пакетов образа в SBOM\n(только добавление, без обновления)"]
            CDXGEN --> GEN
            SYFT --> GEN
            GEN --> CLAIR_SCAN --> CLAIR_ENRICH
        end

        STEP1 --> DEDUP["2 · dedup.py\napp-bom-dedup.json\nдедуп компонентов по PURL\n(cdxgen + syft + Clair)"]
        DEDUP --> SIGN1["3 · sign.py\napp-bom-dedup-signed.json + .sig\nSHA-256 — SBOM без уязвимостей"]
        SIGN1 --> SCAN

        subgraph SCAN["4 · scanner/ — параллельно (ThreadPoolExecutor)"]
            direction LR
            TRIVY_FS["trivy.py — scan_filesystem\ntrivy-fs.json (опц. --path)"]
            TRIVY_SBOM["trivy.py — scan_sbom\nsbom-vulns.json"]
            DEPCHECK["depcheck.py — docker run\ndependency-check-report.* (опц. --path)"]
            CLAIR_VULNS["clair.py — parse_report_findings()\n+ NVD CVSS fallback (опц. --image)"]
        end

        TRIVY_FS & TRIVY_SBOM & DEPCHECK & CLAIR_VULNS --> CROSS["cross-populate CVSS\nмежду сканерами"]
        CROSS --> DDUP2["5 · dedup.py\nдедуп уязвимостей\nпо CVE + компонент"]
        DDUP2 --> MERGE["6 · vuln_merger.py\nvulnerabilities[] в SBOM\n+ БДУ ФСТЭК (опц. --bdu)\nvulns-normalized.json"]
        MERGE --> SIGN2["7 · sign.py\nmerged-bom-signed.json + .sig\nSHA-256 — SBOM с уязвимостями"]
        SIGN2 --> EXPORT["8 · exporter.py"]
    end

    CLAIR_SCAN -.->|"отчёт повторно используется\nна этапе 4"| CLAIR_VULNS

    EXPORT --> XLSX["secgensbom_reports/\n*.xlsx"]
    EXPORT --> DOCX["secgensbom_reports/\n*.docx"]
    EXPORT --> ODT["secgensbom_reports/\n*.odt"]

Структура репозитория

sbom_genform/
├── src/sbom_pipeline/
│   ├── cli.py            # secsbom / secsbom-pipeline (typer)
│   ├── pipeline.py       # оркестратор
│   ├── generate.py       # генерация SBOM
│   ├── dedup.py          # дедупликация
│   ├── sign.py           # SHA-256 подпись
│   ├── exporter.py       # xlsx / docx / odt
│   ├── vuln_merger.py    # встраивание уязвимостей
│   ├── config.py         # конфигурация
│   ├── scanner/
│   │   ├── trivy.py
│   │   ├── depcheck.py
│   │   └── clair.py
│   └── enrichters/
│       ├── bdu.py        # БДУ ФСТЭК (CVE → BDU ID)
│       └── nvd.py        # NVD API (CVSS fallback)
├── docker/
│   └── Dockerfile.secgensbom
├── examples/project_inject/   # уязвимый PHP проект
├── secgensbom/secgensbom.yml  # GitLab CI shared template
├── .github/workflows/
│   ├── ci.yml
│   ├── secgensbom.yml
│   └── publish.yml
├── tests/test_smoke.py
├── pyproject.toml
└── .env.example

Copyright (c) 2026 Elijah S Shmakov

Logo

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sbom_pipeline-2.2.0.tar.gz (7.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

sbom_pipeline-2.2.0-py3-none-any.whl (79.5 kB view details)

Uploaded Python 3

File details

Details for the file sbom_pipeline-2.2.0.tar.gz.

File metadata

  • Download URL: sbom_pipeline-2.2.0.tar.gz
  • Upload date:
  • Size: 7.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sbom_pipeline-2.2.0.tar.gz
Algorithm Hash digest
SHA256 26c85cab8f6fafa452cdec804c7c4efcf3a3a2092f98c8c21544deed608df4fe
MD5 9539555486934b619a3762d369b348fc
BLAKE2b-256 c9c2843c2781c30b3b47419b2b9dd8faf7f867292104ad076b6fff2a547c7e53

See more details on using hashes here.

File details

Details for the file sbom_pipeline-2.2.0-py3-none-any.whl.

File metadata

  • Download URL: sbom_pipeline-2.2.0-py3-none-any.whl
  • Upload date:
  • Size: 79.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for sbom_pipeline-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 576e31e98a6536363444160c6b868848cd63a64735118c0c5c3a16423afbd563
MD5 91bb70f7068ba2d9a135e780d234061c
BLAKE2b-256 0df7967b16ffe273aab1a210ad5eeb72f3314b7dd951059ef793c301e5438833

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page