Скан и мониторинг¶
Сканирование — основной цикл 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 фиксирует успешное время загрузки по каждому источнику.
Пошагово (полное сканирование)¶
- Пользователь нажимает Полное сканирование; клиент отправляет
stackи флагtranslate. - Сервер проверяет массив стека и запускает таймеры.
- JSON CISA KEV, страницы GitHub advisory (кэш) и RSS-ленты загружаются параллельно.
- Для каждого инструмента NVD/OSV/GitHub выполняются с look-back
SCAN_DAYS. mergeVulnerabilitiesдедуплицирует и объединяет тегиsources.enrichWithKevпомечает эксплуатируемые CVE.- При
translate: trueна скане могут заполняться поля для персидского; другие локали запрашиваются позже через/api/translate. - Возвращаются сводные счётчики и массив 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
Пошагово (мониторинг)¶
- Хук
useWatchсрабатывает по интервалу (2/5/15 мин из настроек). - Клиент отправляет текущие id CVE как
knownIds. - Сервер загружает только OSV/GitHub/RSS.
- Новые id, отсутствующие в
knownIds, попадают вnewVulns; баннер/toast при включённых оповещениях. - Клиент объединяет с локальным списком 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 и перевод