Перейти к содержимому

Сопоставление с CVE

Начиная с 2.0, enodia показывает, какие известные уязвимости затрагивают ровно ту версию, которую сообщил каждый таргет, — вместе с осями patch/lifecycle/branch, а не вместо них. Сверка идёт по двум публичным базам:

  • БДУ ФСТЭК — банк данных угроз ФСТЭК России, bdu.fstec.ru.
  • NIST NVD — американская National Vulnerability Database, nvd.nist.gov.

Каждый источник работает и в одиночку; если настроены оба, их находки объединяются по CVE. Всё это полностью опционально: конфиг без блока cve: ведёт себя ровно так же, как в 1.x.

Файлы скачиваете вы, вы же решаете, когда их обновлять, и указываете enodia, где они лежат. У enodia нет кода, который сам обращался бы к bdu.fstec.ru или nvd.nist.gov, — та же логика закрытого контура, что и в двухфазном дизайне: машине, на которой запускается check, для сверки с CVE не нужен интернет, нужна только копия файлов.

Один файл — полная выгрузка ФСТЭК (около 33 МБ в архиве):

Окно терминала
curl -fL --cacert ru-chain.pem \
-o /var/lib/enodia/cve/bdu/vulxml.zip \
https://bdu.fstec.ru/files/documents/vulxml.zip

У bdu.fstec.ru сертификат национального удостоверяющего центра Минцифры, которого нет в обычных системных хранилищах доверия, — простой curl падает с ошибкой сертификата. Кроме того, сервер не отдаёт свой промежуточный сертификат, а curl (в отличие от браузера) недостающий сам не скачивает, поэтому одного установленного корневого мало. Соберите бандл из корневого и того промежуточного, на который ссылается сертификат сайта:

Окно терминала
curl -fsS -o root.crt https://gu-st.ru/content/lending/russian_trusted_root_ca_pem.crt
curl -fsS -o sub.crt http://nuc-cdp.digital.gov.ru/cdp/subca_ssl_rsa2024.crt
{ cat root.crt; echo; cat sub.crt; } > ru-chain.pem

Проверено вживую 2026-09-23. Если перестанет работать — скорее всего, промежуточный сертификат сменили: актуальный указан в поле Authority Information Access сертификата самого сайта (openssl s_client -connect bdu.fstec.ru:443 | openssl x509 -noout -ext authorityInfoAccess). curl -k файл тоже скачает, но без проверки того, что вы затем подкладываете в свой отчёт по безопасности.

По одному файлу на год, nvdcve-2.0-<год>.json.gz, с 2002 по текущий. Сложите нужные в одну директорию:

Окно терминала
mkdir -p /var/lib/enodia/cve/nvd && cd /var/lib/enodia/cve/nvd
for y in $(seq 2002 "$(date +%Y)"); do
curl -fsSLO "https://nvd.nist.gov/feeds/json/cve/2.0/nvdcve-2.0-$y.json.gz"
done

Файл текущего года обновляется ежедневно, прошлые годы — редко. У каждого файла есть сопутствующий .meta (nvdcve-2.0-<год>.meta) с размером и sha256 — обратите внимание, хеш считается от распакованного JSON, а не от .gz.

Блок cve: в enodia.yaml — не в settings.yaml, поскольку он меняет саму оценку, а не только отображение:

enodia.yaml
schemaVersion: 1
cve:
bdu:
path: /var/lib/enodia/cve/bdu/vulxml.zip
nvd:
path: /var/lib/enodia/cve/nvd
targets:
- id: gitlab-main
product: gitlab
address: https://gitlab.example.com
credentials: gitlab-token
Поле Принимает
cve.bdu.path .xml, .zip (выгрузка в том виде, как её публикуют) или .tar.gz/.tgz
cve.nvd.path один файл .json, .json.gz или .json.zip, либо директорию с ними

Относительные пути резолвятся относительно директории того конфига, в котором они указаны, — так же, как credentials_file. Блок читается из того конфига, который реально использует запуск, — --config, $ENODIA_CONFIG или стандартные пути поиска. Это касается и check --from inventory.jsonl: инвентарь, собранный в закрытом контуре, сверяется там, где запускается check, если там находится конфиг с блоком cve:. Если конфиг не найден вовсе, check --from всё равно работает, просто без CVE.

Указанный путь, которого не существует, — это ошибка, а не тихий пропуск: check завершается с stat ...: no such file or directory, а не выдаёт отчёт, в котором CVE просто молча отсутствуют. enodia config validate проверяет форму блока (включая проверку на управляющие символы, см. ниже), но не существование файлов — оно проверяется только тогда, когда запуск действительно их загружает.

Оба источника разбираются потоково, результат кешируется в системной директории кеша ($XDG_CACHE_HOME/enodia/cve, по умолчанию ~/.cache/enodia/cve в Linux; ~/Library/Caches/enodia/cve в macOS; %LocalAppData%\enodia\cve в Windows). Первый запуск после изменения файла разбирает его целиком — около минуты на весь NVD плюс БДУ; замер 2026-09-23 на БДУ плюс одном файле NVD за 2026 год — 25 с. Все следующие запуски читают кеш: 0,2 с на тех же данных, кеш 11 МБ. TTL нет — ключ кеша строится по самим файлам (размер и время изменения) и по собственным таблицам продуктов enodia, поэтому замена файла, добавление года в директорию NVD или обновление enodia сами вызывают пересборку.

