Представим, что после очередного сканирования инфраструктуры сертифицированным сканером вы получили красивый HTML- или PDF-отчет на сотни страниц. Его можно открыть, пролистать, даже отправить кому-нибудь на почту, но вот встроить результаты такого сканирования в рабочий процесс обработки уязвимостей уже сложнее. Особенно если речь идет о сертифицированных решениях, которые чаще всего не поддерживают передачу результатов в удобном формате для дальнейшей автоматизации. В итоге данные живут порознь: сканер отдельно, Jira отдельно, DefectDojo отдельно, а аналитики продолжают искать нужные CVE в огромных отчетах.

В статье не будет слов про домашнюю безопасность или очередной «пентест за 15 минут». Материал рассчитан на специалистов по информационной безопасности, DevSecOps-инженеров и администраторов, которым нужно встроить результаты сетевого сканирования, выполненного сертифицированным сканером, в существующие процессы управления уязвимостями и не переплачивать за платные конвертеры. Разберем, как превратить HTML-отчеты «Сканер-ВС» в структурированный JSON, автоматически загружать результаты в DefectDojo и при необходимости написать собственный парсер для более глубокой интеграции.

Ранее мы рассказывали об автоматизированном запуске решения «Сканер-ВС» с помощью скриптов. Рекомендуем ознакомиться, если интересна эта тема:

Сегодня разберем, как извлекать из отчетов наиболее ценную информацию и работать с ней в удобном виде.

Целевая схема

Общая схема проекта выглядит следующим образом:

Общая «цепочка» между Сканер-ВС и DefectDojo.

Мы ожидаем из «Сканер-ВС» отчет в формате HTML, после чего обрабатываем его Python-скриптом и получаем JSON-отчет, готовый для экспорта в DefectDojo. Важно отметить, что после парсинга JSON можно будет анализировать и вручную (если у вас не развернуты решения, аналогичные DefectDojo) — это будет удобнее, чем листать отчет в несколько десятков или сотен страниц. 

Таким образом, наша конечная цель — увидеть данные, полученные из отчета сертифицированного сканера, в формате JSON и отправить его в DefectDojo. Но сперва пара слов об упомянутых решениях, с которыми будем работать.

Об используемых инструментах: Сканер-ВС и DefectDojo

Сканер-ВС

«Сканер-ВС» — сертифицированный ФСТЭК России инструмент для тестирования и анализа защищенности информационных систем, а также контроля эффективности средств защиты информации. Решения такого класса, сертифицированные ФСТЭК, являются обязательными для выполнения требований, например, в рамках аттестаций государственных информационных систем (ГИС).

Актуальной версией «Сканер-ВС» является седьмая, но важно учитывать, что и шестая еще не потеряла своей популярности. С точки зрения отчетов основное отличие в том, что в предыдущей версии это были форматы PDF и HTML, а в текущей — только HTML. При этом структура тегов HTML-отчетов шестой и седьмой версий совпадает, поэтому разработанный скрипт подойдет сразу для обеих.

DefectDojo — что это и зачем

DefectDojo — это открытая платформа для управления уязвимостями (Vulnerability Management Platform). Она агрегирует результаты различных сканеров безопасности в едином интерфейсе, позволяет отслеживать жизненный цикл уязвимостей, приоритезировать их устранение и строить отчетность. Разберем ключевые возможности DefectDojo.

  • Поддержка более 150 встроенных парсеров: Nmap, Burp Suite, Trivy, OpenVAS и других.

  • Дедупликация уязвимостей между сканами.

  • Интеграция с Jira, Slack, GitHub и другими системами.

  • REST API для автоматизации импорта результатов.

  • Ролевая модель доступа.

  • Метрики и дашборды по состоянию безопасности.

Платформа организует данные в иерархию: Product → Engagement → Test → Finding. Это позволяет структурировать уязвимости в разрезе продуктов и этапов разработки.

DefectDojo написан на Python. Это позволяет легко добавить собственные парсеры отчетов, полученных от источников, которые платформа изначально не поддерживает.

Security Center 

Рассказываем о лучших практиках и средствах ИБ, требованиях и изменениях в законодательстве.

Исследовать →

Настройка DefectDojo

Быстрое развертывание с docker-compose

Самый простой способ запустить DefectDojo локально — использовать официальный docker-compose из репозитория проекта.

Клонирование репозитория:

git clone https://github.com/DefectDojo/django-DefectDojo.git
cd django-DefectDojo

