Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
PURL pkg generic fallback
Почему это важно для SCA/OSA
PURL кодирует тип экосистемы (pkg:deb/..., pkg:conan/..., pkg:cargo/...), и именно по типу публичные сканеры решают, в какую базу идти за уязвимостями. Когда генератор SBOM находит C/C++ артефакт, который не лёг ни в один известный пакетный менеджер — статически вшитую библиотеку, файл из third_party/, бинарь без apt/dpkg-происхождения — он часто выдаёт pkg:generic/<name>@<version>. Это честный, но «немой» идентификатор: тип generic не указывает на публичный индекс, поэтому OSV/экосистемные сканеры по нему ничего не ищут. Компонент остаётся в SBOM, но фактически выпадает из матчинга.
generic — это не баг, а сигнал «инструмент не смог определить экосистему». Опасность в том, что строка выглядит как полноценная координата, и при беглом взгляде кажется, что компонент покрыт. На деле pkg:generic/openssl@3.0.11 и pkg:deb/debian/libssl3@3.0.11 для сканера — разные миры: первый не матчится, второй матчится.
Как это проявляется
Генератор SBOM не нашёл системного происхождения и подставил generic:
{ "type": "library", "name": "zlib", "version": "1.2.13",
"purl": "pkg:generic/zlib@1.2.13",
"properties": [{ "name": "cdx:bom:resolvedFrom", "value": "static-archive" }] }
Сравните с тем, что дал бы маппинг на пакет:
pkg:generic/zlib@1.2.13 → OSV: 0 находок (тип не маршрутизируется)
pkg:deb/debian/zlib1g@1:1.2.13.dfsg-1?arch=amd64 → OSV: матчится по deb-экосистеме
pkg:conan/zlib@1.2.13 → OSV: матчится по conan
Тот же эффект у вшитых форков: pkg:generic/customnet@1.0 для внутренней библиотеки без апстрима — это правильный fallback, его и не нужно тянуть к публичной координате. А вот pkg:generic/curl@7.88.1 — это упущенный публичный компонент, который надо переразметить в pkg:deb/... или pkg:conan/....
Слепая зона или приём
Слепая зона — принять generic за покрытие. Приём: разделить generic-компоненты на два класса. Первый — публичный OSS, для которого fallback случаен (инструмент не нашёл deb/conan-происхождение): его дотягивают до типизированного PURL и возвращают в матчинг. Второй — действительно внутренний компонент без апстрима: generic для него корректен, его версионируете и отслеживаете вручную, не выдумывая публичный тип.
Что делать на проекте
- Отфильтровать из SBOM все
pkg:generic/...— это явный worklist «без публичной координаты». - Для каждого решить: это публичный OSS или внутренний компонент? Подсказки — наличие апстрима, лицензия, имя.
- Публичные — переразметить: восстановить экосистему через
dpkg -S/rpm -qf(→pkg:deb/pkg:rpm) или Conan/vcpkg metadata (→pkg:conan), проверить матчинг на OSV. - Внутренние — оставить
generic, но завести собственную версию и наблюдение; не подменять публичным PURL. - Сохранять исходный
generic-PURL рядом как evidence того, откуда компонент попал в SBOM. - Не считать наличие
pkg:genericстроки покрытием: в отчёте о качестве данных это строка с пониженным confidence.
Связь
- Модуль: М04. Идентификаторы компонентов и уязвимостей (PURL как маршрут к OSV), М09. C/C++ legacy (откуда берутся безымянные компоненты).
- Практики: П24. PURL нормализация и private qualifiers (канон PURL), П25. CPE alias worklist (когда у компонента нет даже CPE).
- Нормативка: CISA Minimum Elements for SBOM (уникальный идентификатор как базовый элемент), BSI TR-03183-2 v2.1.0 (полнота и точность идентификаторов), NIST SP 800-218 SSDF (RV.1).
- Смежные заметки: dpkg apt metadata (как поднять generic до deb), SBOM evidence occurrences (чем подтвердить происхождение), detection accuracy (generic как скрытый false negative).