Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
П35. VEX triage
Контекст практики П09. VDR и VEX различие факта и решения учит оформить одно решение. Здесь задача другая — провести триаж всего потока находок и сделать так, чтобы решения не лежали в текстовом файле, а машинно вычитались сканером: помеченные
not_affectedнаходки исчезают из выдачи, и gate перестаёт падать на разобранном шуме. Инструмент — OpenVEXvexctl(минимальный, формат-агностичный). Контролируемый результат — OpenVEX-документ, после применения которого число findings у сканера снижается ровно на разобранные CVE. Перед практикой прочитайте VEX в процессе РБПО.
Цель
По VDR из 5–10 находок:
- разнести каждую находку по статусу OpenVEX: not_affected / affected / fixed / under_investigation;
- для каждого not_affected указать обязательный justification из разрешённого перечня;
- указать author/issuer, который вправе выпускать VEX для этой версии продукта;
- собрать валидный OpenVEX-документ через vexctl create;
- применить его к выводу сканера так, чтобы разобранные not_affected находки ушли из отчёта, а affected — остались.
Проверяемый результат: число findings до триажа > числа findings после применения VEX, и разница равна количеству not_affected-записей.
Команда или действие
OpenVEX через vexctl (Go-инструмент проекта OpenVEX):
# 1. Исходный поток находок (тот же SBOM, что и в gate)
grype sbom:sbom.cdx.json -o table | tee before.txt
# 2. Решение по одной находке -> запись OpenVEX
vexctl create \
--product "pkg:npm/myapp@1.0.0" \
--subcomponent "pkg:npm/semver@7.3.7" \
--vuln "CVE-2022-25883" \
--status "not_affected" \
--justification "vulnerable_code_not_in_execute_path" \
--status-note "semver используется только на build-time, в рантайме недостижим" \
> vex.openvex.json
# (повторить для остальных находок; статусы affected/fixed/under_investigation
# объединить в один документ через несколько --vuln или vexctl merge)
# Проверьте, что author/issuer в итоговом документе отражает Product Security/PSIRT/AppSec,
# а не имя сканера или внешней базы уязвимостей.
# 3. Применить VEX при сканировании: not_affected уходят из отчёта
grype sbom:sbom.cdx.json --vex vex.openvex.json -o table | tee after.txt
Разрешённые justification для not_affected (OpenVEX): component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary, inline_mitigations_already_exist.
Что вы должны увидеть
Скелет OpenVEX-документа (vex.openvex.json):
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "https://openvex.dev/docs/public/vex-...",
"author": "AppSec / Организация",
"timestamp": "2026-06-18T10:00:00Z",
"statements": [
{
"vulnerability": { "name": "CVE-2022-25883" },
"products": [
{ "@id": "pkg:npm/myapp@1.0.0",
"subcomponents": [ { "@id": "pkg:npm/semver@7.3.7" } ] }
],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path"
}
]
}
Эффект применения — число findings падает:
# before.txt: 4 findings (CVE-2022-25883 High, CVE-... ...)
# after.txt: 3 findings <- CVE-2022-25883 отфильтрована как not_affected
Признак готовности: diff между before.txt и after.txt показывает ровно те CVE, которые вы пометили not_affected; affected/under_investigation остались в отчёте; gate в CI после VEX перестал падать на разобранном шуме, но продолжает падать на нетриажированных affected.
VEX не «глушит» уязвимость — он документирует решение
not_affectedбезjustificationиз перечня — невалидная запись:vexctlлибо отклонит её, либо она не отфильтрует находку. VEX безauthor/issuer и evidence — слабое управленческое утверждение. И помните: фильтрация работает, только если PURL вsubcomponentsточно совпадает с координатой компонента в SBOM. Несовпадение PURL = VEX «висит в воздухе», находка остаётся.
Если не получилось
after.txtравенbefore.txt— ничего не отфильтровалось. PURL в VEX не совпал с PURL компонента в SBOM (версия, namespace, qualifiers). Сверьте:jq '.components[] | select(.name=="semver") | .purl' sbom.cdx.jsonи тот же ref в VEX.vexctl: invalid justification. Использованjustificationне из перечня OpenVEX (например, скопирован из CycloneDX-словаря — там другие значения, см. П09. VDR и VEX различие факта и решения). Возьмите значение из списка выше.authorзаполнен внешним источником. NVD, БДУ, OSV, GHSA и upstream advisory не являются issuer вашего VEX. Их можно указать как evidence, но итоговое утверждение выпускает ответственная за продукт сторона.- Отфильтровались
affected-находки. Неверныйstatus: фильтр снимает толькоnot_affectedиfixed. Проверьте, что эксплуатируемые находки помеченыaffected, а не ошибочноnot_affected. - Документ невалиден /
vexctlмолчит. Нет обязательных полей верхнего уровня (@context,author,timestamp) или пустойstatements. Проверьтеjq . vex.openvex.jsonи наличие хотя бы одного statement.
Критерий зачёта
Показать преподавателю: (1) VDR из 5–10 находок и таблицу триажа со статусом, issuer/владельцем и evidence по каждой; (2) валидный OpenVEX-документ с author и justification из перечня для всех not_affected; (3) before.txt/after.txt, где разница findings = числу not_affected; (4) пояснение, чем эта практика отличается от П09. VDR и VEX различие факта и решения (там — одно решение, здесь — машинно применяемый триаж потока и срок пересмотра not_affected).
Нормативная связка
- М06. Поиск уязвимостей и управление VDR/VEX — родительский модуль.
- VEX в процессе РБПО — кто выпускает VEX, чем подтверждать
not_affected, где хранить evidence. - П09. VDR и VEX различие факта и решения · П06. Grype поверх готового SBOM · П08. Dependency-Track как портфель SBOM · П10. БДУ ФСТЭК как национальный источник · П16. GitLab CI security gate
- Политика управления уязвимостями компонентов · Регламент ретеста после исправления · Порядок принятия риска
- CycloneDX ECMA-424 (VEX-расширение) · NIST SP 800-218 SSDF (RV.2 — оценка и реагирование) · OWASP SCVS.