Skip to content

Скан и мониторинг

Сканирование — основной цикл CVE Intelligence Panel. В этой главе сравниваются полное сканирование и мониторинг, описывается поведение сервера и приведены диаграммы для операторов.

Зачем два режима

NVD даёт широкое покрытие, но применяет rate limits. Опрос NVD каждые две минуты приведёт к зависанию или ошибкам. Поэтому мониторинг пропускает NVD и опрашивает более быстрые источники. Полное сканирование нужно для полного инвентаря, когда задержка приемлема.

Обычно операторы запускают полное сканирование раз в день (или по запросу) и держат мониторинг включённым между сканами.

Сравнение режимов

Аспект Полное сканирование Мониторинг
Endpoint POST /api/scan POST /api/watch
NVD Да Нет
Prefetch KEV Да Да (для флагов)
Клиентский knownIds Не обязателен Дедуплицирует «новые» находки
meta.mode full watch

Поток полного сканирования

flowchart LR
  classDef ui fill:#e9edf5,stroke:#00baba,color:#253343
  classDef api fill:#f3fcfc,stroke:#008c8c,color:#253343
  classDef ext fill:#fff7ed,stroke:#eda232,color:#253343

  UI[Браузер]:::ui --> S[POST /api/scan]:::api
  S --> KEV[Загрузка KEV]:::api
  S --> GH[Кэш GitHub]:::api
  S --> RSS[RSS-ленты]:::api
  S --> Loop[По каждому инструменту]:::api
  Loop --> NVD[Запрос NVD]:::ext
  Loop --> OSV[Запрос OSV]:::ext
  Loop --> GHA[GitHub advisories]:::ext
  S --> M[merge + обогащение KEV]:::api
  M --> T[Опциональный перевод]:::api
  T --> R[JSON-ответ]:::api

Разбор диаграммы

Сервер один раз загружает общие каталоги, затем для каждого инструмента параллельно запрашивает NVD (полный режим), OSV и GitHub и прикрепляет совпадения по ключевым словам из RSS. Результаты объединяются по id CVE; членство в KEV выставляет exploited_in_wild. Опциональный перевод заполняет translations / title_fa. meta.sources_updated_at фиксирует успешное время загрузки по каждому источнику.

Пошагово (полное сканирование)

  1. Пользователь нажимает Полное сканирование; клиент отправляет stack и флаг translate.
  2. Сервер проверяет массив стека и запускает таймеры.
  3. JSON CISA KEV, страницы GitHub advisory (кэш) и RSS-ленты загружаются параллельно.
  4. Для каждого инструмента NVD/OSV/GitHub выполняются с look-back SCAN_DAYS.
  5. mergeVulnerabilities дедуплицирует и объединяет теги sources.
  6. enrichWithKev помечает эксплуатируемые CVE.
  7. При translate: true на скане могут заполняться поля для персидского; другие локали запрашиваются позже через /api/translate.
  8. Возвращаются сводные счётчики и массив vuln; клиент сохраняет через src/lib/scanCache.ts (stackKey должен совпадать с текущим стеком).

Клиентский кэш scan

Браузер хранит последний успешный scan в cve-radar:last-scan с ключом стека (нормализованные, отсортированные имена инструментов). При перезагрузке loadLastScan восстанавливает vuln и summary при совпадении ключа; иначе кэш игнорируется. persistLastScan выполняется после полного scan и когда watch возвращает новые элементы.

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

Последовательность мониторинга

sequenceDiagram
  participant B as Браузер
  participant A as Express API
  participant O as OSV
  participant G as GitHub
  participant R as RSS

  B->>A: POST /api/watch {stack, knownIds}
  A->>O: Запрос по инструменту
  A->>G: Кэш advisory
  A->>R: Разбор ленты
  A->>A: Merge + diff vs knownIds
  A-->>B: newVulns, hasNew, meta

Пошагово (мониторинг)

  1. Хук useWatch срабатывает по интервалу (2/5/15 мин из настроек).
  2. Клиент отправляет текущие id CVE как knownIds.
  3. Сервер загружает только OSV/GitHub/RSS.
  4. Новые id, отсутствующие в knownIds, попадают в newVulns; баннер/toast при включённых оповещениях.
  5. Клиент объединяет с локальным списком vuln и обновляет sources_updated_at.

GitLab и фиды дистрибутивов Linux

Помимо NVD/OSV/GitHub/RSS, полное сканирование может запрашивать GitLab Advisory Database (GraphQL) и несколько фидов безопасности дистрибутивов Linux, если они включены в настройках источников или через переменные env.

Источник Роль
GitLab Package advisories (npm, PyPI, Maven, Go, …) — пропускается при AIRGAPPED=true без GITLAB_ADVISORY_MIRROR_URL
Alpine secdb JSON по релизам (ALPINE_RELEASES)
Ubuntu USN Предзагруженная карта CVE→пакет из JSON Ubuntu Security
Red Hat Обогащение (метаданные CVE, не отдельные строки)
Debian Security Tracker (DEBIAN_ENABLED или DEBIAN_TRACKER_CACHE_PATH для air-gap)
Amazon Linux ALAS updateinfo XML
MITRE CVE Опциональное обогащение JSON 5.x при MITRE_CVE_ENABLED=true

Сопоставление на уровне пакетов — shared/distroPackages.ts (инструмент стека → имя пакета дистрибутива). Результаты дистрибутивов дедуплицируются с NVD/OSV по id CVE; sources_failed фиксирует частичные ошибки фидов как у других встроенных источников.

Замечания и исключения

  • Rate limit сервера (429): POST /scan и POST /watch используют отдельные in-memory bucket на IP (RATE_LIMIT_SCAN_PER_MIN по умолчанию 12, RATE_LIMIT_WATCH_PER_MIN по умолчанию 120). Ответ: code: "RATE_LIMITED", retryAfterSec. POST /scan/validate не ограничивается. Несколько вкладок или React StrictMode в dev могут вызвать лимит watch — закройте лишние вкладки или настройте env.
  • Без NVD_API_KEY большие стеки могут получить HTTP 403/429 от NVD upstream — повторите позже или добавьте ключ (отличается от rate limit приложения).
  • Периодическое авто полное сканирование (30 мин) опционально в настройках; независимо от интервала мониторинга.
  • Полоса прогресса сканирования в шапке отражает клиентскую оценку прогресса во время длинных сканов.

Далее: i18n и перевод