Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
version normalization
Почему это важно для SCA/OSA
Матчинг на уязвимости — это не сравнение строк, а проверка попадания версии в уязвимый диапазон CVE (versionStartIncluding, versionEndExcluding). Но «версия» в C/C++ записывается десятком несовместимых способов: upstream-тег 3.0.11, debian-версия 3.0.11-1~deb12u2 с epoch и ревизией, RPM-релиз 3.0.11-2.el9, строка из бинаря OpenSSL 3.0.11 19 Sep 2023, suffix 1.2.13.dfsg. Если в SBOM попала дистрибутивная строка целиком, а CVE оперирует upstream-версией, сравнение версий ломается — и снова не как ошибка, а как тишина в findings.
C/C++ особенно уязвим, потому что одна и та же библиотека приходит из разных миров с разными схемами версий: системный apt/rpm, Conan, ручной third_party/. Нормализация версии — это приведение к той форме, в которой её сравнивает целевая база уязвимостей, с сохранением исходной строки для трассировки.
Как это проявляется
Дистрибутивная версия несёт лишние компоненты, которых нет в CVE-диапазоне:
upstream (как в CVE): 3.0.11
deb: 3.0.11-1~deb12u2 epoch? rev=-1 +~deb12u2
rpm: 3.0.11-2.el9 release=-2.el9
из бинаря: "OpenSSL 3.0.11 19 Sep 2023"
+dfsg/+ds: 1.2.13.dfsg-1 +dfsg — переупаковка, не апстрим-версия
epoch: 1:1.2.13.dfsg-1 ведущее "1:" — debian epoch
Сравнение версий по-разному ведёт себя в разных схемах: для deb это dpkg --compare-versions, для rpm — rpmdev-vercmp, для упорядоченных по компонентам — semver. Поэтому одну и ту же версию нельзя сравнивать «как строку»:
$ dpkg --compare-versions "3.0.11-1~deb12u2" lt "3.0.11" && echo "tilde < release"
tilde < release # ~ делает версию МЕНЬШЕ базовой — частый источник ошибок
Для матчинга на NVD из 3.0.11-1~deb12u2 нужно извлечь upstream-ядро 3.0.11; ревизию -1~deb12u2 и epoch сохранить отдельно — они различают сборку, но не входят в CVE-диапазон upstream.
Слепая зона или приём
Слепая зона — сравнивать версии лексикографически и терять смысл суффиксов. 3.0.11-1~deb12u2 строкой «больше» 3.0.11, а по правилам Debian — меньше; 1.2.13.dfsg — это та же upstream 1.2.13, переупакованная. Приём: знать схему версии источника (deb/rpm/semver) и сравнивать её родными правилами, отделяя upstream-ядро (для CVE-диапазона) от distro-метаданных (для трассировки сборки). Не выкидывайте epoch и ревизию — сохраняйте их рядом.
Что делать на проекте
- Для каждого компонента фиксировать схему версии источника: deb, rpm, conan/semver, строка из бинаря.
- Выделять upstream-ядро версии для матчинга на upstream-CVE; epoch/ревизию/
+dfsgхранить отдельно как distro-метаданные. - Сравнивать версии родными правилами:
dpkg --compare-versionsдля deb,rpm-сравнение для rpm, semver — для упорядоченных. - Сверять не точную строку, а попадание в уязвимый диапазон CVE (
versionStartIncluding/versionEndExcluding). - Сохранять исходную строку версии в SBOM как evidence — не затирать её нормализованной.
- Отдельно проверять версии, восстановленные из бинаря: формат там свободный и легко искажается.
Связь
- Модуль: М04. Идентификаторы компонентов и уязвимостей (версия — часть координаты), М09. C/C++ legacy (разные источники версий).
- Практики: П24. PURL нормализация и private qualifiers (версия внутри PURL), П25. CPE alias worklist (версия в CPE-диапазоне).
- Нормативка: BSI TR-03183-2 v2.1.0 (точность идентификаторов, включая версию), CISA Minimum Elements for SBOM (версия как базовый элемент), NIST SP 800-218 SSDF (RV.1).
- Смежные заметки: dpkg apt metadata (откуда deb-версии с epoch), CPE alias для libssl3 (версия + alias), detection accuracy (версия как источник пропусков).