Запуск:

docker compose up -d

После запуска DefectDojo будет доступен по адресу http://localhost:8080. Первоначальный пароль администратора выводится в логах:

docker-compose logs initializer | grep 'Admin password:'

Парсинг отчетов Сканера-ВС

Переходим к разбору HTML-отчета — именно его данные будут служить входными для нашего парсера.

Структура HTML-файла отчета

После выполнения сканирования отчет выгружается из «Сканер-ВС» в формате HTML. Логически он состоит из нескольких разделов.

Раздел 1. Резюме

В первом разделе находится общая информация о результатах сканирования: 

  • количество обнаруженных уязвимостей, разделенных по степени критичности; 

  • перечень активов с указанием их IP-адресов, FQDN и ОС (если была выявлена); 

  • топ-5 уязвимых активов;

  • список наиболее уязвимых программных пакетов.

Раздел 2. Данные о просканированных ресурсах

Общая информация. Здесь отображается количество обнаруженных уязвимостей с разделением по степени критичности.

Подбор паролей. Если была запущена задача подбора паролей, здесь будут находиться результаты ее выполнения.

Аудит конфигураций. Если была запущена задача аудита конфигураций, здесь будут находиться результаты ее выполнения.

Найденные уязвимости. В подпунктах этого раздела подробно описаны обнаруженные уязвимости, а именно:

  • в заголовке подпункта — идентификатор CVE;

  • в поле «Связанные идентификаторы» — дополнительные идентификаторы БДУ ФСТЭК и других баз уязвимостей;

  • в поле «Уровень критичности» — текстовая характеристика степени критичности уязвимости;

  • в поле «ПО/Пакет» — наименование уязвимой службы;

  • в поле «Порт» — порт актива, на котором была выявлена уязвимая служба;

  • в полях «CVSSv2», «CVSSv3» и «CVSSv4» — числовой скоринг для обнаруженной уязвимости с указанием векторов атак;

  • в поле «Описание» — дополнительная информация об обнаруженной уязвимости (не всегда заполнено);

  • в поле «Рекомендации» — данные по способу устранения уязвимости, обычно в виде ссылок на сторонние ресурсы (не всегда заполнено).

Если у актива не были выявлены уязвимости, раздел 2 для него будет пустым.

Чтобы увидеть полный «скелет» HTML-отчета, можно очистить все данные. Удалить атрибуты и значения тегов вы можете, например, с помощью кода:

from bs4 import BeautifulSoup

with open('input.html', 'r', encoding='utf-8') as f:
    soup = BeautifulSoup(f, 'html.parser')

# Функция для очистки содержимого тега, сохраняя структуру
def clear_tag_content(tag):
    # Удаляем атрибуты
    tag.attrs = {}
    # Удаляем текстовые узлы (но не дочерние теги)
    for child in tag.contents[:]:  # Копия списка, чтобы безопасно удалять
        if isinstance(child, str):
            child.replace_with('')  # Заменяем текст на пустую строку
        elif child.name:  # Это тег — рекурсивно очищаем его
            clear_tag_content(child)

# Применяем к корневому элементу
clear_tag_content(soup)

# Сохраняем результат
with open('output.html', 'w', encoding='utf-8') as f:
    f.write(str(soup))

Так как нас интересуют данные об уязвимостях, находящихся во втором разделе, оставим только его теги и отметим те, из которых нужно будет забирать информацию:

<html>
<body>
…
<div>
    <h1></h1> <!--ip-адрес объекта сканирования-->
    <h2></h2>
    <table>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    <p></p>
    <div>
        <div></div>
    </div>
    <script></script>
    <style></style>
    <p></p>
    <div><span></span></div><img />
</div>
<div>
    <h2></h2>
    <p></p>
    <div><span></span></div><img />
</div>
<div>
    <h2></h2>
    <p></p>
    <div><span></span></div><img />
</div>
<div>
    <h2></h2> <!--Заголовок "Найденные уязвимости"-->
    <p></p>
    <h3></h3> <!--Идентификатор первой уязвимости в формате CVE-год-номер-->
    <p></p>
    <table>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- Уровень критичности -->
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- ПО/Пакет -->
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- Порт -->
            </tr>
            ...
            <tr>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </table>
    <div><span></span></div>
