Что такое VEX

VEX и связь с отчётами об уязвимостях.

VEX (Vulnerability Exploitability eXchange) — формат документов, позволяющий поставщикам и операторам указывать, применима ли конкретная уязвимость (CVE) в данном продукте, компоненте или образе. Цель — уменьшить шум в отчётах сканирования: не все найденные CVE реально эксплуатируемы в вашем контексте (используемая версия пакета, отключённая функция, изолированная среда и т.п.).

VEX-документ связывает артефакт (например, образ контейнера), уязвимость (идентификатор CVE) и статус применимости (affected / not_affected / fixed и др.), при необходимости с обоснованием. Это помогает:

  • фокусироваться на реально применимых уязвимостях;
  • обоснованно исключать ложные срабатывания в отчётах и политиках (например, «запрет подов с критическими уязвимостями» с учётом VEX).

Спецификация VEX разрабатывается в рамках CISA и связана с форматами SBOM (Software Bill of Materials). Поддержка VEX в инструментах сканирования (в том числе в Trivy) позволяет учитывать такие документы при формировании отчётов и фильтрации уязвимостей.


Использование в платформе «Штурвал»

В платформе сканирование образов выполняется на базе Trivy (Модуль сканирования образов контейнеров, shturval-scanner). Размеченные уязвимости (в том числе с использованием VEX или внутренних процедур разметки) могут исключаться из отчёта или помечаться как неприменимые, чтобы в интерфейсе и при применении политик (например, блокировка подов с критическими CVE) учитывались только реально применимые уязвимости.

Когда модуль включён, в кластере формируются отчёты о выявленных уязвимостях в образах контейнеров (VulnerabilityReports), которые отображаются в разделе Безопасность на странице Анализ образов.

Для включения VEX в кластере применить ShturvalServicePatch (SSP) к shturval-scanner: оператор берёт документы из VEX-репозитория при сканировании.

После подключения VEX на странице Анализ образов остаются только те CVE, которые ещё нужно разбирать. Уязвимости, которые «Штурвал» разметил как неприменимые, из таблицы пропадают — сводка по Critical / High / Medium / Low их тоже не считает. Это ожидаемо: их убрали не потому, что сканер «не нашёл», а потому что в платформе они не эксплуатируются.

Чтобы понять, какие уязвимости исключили, в SSP можно включить параметр trivy.showSuppressed: true. По умолчанию он выключен и исключённые CVE нигде не сохраняются. Когда включен показ исключенных уязвимостей в отчёте report.modifiedFindings есть данные. В блоке report.modifiedFindings для каждой записи указаны идентификатор CVE, статус, причина исключения и источник (VEX).

Администрирование → Кастомные ресурсы → API-группа aquasecurity.github.io → VulnerabilityReport.

Список отчётов (колонка Modified — число исключённых CVE):

kubectl get vulnerabilityreports -A

Содержимое report.modifiedFindings у конкретного отчёта:

kubectl get vulnerabilityreport <имя> -n <неймспейс> -o jsonpath='{.report.modifiedFindings}'

Перед подключением переведите shturval-scanner в режим Авто. Как создавать SSP — Как управлять CustomValues сервисов.

Подключить VEX через ShturvalServicePatch

  1. Подготовьте манифест ShturvalServicePatch для shturval-scanner. Подставьте версию платформы в vexRepo.release и адрес репозитория в vexRepo.baseUrl.

    ПараметрОписаниеТипПример
    vexRepo.enabledВключает обращение Trivy к VEX-репозиторию (--vex repo) и монтирует repository.yaml. По умолчанию выключен.booleantrue
    vexRepo.baseUrlБазовый URL репозитория без /vex/{release}.stringhttps://public.shturval.tech/repository/shturval_bin_public
    vexRepo.releaseРелиз, для которого берутся VEX-документы. Итоговый URL: {baseUrl}/vex/{release}.string"2.15.0"
    vexRepo.nameИмя записи в repository.yaml. По умолчанию shturval.stringshturval
    vexRepo.insecureНе проверять TLS при обращении к репозиторию VEX.booleanfalse
    vexRepo.skipUpdateНе обновлять VEX при сканировании (--skip-vex-repo-update). Необходим, только если сканер не должен ходить в репозиторий.booleanfalse
    vexRepo.preloadСкачать VEX в init-контейнере scan job (trivy vex repo download). Для закрытого контура с зеркалом оставьте true и skipUpdate: false.booleanfalse
    trivy.showSuppressedСохранять исключённые уязвимости в report.modifiedFindings. По умолчанию false.booleantrue

    Если репозиторий требует аутентификацию, задайте vexRepo.username и vexRepo.password или vexRepo.token.

