Skip to content

Алгоритм дедупликации

Finding — это результат одного сканирования, который содержит информацию об уязвимости. Finding считается родительским, если это является первой находкой для уязвимости, она создает issue.

Issue — это сущность в Vampy, которая содержит всю информацию об уязвимости, полученную из finding.

Finding считается duplicate, если во время импорта и работы алгоритма дедупликации была найдена совпадающая существующая issue. В этом случае дубликат finding связывается с issue.

Если дубликат определен, он связывается с issue и отображается в разделе Duplicate. Данные в issue берутся из родительской finding, дубликаты finding не обновляют их. Единственное поле, которое может быть обновлено — это solution.

Дедубликация — это алгоритм, который помогает Vampy распознавать идентичные issues в результатах сканирования.

Результат сканирования содержит несколько findings, которые включают в себя несколько полей, в зависимости от сканера. Обычно все сканы содержат repository name, branch name и внутренний дубликат отпечатка сканера — SD ID, но некоторые поля специфичны для различных видов сканеров.

SAST SCA DAST
CVE CVE CVE
CWE CWE CWE
file path file path asset host
file line number file line number asset path
code snippet library name asset query
library version

Основная проблема заключается в том, что не все сканеры заполняют эти поля, поэтому иногда мы можем получить несколько finding от разных сканеров, которые в основном ссылаются на одну и ту же issue. Для каждой finding Vampy создает несколько хешей на основе полей, которые содержит данная finding. Они используются для сравнения findings с существующими issues, чтобы выяснить, получили ли мы дубликат или нам нужно создать новую issue.

Таким образом, мы создаем следующие хеши для каждой finding

Приоритет SAST SCA DAST
1 repository + branch + SD ID
(необходимо SD ID)
repository + branch + product + artifact version + SD ID
(необходимо SD ID)
product + asset host + asset path + asset query + SD ID
(необходимо SD ID)
2 repository + branch + CVE + CWE + filepath + code snippet
(необходимы filepath и code snippet)
repository + branch + product + artifact version + CVE + CWE + filepath + file line number + library name + library version
(необходимы library name и library version)
product + asset host + asset path + asset query + CVE + CWE
(необходимо CVE)
3 repository + branch + CVE + CWE + filepath + file line number
(необходимы filepath и file line number)
repository + branch + product + artifact version + CVE + CWE + filepath + file line number + library name
(необходимо library name, пустое для поиска library version)
product + asset host + asset path + asset query + CVE + CWE + title
4 repository + branch + CVE + CWE + filepath + file line number + code snippet + title repository + branch + product + artifact version + CVE + CWE + filepath + file line number + library name + library version + title

Когда новые findings связываются с существующей issue, то и их хеши также связываются. В итоге мы имеем issue, которая имеет несколько хешей, полученных из всех findings, связанных с ней.

Примеры

SAST

Допустим, у нас есть 2 findings: A в качестве родительской и B как finding, которую нужно проверить на дубликат. У них есть все поля для SAST, A была найдена с помощью Semgrep, а B — с помощью Checkmarx. Как это выглядит в нашей системе? Красные стрелки показывают путь для наших примеров.

Здесь мы видим, что они не совпадают, поскольку у них разные отпечатки, полученные от разных сканеров. Но когда мы проверяем другие поля, мы понимаем, что это одна и та же issue.

SCA

Мы нашли Finding A, с заполненными полями. Он описывает уязвимость в кусочке кода, поддерживаемом библиотекой версии 1.0. Мы обновили версию библиотеки до 1.1, но уязвимость никуда не делась, и следующий скан выявляет Finding B.

Схема выглядит довольно просто.

Автоматическое изменение статусов

При обработке нового скана платформа автоматически сравнивает:

  • какие issues были найдены в текущей загрузке (как source finding или duplicate finding);
  • какие issues раньше были в этом же контексте, но в текущей загрузке уже не встретились.

Контекст сравнения зависит от типа загрузки:

  • репозиторий + ветка;
  • продукт + репозиторий + ветка;
  • продукт + актив;
  • продукт + версия артефакта.

Дополнительно сравнение выполняется в рамках того же парсера/саб-парсера. То есть отсутствие дефекта в одном сканере не закрывает дефект, найденный другим сканером.

Исключение: если результаты разных сканеров уже были явно объединены дедупликацией в один issue (например, два SAST-инструмента нашли одну и ту же уязвимость по критериям дедупликации), автопереходы применяются к этому issue как к единой сущности.

Какие переходы выполняются автоматически

Если дефект найден в новом скане:

  • NewRecurrent
  • FixedReopened

Если дефект не найден в новом скане:

  • NewFixed
  • RecurrentFixed
  • ReopenedFixed
  • ConfirmedFixed
  • Risk acceptedFixed

Статусы False Positive и Check required автоматически не переводятся.