</div>
<div>
    <h3></h3> <!--Идентификатор следующей уязвимости в формате CVE-год-номер-->
    <p></p>
    <table>
        <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- Уровень критичности -->
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- ПО/Пакет -->
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td> <!-- Порт -->
            </tr>
            ...
            <tr>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td><a></a></td>
            </tr>
            <tr>
                <td><a></a></td>
            </tr>
        </tbody>
    </table>
    <div><span></span></div>
</div>
…
</body>
</html>

Это пример для двух уязвимостей. Все остальные будут выбираться аналогично из тегов второго раздела. Таким образом, мы определили положение нужных тегов в общем файле отчета «Сканер-ВС». Самое время написать код для парсинга этих данных.

Код для парсинга

Для парсинга HTML-отчетов будем использовать BeautifulSoup — это удобный инструмент, который позволяет извлекать данные из XML- и HTML-файлов. Разберемся в логике работы.

Обработка одного отчета

Функция parse_vulnerabilities_html() парсит HTML-файл и извлекает информацию об уязвимостях. Рассмотрим ее основные шаги.

  1. Проверяет, существует ли файл и доступен ли он для чтения.

  2. Находит все заголовки <h1 class="header"> — они соответствуют IP-адресам хостов.

  3. Для каждого хоста извлекает IP-адрес и DNS-имя (если оно присутствует), находит все блоки <div class="pbi_avoid page">, относящиеся к текущему хосту и выбирает блок с разделом «Найденные уязвимости». 

  4. Извлекает идентификаторы CVE из тегов <h3> для каждой уязвимости парсит таблицу и извлекает порт, компонент и уровень критичности.

Результат работы функции — словарь следующего вида:

{ip: {cve: {port: ..., component: ..., severity: ...}}}

Немного об особенностях обработки. Если в блоке отсутствует тег <h3>, он пропускается без ошибки, а если таблица с данными не найдена, выводится предупреждение.

Обработка нескольких отчетов

Функция parse_all_reports() обрабатывает все HTML-файлы в указанном каталоге.

  1. Проверяет существование каталога.

  2. Находит все файлы с расширением .html.

  3. Для каждого файла вызывает parse_vulnerabilities_html() и объединяет результат в общий словарь.

На выходе получаем агрегированные данные по всем хостам из всех отчетов:

all_data = {ip: {...}}

Преобразование структуры данных

Функция restructure_data() позволяет переупорядочить данные по выбранному полю:

  • IP-адресу,

  • CVE,

  • порту,

  • уровню критичности,

  • компоненту.

Это позволяет анализировать результаты с разных точек зрения.

Отправка JSON в DefectDojo

Функция dd_sender() отправляет сформированный JSON-файл в DefectDojo через API.

  1. Проверяет существование файла.

  2. Отправляет POST-запрос на указанный URL.

  3. Использует формат multipart/form-data, передавая file — JSON-файл и параметры сканирования (scan_typeengagementscan_date).

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

  • проверка SSL-сертификата отключена (verify=False);

  • в консоль выводится статус ответа сервера.

Параметр scan_type должен соответствовать зарегистрированному типу в DefectDojo. В нашем случае используется значение ScannerVS.

Общая последовательность действий выглядит следующим образом:

Общая последовательность действий при отправке JSON в DefectDojo.

Результат работы скрипта

Скрипт формирует словарь с возможностью сортировки по различным полям. Рассмотрим на конкретных примерах.

По IP-адресам:

{ip: {cve: {port, component, severity}}}

По CVE:

{cve: {ip: {port, component, severity}}}

По портам:

{port: {ip: {cve, component, severity}}}

По уровню критичности:

{severity: {ip: {cve, port, component}}}

По компонентам:

{component: {ip: {cve, port, severity}}}

Такая агрегация упрощает анализ и помогает быстрее определить приоритеты устранения уязвимостей. Например, группировка по компонентам показывает, какие пакеты требуют обновления в первую очередь, а группировка по портам позволяет выявить сервисы, требующие дополнительного контроля или ограничения доступа.

→ Исходный код можно найти в репозитории.

Экспорт отчета в Defectdojo

Сгенерируем отчет и с помощью скрипта отправим его DefectDojo, выполнив следующую команду:

python3 report_parser.py --dd_sender --dd_api_key <api_token>

После успешного импорта логов в DefectDojo сервер вернет Status: 201:

[SUCCESS] Scan imported successfully. Status: 201

А также краткую сводку по отправленным событиям:

