Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин 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, компонент остался бы «невидимым» для сопоставления с уязвимостями.
Слепые зоны именно этой темы
- Манифест-скан показывает объявленное, а не поставленное: dev-зависимости, неустановленные optional-пакеты искажают картину.
- Binary-скан теряет статически слинкованные библиотеки и плохо работает по stripped-бинарям.
- cdxgen без обогащения отдаёт C/C++ каркас без версий
.soи без DEB-координат. - Облачные/онлайн-режимы и публичные зеркала в инструментах: что и куда уходит — отдельное решение в закрытом контуре.
Связь с нормативкой
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 — управляемость работ.
Что уносим в работу
- Выбираем генератор по экосистеме: манифесты — Syft/cdxgen; образ + CVE одним шагом — Trivy; C/C++ — cdxgen с последующим обогащением.
- Всегда фиксируем tool version, commit/tag входа и параметры — без этого SBOM нельзя сравнивать.
- Для C/C++ сырой cdxgen-SBOM отдаём «генератору фактов» на обогащение ELF/DEB.
- Практики: П03. Генерация SBOM через Syft · П04. Генерация SBOM через cdxgen для C C++ · П05. Trivy как генератор и сканер.