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

Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин 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 для него корректен, его версионируете и отслеживаете вручную, не выдумывая публичный тип.

Что делать на проекте

  1. Отфильтровать из SBOM все pkg:generic/... — это явный worklist «без публичной координаты».
  2. Для каждого решить: это публичный OSS или внутренний компонент? Подсказки — наличие апстрима, лицензия, имя.
  3. Публичные — переразметить: восстановить экосистему через dpkg -S/rpm -qf (→ pkg:deb/pkg:rpm) или Conan/vcpkg metadata (→ pkg:conan), проверить матчинг на OSV.
  4. Внутренние — оставить generic, но завести собственную версию и наблюдение; не подменять публичным PURL.
  5. Сохранять исходный generic-PURL рядом как evidence того, откуда компонент попал в SBOM.
  6. Не считать наличие pkg:generic строки покрытием: в отчёте о качестве данных это строка с пониженным confidence.

Связь