{
'scan_date': '2026-04-08', 'minimum_severity': 'Info', 'active': True, 'verified': False, 'endpoint_to_add': None, 'auto_create_context': False, 'deduplication_on_engagement': False, 'lead': None, 'push_to_jira': False, 'api_scan_configuration': None, 'create_finding_groups_for_all_findings': True, 'test_id': 691, 'engagement_id': 1, 'product_id': 1, 'product_type_id': 5, 'statistics': {'after': {'info': {'active': 0, 'verified': 0, 'duplicate': 0, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 0}, 'low': {'active': 0, 'verified': 0, 'duplicate': 0, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 0}, 'medium': {'active': 0, 'verified': 0, 'duplicate': 0, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 0}, 'high': {'active': 106, 'verified': 0, 'duplicate': 5, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 111}, 'critical': {'active': 81, 'verified': 0, 'duplicate': 4, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 85}, 'total': {'active': 186, 'verified': 0, 'duplicate': 10, 'false_p': 0, 'out_of_scope': 0, 'is_mitigated': 0, 'risk_accepted': 0, 'total': 196}}}, 'apply_tags_to_findings': False, 'apply_tags_to_endpoints': False, 'scan_type': 'ScannerVS', 'engagement': 1, 'close_old_findings': False, 'close_old_findings_product_scope': False, 'test': 691
}

В веб-интерфейсе самого DefectDojo получим разложенные по полям значения. При этом для идентификаторов CVE будут добавлены ссылки на дополнительную информацию с описанием и рекомендациями по устранению: 

Скриншот веб-интерфейса DefectDojo.

Создание кастомного парсера для «Сканер-ВС»

На практике JSON-отчета и импорта через API часто хватает для базовой интеграции. Но у такого подхода есть ограничения: схема данных фиксированная, а сам импорт сложно подстроить под свои процессы. Если нужно больше контроля, то рано или поздно вы придете к идее написания собственного парсера для DefectDojo. Тогда вы сможете самостоятельно управлять логикой импорта: настроить дедупликацию, нормально сопоставить severity, добавить нужные поля в findings и учесть особенности отчетов конкретного сканера.

Это же упрощает дальнейшую автоматизацию. Например, можно в одном месте обрабатывать отчеты разных версий «Сканер-ВС» или добавлять свои правила нормализации без отдельных конвертеров. 

Как DefectDojo обнаруживает парсеры

При старте приложения DefectDojo автоматически сканирует директорию /app/dojo/tools/ и регистрирует все найденные парсеры. Механизм работает следующим образом:

  • для каждой поддиректории проверяется наличие модуля parser.py;

  • из модуля импортируется класс, имя которого соответствует шаблону: имя_папки (без подчеркиваний) + parser;

  • вызывается метод get_scan_types() для регистрации типов сканирования.

Пример: папка scanner_vs → класс должен называться ScannerVsParser(регистронезависимо).

Структура парсера

Минимальная структура файлов выглядит следующим образом:

dojo/tools/scanner_vs/
├── __init__.py    # пустой файл
└── parser.py      # код парсера

При этом каждый парсер должен реализовать четыре метода.

Метод

Назначение

get_scan_types()

Возвращает список имен типов сканирования

get_label_for_scan_types(scan_type)

Возвращает отображаемое имя в UI

get_description_for_scan_types(scan_type)

Описание парсера

get_findings(file, test)

Основной метод — парсит файл и возвращает список Finding

Пример: парсер ScannerVS

Формат входного файла

Парсер обрабатывает JSON-отчет следующей структуры: ключи верхнего уровня — IP-адреса хостов, вложенные ключи — идентификаторы CVE с деталями уязвимости. 

Пример отчета «Сканер-ВС»:

{
  "10.10.21.1": {
    "CVE-2023-38408": {
      "port": "2222",
      "component": "ssh",
      "severity": "критический"
    },
    "CVE-2023-48795": {
      "port": "2222",
      "component": "ssh",
      "severity": "средний"
    }
  }
}

Код парсера

Полный код парсера с дедупликацией и маппингом severity:

import hashlib
import json


from django.conf import settings


from dojo.models import Endpoint, Finding
from dojo.tools.locations import LocationData


SEVERITY_MAP = {
    "критический": "Critical",
    "высокий":     "High",
    "средний":     "Medium",
    "низкий":      "Low",
    "информационный": "Info",
}




