Пиков / КАПО
Как читать авторский курс и нормативные материалы

Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.

Конспект: Инструменты генерации SBOM

Зачем модуль

SBOM — это не свойство проекта, а снимок, сделанный конкретным инструментом. Запустите Syft, Trivy и cdxgen на одном и том же репозитории — получите три разных bom.json: с разным числом компонентов, разной долей заполненных PURL, разным набором лицензий. Разница не в «качестве» инструментов, а в том, куда каждый из них смотрит. Поэтому первый вопрос аудита SBOM — не «сколько там компонентов», а «чем и на каком входе он сгенерирован». Модуль учит читать SBOM с поправкой на инструмент и осознанно выбирать генератор под экосистему.

Ключевая идея модуля развёрнута отдельно Почему генерация SBOM — это инженерное искусство, чем плохой SBOM отличается от хорошего и почему в C/C++ это «искусство в квадрате» — собрано в одной заметке: Почему генерация SBOM — это искусство.

Ключевые идеи

Манифест-скан против бинарь-скана. Манифест-скан читает декларации: package-lock.json, requirements.txt, go.mod/go.sum, Cargo.lock. Он быстр, даёт устойчивые PURL, но видит только то, что объявлено, — и не видит, что реально попало в артефакт. Бинарь-скан анализирует собранный образ или ELF-файл: распаковывает слои контейнера, ищет установленные пакеты, читает таблицы линковки. Он видит фактически поставленное, но хуже восстанавливает версии и легко спотыкается о статическую линковку и stripped-бинари.

Что видит каждый инструмент. Syft — «инвентаризатор файловой системы и образов»: ходит по каталогам и слоям, распознаёт пакеты десятков экосистем (npm, PyPI, Go, Maven, RPM, DEB, APK), отдаёт SPDX или CycloneDX. Уязвимости он не считает — это работа парного Grype. Trivy совмещает оба режима: генерирует SBOM и сразу матчит его на CVE из собственной БД, удобен как единый CI-шаг. cdxgen восстанавливает граф из системы сборки для большого числа экосистем и, что важно для нас, умеет режим -t cpp для C/C++, где остальные пасуют.

C/C++ и обогащение. Для C/C++ ни один генератор не отдаёт полный состав: #include не задаёт версию, а статически вшитая библиотека исчезает из артефакта. cdxgen даёт каркас, а недостающие факты — динамические .so (через анализ ELF) и их привязку к системным DEB-пакетам — дотягивает отдельная enrichment-утилита, «генератор фактов»: она читает ELF, определяет слинкованные библиотеки, маппит их на DEB через apt, дополняет метаданные из PyPI/npm/Conan/apt и пишет обогащённый CycloneDX bom.json.

Tool version и вход — часть результата SBOM без зафиксированных версии инструмента, commit/tag входа и параметров запуска невоспроизводим: завтра другая версия Syft даст другой набор компонентов, и вы не поймёте, изменился проект или инструмент. Фиксируйте syft version/trivy --version/cdxgen --version рядом с bom.json.

Как выглядит на практике

Инструмент Что видит Чего не видит Уязвимости
Syft пакеты в ФС и образах (npm/PyPI/Go/RPM/DEB/APK), манифесты + установленное граф сборки C/C++, статическую линковку нет (нужен Grype)
Trivy то же + слои образа, ОС-пакеты детальный C/C++ граф да, встроенный матчинг CVE
cdxgen граф из системы сборки, многие экосистемы, режим C/C++ динамику ELF и DEB-привязку без обогащения нет
# манифест-скан каталога → CycloneDX
syft dir:. -o cyclonedx-json=syft-bom.json
# генерация + сканирование образа одним шагом
trivy image --format cyclonedx --output trivy-bom.json myapp:1.4
# C/C++ граф из системы сборки
cdxgen -t cpp -o cdxgen-bom.json .

Фрагмент bom.json (CycloneDX), показывающий, чем «полный» компонент отличается от «слепого»:

{ "type": "library", "name": "openssl", "version": "3.0.11",
  "purl": "pkg:deb/debian/openssl@3.0.11",
  "licenses": [{ "license": { "id": "Apache-2.0" } }] }

Здесь есть purl — анализатор найдёт CVE. Если бы строка была { "name": "libssl", "version": null } без PURL, компонент остался бы «невидимым» для сопоставления с уязвимостями.

Слепые зоны именно этой темы

Связь с нормативкой

NIST SP 800-218 SSDF (PS.3.2) требует формировать и хранить SBOM; BSI TR-03183-2 v2.1.0 задаёт критерии качества (полнота PURL, лицензии, dependencies); CycloneDX ECMA-424 — формат; NTIA Minimum Elements for SBOM и CISA Minimum Elements for SBOM — обязательный минимум полей; ГОСТ Р 56939-2024 — управляемость работ.

Что уносим в работу