enodia serve перечитывает блок cve: и файлы на каждом цикле --interval (дёшево, из кеша), так что замена файлов по cron начинает действовать без перезапуска сервера.

  • check — колонка CVES в представлениях compact и drift: число различных CVE, затрагивающих именно эту версию. - означает, что находок нет: ни одна не затрагивает эту версию, нет блока cve: или продукт не сопоставляется (см. ниже); сама колонка есть всегда. У lifecycle и fleet этой колонки нет.
  • export --format html — та же колонка со ссылкой, открывающей список по таргету: одна строка на CVE, самые опасные сверху, со ссылками на NVD, cve.org и, для находок из БДУ, на страницу bdu.fstec.ru; русский текст из БДУ, если CVE есть в БДУ, иначе английское описание из NVD; оценка — цветными бейджами, например CRITICAL · CVSS 3.1 9.8. Сделано на чистом CSS — офлайн-отчёт по умолчанию по-прежнему не содержит JavaScript вообще.
  • export --format json — каждая находка каждого источника целиком, в массиве cves у каждой оценки: источник (bdu/nvd), идентификатор бюллетеня, идентификаторы CVE, заголовок, собственная текстовая оценка источника, сопоставленное имя продукта или CPE, диапазон версий и разобранная оценка CVSS. В отличие от таблицы и HTML-списка, где одна строка — один CVE, JSON хранит находку каждого источника отдельно: один и тот же CVE может встретиться один раз из БДУ и по разу на каждый подходящий CPE из NVD.
  • export --format prometheus — без данных о CVE.

CVE не влияют ни на severity, ни на код выхода. SEVERITY по-прежнему считается только по осям patch/lifecycle/branch, и --fail-on тоже знает только эти три оси — находка остаётся фактом, который стоит посмотреть, а не вердиктом, вынесенным enodia за вас. Нужно ли и как CVE должен повышать severity — открытый вопрос в апстриме.

52 из 90 продуктов, каждое имя вендора/продукта сверено дословно по реальным полным выгрузкам — источники для каждого указаны на его собственной странице в разделе Настройка продуктов.

Не сопоставляются, и у каждого случая своя причина:

  • Дистрибутивы Linux общего назначения (Debian, Ubuntu, RHEL, Alma, Rocky, Fedora, РЕД ОС, Astra Linux, …) — их CVE относятся к пакетам; номер релиза не говорит, какие пакеты с тех пор обновлены.
  • BSD-системы и Oracle Solaris — NVD хранит их уровень патчей (-p5 у FreeBSD, errata у OpenBSD) в поле CPE, которое этот механизм не читает; сверка только по релизу приписала бы полностью пропатченному хосту все CVE, когда-либо исправленные в этом релизе.
  • ESXi и vCenter — та же проблема: почти все записи вида 7.0 + update_1.
  • Synology DSM — границы вида 6.2.4-25556-3, которые строгий разбор диапазонов отклоняет.
  • TrueNAS — слишком мало записей, с другой нумерацией, чем сообщает проба.
  • Нет пригодных данных ни в одном источнике — Kitsu, Zou, postgres_exporter, Perforce Proxy, Perforce Helix Swarm.
  • generic — у самописного парсера нет идентичности продукта, по которой можно искать.

GitLab, HashiCorp Vault, Nextcloud и MongoDB публикуют отдельные списки CVE для community- и enterprise-редакций. Их пробы записывают редакцию сервера в extra.enterprise, и community-инстанс больше не видит находок только для enterprise — на реальных данных GitLab 19.2.2 CE видит 4 из 9 находок NVD, Nextcloud 27.1.3 CE — 11 из 23. Если редакция неизвестна (старый сервер её не сообщает), сохраняются все находки.

Проба ssh охватывает любую реализацию SSH, поэтому сопоставление идёт по баннеру: OpenSSH_… ищется как OpenSSH, dropbear_… — как Dropbear, а любой другой SSH-стек остаётся без сверки, а не получает чужие CVE от OpenSSH.

  • БДУ может давать лишние находки между ветками. Одна запись БДУ часто перечисляет отдельный диапазон на каждую поддерживаемую ветку, и у всех общая нижняя граница, поэтому версия, которая уже является исправлением в своей ветке, может попасть в более широкий диапазон соседней (задокументированный пример — Confluence 8.3.3 и CVE-2023-22515). У диапазонов NVD для того же CVE есть собственные нижние границы, и этой проблемы нет. enodia сознательно предпочитает показать находку, которую стоит перепроверить, чем молча пропустить настоящую.
  • Записи NVD без каких-либо ограничений по версии отбрасываются. По замерам на полных выгрузках это почти всегда были CVE десятилетней давности, привязанные к текущим релизам; цена — редкий действительно ещё не исправленный CVE, записанный таким образом.
  • Условия NVD на несколько продуктов («уязвимо только вместе с библиотекой Y») не вычисляются — проба сообщает один продукт на таргет, поэтому каждая уязвимая запись для сопоставленного продукта учитывается сама по себе.