class ScannerVsParser:
    def get_scan_types(self):
        return ["ScannerVS"]


    def get_label_for_scan_types(self, scan_type):
        return "ScannerVS"


    def get_description_for_scan_types(self, scan_type):
        return "Parser for ScannerVS JSON format"


    def get_findings(self, file, test):
        data = json.load(file)
        findings = []
        seen = set()


        for ip, cves in data.items():
            for cve_id, details in cves.items():
                port = details.get("port", "")
                component = details.get("component", "")
                severity_ru = details.get("severity", "средний").strip()
                severity = SEVERITY_MAP.get(severity_ru, "Medium")


                # Дедупликация: CVE + IP + порт
                dedup_key = f"{cve_id}|{ip}|{port}"
                if dedup_key in seen:
                    continue
                seen.add(dedup_key)


                # hash_code для дедупликации между сканами
                hash_code = hashlib.sha256(
                    dedup_key.encode()
                ).hexdigest()


                finding = Finding(
                    title=f"{cve_id} on {ip}:{port} ({component})",
                    test=test,
                    severity=severity,
                    description=(
                        f"CVE: {cve_id}\n"
                        f"Host: {ip}\n"
                        f"Port: {port}\n"
                        f"Component: {component}"
                    ),
                    cve=cve_id,
                    component_name=component,
                    unique_id_from_tool=dedup_key,
                    hash_code=hash_code,
                )


                port_int = int(port) if port.isdigit() else None


                # Поддержка V3_FEATURE_LOCATIONS (DefectDojo >= 2.56.1)
                if settings.V3_FEATURE_LOCATIONS:
                    finding.unsaved_locations = [
                        LocationData.url(host=ip, port=port_int)
                    ]
                else:
                    finding.unsaved_endpoints = [
                        Endpoint(host=ip, port=port_int)
                    ]


                findings.append(finding)


        return findings

На что обращать внимание при разработке

Наименование класса

Здесь встречается самая частая ошибка. Имя класса должно точно соответствовать следующей формуле:

# Формула:
# имя_папки.replace('_', '') + 'parser'  (регистронезависимо)


# Папка: scanner_vs
# Ожидаемое имя: scannervsparser
# Правильное имя класса: ScannerVsParser  ✅
# Неправильно: ScannerVSParser            ❌ (VS — верхний регистр)

unsaved_endpoints vs unsaved_locations

В DefectDojo 2.56.1 появился новый механизм хранения адресов — Locations. Необходимо проверять флаг V3_FEATURE_LOCATIONS и использовать соответствующий подход:

if settings.V3_FEATURE_LOCATIONS:
    finding.unsaved_locations = [LocationData.url(host=ip, port=port)]
else:
    finding.unsaved_endpoints = [Endpoint(host=ip, port=port)]

Если передать unsaved_endpoints как аргумент конструктора Finding() — будет ошибка обнаружения эндпоинтов. Присваивать нужно после создания объекта.

Дедупликация

DefectDojo использует два поля для дедупликации:

  • unique_id_from_tool — уникальный ID внутри одного скана, предотвращает дубли при повторном импорте;

  • hash_code — SHA256-хеш ключевых полей, используется для дедупликации между разными сканами.

Рекомендуемый ключ для CVE-сканеров — CVE_ID|IP|PORT.

Маппинг severity

DefectDojo принимает строго определенные значения severity: Critical, High, Medium, Low, Info. При использовании русскоязычных отчетов необходим явный маппинг с .strip() для защиты от лишних пробелов.

30+ бесплатных курсов на IT-темы в Академии Selectel

Для начинающих и опытных специалистов.

Изучить →

Сборка и деплой кастомного образа

Dockerfile:

FROM defectdojo/defectdojo-django:2.56.1


# Копируем парсер в контейнер
COPY scanner_vs/ /app/dojo/tools/scanner_vs/

Сборка и публикация:

# Сборка образа
docker build -t defectdojo-custom:2.56.1 .


# Тег для вашего registry
docker tag defectdojo-custom:2.56.1 \
  your-registry/defectdojo-django:2.56.1-scannervs


# Публикация
docker push your-registry/defectdojo-django:2.56.1-scannervs

Обновление Helm values (если используется Kubernetes):

images:
  django:
    image:
      registry: your-registry
      repository: defectdojo/defectdojo-django
      tag: 2.56.1-scannervs  # <-- обновить тег
helm upgrade defectdojo ./defectdojo \
  -f values.yaml -n defectdojo

Проверка регистрации парсера:

