Dozor -- блоклисты из базы уязвимостей
NORA не держит базу уязвимостей. Это осознанное архитектурное решение (ADR-2): выгрузки OSV по экосистемам, которые NORA проксирует, весят около 360 МБ в сжатом виде и обновляются ежедневно, а сопоставление версий с ними требует индекса — то есть встроенной базы данных внутри процесса, который стартует за три секунды и в покое занимает меньше 50 МБ.
Dozor — это компаньон, который
закрывает пробел снаружи. Он собирает фид OSV вместе с описью того, что реально
лежит в вашем реестре, в blocklist.json того формата, который NORA уже умеет
читать. Никаких изменений в NORA, никаких плагинов, никакой сети между ними —
файл и есть весь интерфейс.
снапшот osv.dev ─┐опись реестра ─┼─► dozor build ─► blocklist.json ─► git PR ─► NORApolicy.toml ─┘Dozor — компилятор, а не сервис. У него нет демона, и он никогда не стоит на пути скачивания, поэтому не может уронить загрузку или задержать сборку.
Почему это важнее, чем CVE
Заголовок раздела «Почему это важнее, чем CVE»Фид OSV по npm содержит 228 684 записи, и 96,8% из них — это MAL-*,
сообщения о вредоносных пакетах, а не CVE: тайпсквоттинг, угнанные
мейнтейнеры, отравленные релизы. У них вообще нет поля severity, поэтому
политика, выраженная только порогом серьёзности, отбросила бы почти всё.
Сканер в CI видит вредоносный пакет только после того, как реестр уже закэшировал его и раздал команде. Реестр — единственное место, где отказ является предотвращением, а не обнаружением.
Установка
Заголовок раздела «Установка»Скачайте бинарь со страницы релизов или соберите из исходников:
git clone https://github.com/getnora-io/dozorcd dozor && cargo build --releaseИспользование
Заголовок раздела «Использование»# 1. снимок фида (или принесите zip внутрь, если контур изолирован)curl -o npm.zip https://osv-vulnerabilities.storage.googleapis.com/npm/all.zip
# 2. опись того, что лежит в NORAdozor inventory --nora-data /var/lib/nora -o inventory.jsonl
# 3. сборка блоклистаdozor build \ --feed-npm npm.zip \ --inventory inventory.jsonl \ --policy policy.toml \ --proactive \ -o blocklist.json
# 4. отдать NORA -- это вся конфигурация, которая нужнаexport NORA_CURATION_MODE=enforceexport NORA_CURATION_BLOCKLIST_PATH=/etc/nora/blocklist.jsonФлаг --proactive блокирует ещё и все целиком вредоносные пакеты из фида
независимо от того, кэшировали вы их когда-нибудь или нет: пакет отказывается до
первой загрузки.
Политика
Заголовок раздела «Политика»version = 1
[defaults]severity_threshold = "high" # critical | high | moderate | low | offmalicious = "block" # у MAL-* нет severity -- отдельный переключатель
[[exception]]registry = "npm"name = "lodash"version = "4.17.20"reason = "закреплено легаси-сборкой, отслеживается в JIRA-42"expires = "2026-12-31" # обязательно -- просроченное исключение валит сборкуЧто видит разработчик
Заголовок раздела «Что видит разработчик»Строка reason, которую пишет Dozor, проходит через NORA нетронутой и попадает
в тело ответа 403:
{ "error": "blocked_by_policy", "context": { "package": "lisa-bubursumsum21-miaww", "version": "0.0.1-security.1", "rule": "blocklist", "reason": "MALICIOUS package (MAL-2025-115501) — blocked by dozor · https://osv.dev/vulnerability/MAL-2025-115501" }}На выходе артефакт, а не мнение контроллера:
- Детерминированность — одинаковые входы дают побайтово одинаковый выход, поэтому ежедневная задача открывает pull request только тогда, когда что-то действительно изменилось.
- Проверяемость — каждый выход несёт блок
x-dozor-derivationс дайджестами снапшота фида, описи, политики и самого тела.dozor verifyвыводит их заново, так что через месяцы можно доказать, почему сборка была заблокирована. - Ревьюируемость — блоклист лежит в git, и
git log -S <пакет>отвечает на вопрос “когда мы начали это блокировать и кто одобрил”.
Ни оператора, ни CRD, ни петли согласования: задача, которая пишет файл.
Изолированные контуры
Заголовок раздела «Изолированные контуры»dozor build вообще не ходит в сеть. Занесите zip с фидом тем же способом,
которым переносите артефакты, а опись снимается с холодной копии каталога данных
NORA. Больше ничего не нужно.
Dozor 0.1 покрывает npm. Все остальные экосистемы получают ответ Unknown,
и Unknown никогда не превращается в “безопасно”: такие версии считаются и
попадают в x-dozor-unmatched на выходе, а не проходят молча.
Следующий на очереди PyPI (PEP 440), затем семантика версий Maven, Go и RPM/deb.