apiVersion: ops.shturval.tech/v1beta2
kind: ShturvalServicePatch
metadata:
  name: shturval-scanner-vex
spec:
  shturvalServiceConfigName: shturval-scanner
  patchOrder: 100
  customvalues:
    trivy:
      showSuppressed: true
    vexRepo:
      enabled: true
      baseUrl: https://public.shturval.tech/repository/shturval_bin_public
      release: "2.15.0"
      name: shturval
      insecure: false
      skipUpdate: false
      preload: false

В файлах VEX образы записаны как r.shturval.tech/.... В закрытом контуре сканер качает те же образы с вашего зеркала. Чтобы разметка сработала, в отчёте имя должно остаться r.shturval.tech, а не превратиться в адрес зеркала. Зеркало задайте в trivy.configFile.registry.mirrors. Не используйте trivy.registry.mirror — он подменяет имя на FQDN зеркала, и VEX перестаёт узнавать образы.

В примере вместо mirror.example.com укажите адрес вашего зеркала.

Если зеркало доступно из кластера, задайте preload: true и skipUpdate: false: Trivy скачает VEX с зеркала по пути {baseUrl}/vex/{release}. skipUpdate: true нужен только если сканер не должен обращаться к репозиторию. Как положить VEX на зеркало — Работа с зеркалом после инсталляции.

apiVersion: ops.shturval.tech/v1beta2
kind: ShturvalServicePatch
metadata:
  name: shturval-scanner-vex
spec:
  shturvalServiceConfigName: shturval-scanner
  patchOrder: 100
  customvalues:
    trivy:
      showSuppressed: true
      "-registry": {}
      configFile:
        registry:
          mirrors:
            r.shturval.tech:
              - mirror.example.com
        insecure: true
    vexRepo:
      enabled: true
      baseUrl: https://mirror.example.com/repository/shturval_bin_public
      release: "2.15.0"
      name: shturval
      insecure: true
      skipUpdate: false
      preload: true

Ключ "-registry": {} убирает уже включённую в сервисе подмену имени registry. Если её оставить, образы в отчёте снова получат адрес зеркала, и VEX их не узнает.

  1. Загрузите манифест через импорт манифестов.
  2. Откройте Сервисы и репозитории → Установленные сервисы → Модуль сканирования образов контейнеров (shturval-scanner). На вкладке Примененные ShturvalServicePatch должен появиться SSP shturval-scanner-vex. Когда он применится, на вкладке Сервис статус будет Patched.
  3. Подключитесь к кластеру в интерфейсе командной строки и удалите ранее сформированные отчёты VulnerabilityReport:
kubectl get vulnerabilityreports -A -o json | jq -r '.items[] | "\(.metadata.namespace) \(.metadata.name)"' | while read ns name; do kubectl delete vulnerabilityreport "$name" -n "$ns"; done
Скриншот: удаление VulnerabilityReports

Удаление VulnerabilityReports

Сканирование образов контейнеров перезапустится автоматически. 5. Проверьте запуск сканирования и формирование новых отчётов VulnerabilityReports:

kubectl get vulnerabilityreports -A
Скриншот: новые VulnerabilityReports

Проверка VulnerabilityReports

6. В графическом интерфейсе кластера откройте **Безопасность** → **Анализ образов** и убедитесь, что размеченные уязвимости отсутствуют в основном списке.
Скриншоты: отчёт до и после подключения VEX

Анализ образов до подключения VEX

Анализ образов после подключения VEX

Если в SSP задано trivy.showSuppressed: true, исключённые уязвимости можно проверить в ресурсе:

kubectl get vulnerabilityreports.aquasecurity.github.io -A -o json | jq -r '.items[] | select((.report.modifiedFindings // []) | length > 0) | "\(.metadata.namespace)/\(.metadata.name)\tmodified=\(.report.modifiedFindings | length)\tvulns=\((.report.vulnerabilities // []) | length)"'

Дополнительно