# Проверить что файлы скопированы
docker run --rm --entrypoint bash defectdojo-custom:2.56.1 \
  -c "ls /app/dojo/tools/scanner_vs/"


# Проверить логи после деплоя
docker compose logs | grep -i 'scanner_vs\|failed to load'


kubectl logs -n defectdojo deployment/defectdojo-django -c uwsgi \
  | grep -i 'scanner_vs\|failed to load'

Как дебажить парсер

1. Проверка имени класса. Если парсер не появляется в списке типов сканирования, первым делом проверьте имя класса. Запустите скрипт проверки:

docker run --rm --entrypoint bash defectdojo-custom:2.56.1 -c \
  "python3 -c \"
import re, importlib
module = importlib.import_module('dojo.tools.scanner_vs.parser')
expected = 'scanner_vs'.replace('_','') + 'parser'
classes = [x for x in dir(module) if x.lower() == expected]
print('Found:', classes)
\""

2. Логи при загрузке. DefectDojo логирует ошибки при загрузке парсеров. Смотрите логи сразу после старта:

docker compose logs -n 200 | grep -E 'failed|error|scanner_vs'


kubectl logs -n defectdojo deployment/defectdojo-django \
  -c uwsgi --since=2m | grep -E 'failed|error|scanner_vs'

3. Тест парсера без деплоя. Можно протестировать парсер локально внутри контейнера без деплоя в кластер:

docker run --rm --entrypoint bash defectdojo-custom:2.56.1 -c \
  "cd /app && python3 -c \"
from dojo.tools.scanner_vs.parser import ScannerVsParser
import json, io
data = json.dumps({'10.0.0.1': {'CVE-2023-38408': {
  'port': '22', 'component': 'ssh', 'severity': 'критический'
}}})
p = ScannerVsParser()
print('Scan types:', p.get_scan_types())
\""

Ниже — самые частые ошибки и их решения в формате шпаргалки. 

Ошибка

Решение

Парсер не появляется в UI

Проверить имя класса по формуле: папка.replace(‘_’,”) + ‘parser’

unexpected keyword argument ‘unsaved_endpoints’

Присваивать после создания объекта, не в конструктор

Все finding с severity Medium

Добавить .strip() при чтении поля, проверить маппинг

Дубли при повторном импорте

Заполнить unique_id_from_tool и hash_code

Parser does not exist

Проверить что файлы скопированы в образ и образ пересобран

Импорт результатов сканирования

Через веб-интерфейс

Разберем пошаговый процесс импорта через UI. 

  1. Откройте DefectDojo и перейдите в Products.

  2. Создайте или выберите продукт → Engagements → Add New CI/CD Engagement.

  3. Внутри Engagement нажмите Import Scan Results.

  4. В поле Scan Type выберите ScannerVS.

  5. Загрузите JSON-файл и нажмите Import.

Через API

Для автоматизации используйте REST API DefectDojo:

# Получить токен
curl -X POST https://defectdojo.example.com/api/v2/api-token-auth/ \
  -d '{"username": "admin", "password": "password"}'


# Импортировать скан
curl -X POST https://defectdojo.example.com/api/v2/import-scan/ \
  -H 'Authorization: Token YOUR_TOKEN' \
  -F 'scan_type=ScannerVS' \
  -F 'file=@report.json' \
  -F 'engagement=1' \
  -F 'minimum_severity=Low'

При повторном импорте того же файла DefectDojo обновит существующие findings, а не создаст дубли — благодаря unique_id_from_tool и hash_code.

Результаты сканирования

В итоге получается единый пайплайн обработки отчетов: HTML-отчет «Сканер-ВС» разбирается в JSON, после чего данные автоматически отправляются в DefectDojo и становятся пригодны для дальнейшего анализа и агрегации. За счет этого результаты сканирования проще встроить в общий процесс управления уязвимостями без привязки к формату исходного отчета и без сторонних коммерческих конвертеров.

Плюс появляется удобный способ централизованно обогащать данные об активах информацией об обнаруженных уязвимостях. Для команд ИБ это означает более удобную интеграцию сканирования в DevSecOps и другие процессы, а также единый подход к обработке результатов для разных инфраструктур и команд.

Скриншот результатов сканирования.
Скриншот результатов сканирования.
Скриншот результатов сканирования.

Снижаем цены на выделенные серверы в реальном времени

Успейте арендовать со скидкой до 35%, пока лот не ушел другому.

Подробнее →

Комментарии (0)