
Аудитор зависимостей без сборки, который сканирует 10 экосистем офлайн, сообщая о CVE с приоритетом по CISA KEV и EPSS, пакетах с истёкшим сроком поддержки, лицензиях, закоммиченных ключах и бинарных файлах с экспортом в SBOM и SARIF.
Formidable Auditor's Dependency Checker
AKA Fuckin' Autonomous Dependency Checker
fad-checker проверяет Maven · Gradle · npm · Yarn · pnpm · Composer · PyPI · NuGet · Go · Ruby, вендоризованный JavaScript, закоммиченные нативные бинарники и криптографический материал (сертификаты и приватные/публичные ключи) в любом дереве исходников; мультимодульные, монорепозитории, полиглотные; и создаёт самодостаточный HTML + Word отчёт (CVE с приоритетом по EPSS + CISA KEV, EOL, устаревшие, неактуальные, лицензии) плюс экспорт . ; он читает lock-файлы и манифесты прямо с диска.

mvn/gradle/npm install/pip/dotnet restore/go build, никакого node_modules/. Граф Maven разрешается так же, как его разрешает Maven. → как--offline, регрессионно протестировано и воспроизводимо под unshare -rn. На Maven он восстанавливает 657/657 онлайн-результата OSV-Scanner вообще без сетевого интерфейса, против 45 / 40 / 37 у остальных. → Бенчмарк · Air-gapped--typosquat).SHA256SUMS; дифференциальные аудиты сравнивают с предыдущим запуском (--baseline), и CI может гейтить только по новым находкам.--help, помещающийся на экран; длинный хвост переключателей сворачивается в четыре флага — -d eol,nvd выключает, -a licenses,snyk включает то, что по умолчанию выключено, -r html,json выбирает выходные форматы, -o указывает куда. Отдельные флаги по-прежнему работают, а --help-all их перечисляет.--lang fr).doc при --report-doc), CycloneDX 1.6 SBOM, CSAF 2.0 VEX, SARIF 2.1.0, JSON; гейт через --fail-on, триаж через --ignore/--vex. Приватные реестры для каждой экосистемы.Что он делает для аудита, чего не делают другие. Тот же набор столбцов и та же дисциплина источников, что и в
docs/COMPARISON.md — ⚠️ означает частично и поясняет как, ячейки предполагаются
проверяемыми.
| Что аудитору на самом деле нужно сделать | fad | OSV | Trivy | Grype+Syft | OWASP DC | Snyk |
|---|---|---|---|---|---|---|
| Провести аудит полиглотного монорепозитория из 100 модулей одной командой, без установленного тулчейна ¹ | ✅ 105 модулей | ⚠️ reactor пропущен | ⚠️ нужен ~/.m2 | ⚠️ opt-in | ⚠️ Java build | ⚠️ mvn build |
| Сканировать офлайн / air-gapped без потери транзитивных зависимостей ² | ✅ 657/657 | ❌ | ⚠️ ~/.m2 | ⚠️ opt-in | ⚠️ mirror | ❌ |
| Идентифицировать приватные/внутренние зависимости в большом проекте ³ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Извлечь очищенные дескрипторы зависимостей во внешний каталог ⁴ | ✅ -t | ❌ | ❌ | ❌ | ❌ | ❌ |
| Сообщить об EOL / устаревших фреймворках и зависимостях, включая транзитивные ⁵ | ✅ | ⚠️ только deprecated | ⚠️ только OS-дистрибутивы | ❌ | ❌ | ⚠️ только web UI |
| Сообщить о закоммиченных ключах и сертификатах ⁶ | ✅ | ❌ | ⚠️ правило для ключей | ❌ | ❌ | ❌ |
Обнаружить закоммиченные бинарники (.dll, .exe, …) и проверить их по контрольным суммам ⁷ | ✅ | ❌ | ⚠️ некоторые | ⚠️ паттерны | ❌ | ❌ |
| Чётко перечислить, что было просканировано — до того, как клиент спросит ⁸ |
¹ Никаких mvn/go/npm/pip/dotnet — манифесты разбираются с диска, ничего не устанавливается и не выполняется. 105 × pom.xml за один проход: 790 пар против 657 у OSV-Scanner, 133 только у fad, версии опосредуются по модулю, а не выравниваются.
² 657 из 657 онлайн-результата Maven у OSV-Scanner, под unshare -rn — без сетевого интерфейса. Проверено tripwire; за пределы изолированной среды выходят только публичные координаты.
³ Глава 0 называет каждую координату, на которую каждый настроенный реестр ответил 404 — Maven, npm, PyPI, NuGet, Composer, Go и RubyGems — с указанием манифеста(ов), где она объявлена. Реестр, который отвалился по таймауту или ошибке, никогда не учитывается: неокончательный ответ иначе обвинил бы клиента в поставке внутренних пакетов из-за нестабильного прокси. Затем -e <regex> исключает их.
⁴ -t <dir>: нормализованные POM плюс зеркалирование каждого не-Maven lock-файла, приватные координаты вырезаны. Архивируемо и сканируемо чем угодно — включая --snyk.
⁵ endoflife.date, с разделением прямые vs транзитивные, чтобы вы знали, какую зависимость обновлять, плюс deprecated / заброшенные / yanked и неактуальные. Trivy покрывает только OS-дистрибутивы; здоровье пакетов у Snyk только в вебе.
⁶ Инвентаризация и вердикты: истечение, RSA<2048, MD5/SHA1, самоподписанные; приватные vs публичные ключи; JKS/PKCS#12. Офлайн-парсер. Правило секретов Trivy находит файл, а не изъян.
⁷ Идентификация по хэшу через deps.dev + CIRCL → должно-быть-объявлено / имя≠контрольная-сумма / неизвестно / вредоносно. Паттерны Syft называют версию, а не идентичность.
⁸ Глава 0 отмечает то, до чего это сканирование не смогло добраться (отсутствующие lock-файлы, версии только из BOM, Yarn Berry, неопределяемая среда выполнения PHP); глава 6.3 указывает, что инструмент никогда не оценивает. В других местах первое — это строка лога, которую аудит никогда не увидит, а второе вообще не записано.
⁹ Манифест происхождения: инструмент, среда выполнения, режим, конфигурация запуска и свежесть кэша для всех 13 источников. Grype и Dependency-Check несут дату одного источника, а не запуска.
¹⁰ Главы 0→6 с резюме для руководства и рецептами исправлений, самодостаточный HTML плюс Word .doc-двойник. Ни один из остальных не выдаёт Word.
¹¹ Четыре встроенных SVG-графика — CWE по худшей серьёзности, уязвимые транзитивные зависимости на корневую зависимость, ваши самые уязвимые модули (прямые vs транзитивные в одмодульном проекте), полосы приоритета исправлений — отрисовываются и в .doc, с копированием в один клик как PNG (или таблицы как rich HTML), что вставляется в Word с форматированием. Каждый CVE сохраняет свой CVSS-вектор, CWE, ссылки, CPE-конфигурацию и via-path за детализацией, без внешних ресурсов.
¹² --baseline добавляет главу Δ (новые / исправленные / без изменений); --fail-on-new гейтит только по новым находкам. Snyk отслеживает это на своей платформе, а не как локальный diff.
Где он проигрывает — контейнеры/OS-пакеты, авто-PR с исправлениями и покрытие CVE против курируемого
фида Snyk → docs/COMPARISON.md ·
разрыв, измеренный.
Намеренно не является целью: достижимость. Находка — это уязвимая версия в графе зависимостей, и отчёт говорит именно это (гл. 6.3), вместо угадывания путей вызовов. Решение о том, достижим ли уязвимый код в этом приложении, — за аудитором, принимается с контекстом приложения, которого нет ни у одного сканера.
[!WARNING] fad-checker новый и может всё ещё содержать (редкие) баги. Относитесь к его выводу как к сильному первому проходу, перепроверяйте всё критичное и, пожалуйста, сообщайте о проблемах; их быстро исправляют.
npm install -g fad-checker fad-checker -s ./my-project # → ./fad-checker-report/cve-report.html
Бесплатный [ключ API NVD](https://nvd.nist.gov/developers/request-an-api-key) (мгновенно) даёт в 10 раз более быстрое обогащение: `fad-checker --set-nvd-key YOUR_KEY`. Несколько распространённых запусков; полный список через `fad-checker --help` или [docs/USAGE.md](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md):```bash
fad-checker -s ./proj -e "^com\.acme\." # exclude private libs (coord regex)
fad-checker -s ./proj -t ../clean -e "^com\.acme\." # extract only: normalised descriptors, private modules flagged
fad-checker -s ./proj -t ../clean -e "^com\.acme\." -a snyk # same extraction + scan + merge Snyk
fad-checker -s ./proj --offline # fully offline (zero network, needs a warmed cache)
fad-checker -s ./proj -a osv-db,typosquat # offline-complete OSV + typosquat
fad-checker -s ./proj -a licenses --fail-on high # license chapter + CI gate
fad-checker -s ./proj --report-json --baseline last.json --fail-on-new # differential audit: fail CI on NEW findings
fad-checker diff last.json this.json # standalone diff of two findings JSONs
Что на самом деле делает -t <dir>. Это шаг извлечения, а не адаптер Snyk. Он записывает
параллельное дерево нормализованных дескрипторов зависимостей: каждый pom.xml сведён к
узлам, относящимся к зависимостям (координаты, properties, dependencyManagement, dependencies,
modules), родители реактора переподключены к их реальному внутридеревному relativePath, ${…} разрешены в
координатах — плюс каждый не-Maven lockfile/манифест зеркалируется по тому же относительному пути
(package-lock/yarn.lock/pnpm-lock, composer.lock, poetry/Pipfile/uv/pdm,
*.csproj/packages.lock.json, go.mod/go.sum, Gemfile.lock, и сопутствующие, такие как
Directory.Packages.props или nuget.config). В онлайн-режиме он также проверяет каждую координату против
настроенных репозиториев Maven и сообщает о тех, которых там нет — ваши
приватные/внутренние модули — которые -e <regex> затем вырезает из перезаписанных POM. Затем он
останавливается: без прохода CVE/EOL и без отчёта, если вы также не передадите --snyk, --report-<type>,
--fail-on* или --baseline. Что вы получаете — это безборочный, очищенный инвентарь зависимостей, который можно
заархивировать как доказательство для аудита, передать клиенту или на юридическую проверку, или направить на него любой сканер — Snyk через
--snyk будучи одним из них.
[!IMPORTANT]
--offlineчитает кэш, а не заменяет его. На холодном кэше не с чем сопоставлять, поэтому офлайн-первый запуск законно сообщает 0 CVE / 0 EOL / 0 outdated; это пустой кэш, а не чистый проект. Прогрейте его один раз (обычный онлайн-запуск на любом проекте, или--import-cache), затем--offlineвозвращает полный набор результатов с нулевыми сетевыми вызовами. Машины в изолированной среде получают свой кэш через--export-cache/--import-cache.
Единый самодостаточный бинарник (без Node), установка из исходников и автодополнение оболочки находятся в → docs/USAGE.md.
Отчёт организован в корневые главы (каждая группирует связанные подглавы):
| Глава | Источник | Что она выявляет |
|---|---|---|
| 0. Предупреждения (сверху) | локальные эвристики | Отсутствующие lockfile, неразрешённые версии Maven (управляемые BOM), приватные библиотеки, отсутствующие на Maven Central |
Δ. Изменения с момента базовой линии (сверху, с --baseline) | diff относительно предыдущего JSON | Новые / исправленные / неизменённые находки по категориям + список новых production CVE; для повторных аудитов и CI-гейтинга --fail-on-new |
| 1. CVE (X прямых, Y косвенных, Z dev) | CVEProject + OSV.dev + NVD + CPE | 1.1 Production; публичные CVE / GHSA в prod-зависимостях, по экосистеме, по манифесту, приоритизированные по CISA KEV + EPSS + CVSS · 1.2 Уязвимости вендорного JS (retire.js) · 1.3 Dev (test/provided, dev/optional/peer) · 1.4 Вероятные ложные срабатывания (отфильтрованные по CPE) |
| 2. Неуправляемые / безверсионные компоненты | deps.dev + CIRCL (по контрольной сумме), retire.js, встроенный X.509 | 2.1 Встроенные бинарники; CVE в библиотеках, поставляемых внутри закоммиченных .jar/.war/.ear (fat-jars, shaded uber-jars) · 2.2 Нативные бинарники (.dll/.exe/.so/.dylib), идентифицированные по хешу, помеченные как should-be-managed / name≠checksum / unknown / malicious · 2.3 Инвентарь вендорного JavaScript (jQuery, Bootstrap, …) уязвимый или нет · 2.4 Сертификаты и ключевой материал; закоммиченные сертификаты (истечение / слабый ключ / слабая подпись / самоподписанные), приватные и публичные ключи (PEM/OpenSSH/PuTTY/PGP/SSH) и хранилища ключей, всё разбирается офлайн |
| 3. Сопровождение / жизненный цикл (X EOL, Y устаревших, Z устаревших версий) | endoflife.date · курируемые + флаги реестров · Maven Central / npm / Packagist / PyPI / NuGet | 3.1 End-of-Life фреймворки (+ полоса "Out of active support" с ; Symfony/Laravel сгруппированы как одна строка на фреймворк; PHP-рантайм, когда ограничение Composer это доказывает), разделённые на (объявленные / унаследованные от родительского POM — обновляйте их) и (обновляйте зависимость, которая их подтягивает) · · (доступна более новая версия, с датами релиза; только прямые зависимости) |
HTML-отчёт открывается в любом браузере, содержит каждую деталь (векторы CVSS, ссылки, полные описания, конфигурации CPE, via-пути для транзитивных) и поставляется с Word-совместимым .doc-двойником. Каждое совпадение несёт композитный приоритет (эксплуатируемое в KEV > вероятность по EPSS > серьёзность по CVSS), и запуск может дополнительно выдавать CycloneDX 1.6 SBOM (--report-sbom, уязвимости встроены) и CSAF 2.0 VEX (--report-csaf) для нижестоящих инструментов.

Ни один инструмент не находит всё. fad-checker лидирует на 87% из объединения в 908 пар, и 131 пара вернулась от Snyk, а не от него. Рассмотренные по одной против OSV, ни одна не является ошибкой полноты:
| Вердикт | |
|---|---|
| 57 | неверный артефакт — advisory привязан к другой координате |
| 31 | вне диапазона — версия находится вне всех объявленных затронутых диапазонов |
| 23 | нет в OSV — 19 проприетарных SNYK-* id, 4, которые есть только в NVD |
| 19 | нет привязки к Maven — advisory вообще не привязан ни к какому Maven-пакету |
| 1 | уже сообщено, под алиасом CVE |
| 0 | подтверждённых пропусков |
Две трети противоречат публичной записи, поэтому их сообщение означало бы поставку ложных
срабатываний. CVE-2023-6481 — чистый пример: заявленный на [email protected], он привязан
к logback-core на [1.2.12, 1.2.13) — неверный артефакт, и версия опубликована до того, как
уязвимость существовала.
Область охвата. Все 131 — от Snyk: OSV-Scanner, Trivy и Grype+Syft каждый внесли 0 находок, которых не было у других. И все они на цели Maven — вне Maven граф находится в lockfile, каждый сканер читает один и тот же вход, и бенчмарк измеряет идентичные наборы находок на npm, RubyGems и Composer.
Вот почему существует --snyk. fad-checker принимает вывод snyk test как вход и объединяет
его, так что вы получаете объединение, а не выбираете сторону. Выбор покрытия, а не исправление.
Метод, оговорки и вердикты по каждой паре → docs/BENCHMARK.md; воспроизвести
с помощью scripts/adjudicate-gap.js.
Гарантия нулевой передачи данных. В режиме
--offlinefad-checker не делает никаких сетевых вызовов; он читает только прогретые кэши~/.fad-checker/и никогда не передаёт зависимость, путь или находку за пределы машины. Это проверяется регрессионными тестами (test/offline-guarantee.test.js, fetcher-ловушка, которая выбрасывает исключение при обращении) и воспроизводимо аудитором:unshare -rn node fad-checker.js -s ./proj --offline …запускает его в пространстве имён без сетевого интерфейса и даёт побайтово идентичные находки. В отличие от мейнстримных OSS-сканеров, fad также разрешает транзитивный граф Maven офлайн; так что на изолированном многомодульном проекте он находит транзитивные CVE, которые они не могут.
Когда проверяемая система офлайн / конфиденциальна (типично для регулируемого или изолированного аудита), она не может достичь OSV / NVD / Maven Central / npm. Разделите работу между машинами, сохраняя нулевую информацию об окружении вне защищённого анклава: анонимизированный дескриптор несёт только публичные координаты пакетов; никаких путей файловой системы, никаких URL реестров, никаких имён хостов/пользователей; и подробный отчёт создаётся обратно на офлайн-машине.
Передача опирается на свойство кэшей fad-checker: они ключуются по координате или id уязвимости, никогда по пути, поэтому они независимы от машины. Онлайн-шаг просто прогревает кэши; офлайн-шаг воспроизводит сканирование и получает попадания в кэш.```bash
fad-checker -s ./proj -e "^(client|internal)." --export-anonymized deps.json
fad-checker --import-anonymized deps.json # scans coordinates → OSV/NVD/CVE/registry/EOL + retire signatures fad-checker --export-cache fad-cache.tar.gz # bundle the warmed ~/.fad-checker/
fad-checker --import-cache fad-cache.tar.gz # merged into the enclave's own cache fad-checker -s ./proj --offline # re-collect locally (real paths) + cache hits
Что содержит дескриптор (`fad-deps/1`) и что отбрасывает:
| Сохраняется (нужно для сканирования) | Отбрасывается (окружение) |
| --- | --- |
| ecosystem, ecosystemType | пути манифестов / пути pom |
| namespace, name | разрешённые URL реестров |
| version, versions | хеши целостности |
| scope, isDev | цепочки родителей, тип lockfile |
Отчёт онлайн-фазы сам по себе не содержит путей; находки по вендоризованному JavaScript (retire.js)
формируются **офлайн в фазе 3**, поскольку retire нужны сами файлы `.js`; его сигнатурная
БД прогревается онлайн (фаза 2) и переносится через `--export-cache`. Полный контроль офлайн/кэша →
[`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md).
## Документация
- [`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md); каждый флаг и рабочий процесс: контроль офлайн/кэша, приватные реестры, конфигурационные файлы, рецепты, предохранительные механизмы.
- [`docs/ARCHITECTURE.md`](https://github.com/9pings/fad-checker/blob/main/docs/ARCHITECTURE.md); внутреннее устройство: кодеки, сбор, сопоставление, конвейер отчётов.
- [`docs/COMPARISON.md`](https://github.com/9pings/fad-checker/blob/main/docs/COMPARISON.md); против OSV-Scanner / Trivy / Grype / OWASP DC / Snyk, и как он остаётся независимым от сборки.
- [`docs/BENCHMARK.md`](https://github.com/9pings/fad-checker/blob/main/docs/BENCHMARK.md) — воспроизводимый бенчмарк полноты в изолированной среде против OSV-Scanner на публичном проекте из 105 модулей.
- [`docs/DATA-SOURCES.md`](https://github.com/9pings/fad-checker/blob/main/docs/DATA-SOURCES.md); публичные наборы данных, используемые fad-checker, и их лицензии.
- [`docs/SPEC-audit-pro.md`](https://github.com/9pings/fad-checker/blob/main/docs/SPEC-audit-pro.md); функции аудиторского уровня (происхождение, дифференциальный аудит, методология/целостность) и почему каждая была реализована именно так.
- [`CHANGELOG.md`](https://github.com/9pings/fad-checker/blob/main/CHANGELOG.md) · [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md); история релизов · ориентирование в коде для контрибьюторов.
## Участие в разработке
Самое полезное, что можно сделать для молодого сканера — **сказать ему, где он ошибается**: запустите его на
реальном проекте и отправьте [отчёт о ложноположительном / ложноотрицательном срабатывании](https://github.com/9pings/fad-checker/issues/new?template=false_positive.yml)
с координатой и фрагментом манифеста, который его вызвал. Настройка окружения для разработки, основные правила и
точка расширения кодеков → [`CONTRIBUTING.md`](https://github.com/9pings/fad-checker/blob/main/CONTRIBUTING.md). Уязвимости в самом fad-checker
→ [`SECURITY.md`](https://github.com/9pings/fad-checker/blob/main/SECURITY.md) (пожалуйста, сообщайте приватно).
**Об использовании ИИ:** эта кодовая база написана с активным использованием Claude Code; [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md)
в корне репозитория — это ровно то, чем выглядит. Планка, которой она должна соответствовать, — та, которую вы можете проверить
сами: **847 тестов** (`npm test`), гарантия отсутствия сетевых обращений, обеспечиваемая тестом-ловушкой и
воспроизводимая под `unshare -rn`, и показатели покрытия, измеренные относительно базовой линии Snyk, а
не заявленные. Сам `fad-checker` **не использует LLM во время выполнения**; находки берутся из публичных
баз данных уязвимостей и детерминированных парсеров, и никакой текст отчётов не генерируется. Полное
заявление, включая случай, когда ревью действительно поймало плохую находку →
[`AI_POLICY.md`](https://github.com/9pings/fad-checker/blob/main/AI_POLICY.md). Там, где код не соответствует этой планке, — это баг-репорт, который я хочу получить.
## Лицензия
MIT; см. [`LICENSE`](https://github.com/9pings/fad-checker/blob/main/LICENSE).
| ✅ гл. 0 + 6.3 |
| ⚠️ лог |
| ⚠️ лог |
| ⚠️ лог |
| ⚠️ лог |
| ⚠️ лог |
| Ответить «по каким данным?» шесть месяцев спустя ⁹ | ✅ | ❌ | ❌ | ⚠️ дата БД | ⚠️ дата NVD | ❌ |
| Отправить отчёт, а не дамп JSON ¹⁰ | ✅ HTML + .doc | ⚠️ HTML-список | ⚠️ шаблон | ❌ | ⚠️ HTML-список | ⚠️ snyk-to-html |
| Графики, детализация по каждому CVE и копия для вставки в Word ¹¹ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Делать дельта-отчёты, показывающие только изменения ¹² | ✅ --baseline | ❌ | ❌ | ❌ | ❌ | ⚠️ облако |
--eol-support4. Лицензии (опционально: --licenses) | метаданные реестра + Maven POM → политика SPDX | Лицензия каждой зависимости нормализуется к SPDX и классифицируется; copyleft (GPL/AGPL/LGPL/MPL), проприетарные и неизвестные помечаются для проверки |
| 5. Рекомендации по исправлению | вычислено | Рецепты пинов по экосистемам: Maven <dependencyManagement>, Gradle constraints { }, npm overrides, yarn resolutions, composer require, pip install, dotnet add package |
| 6. Контекст сканирования и ограничения | манифест происхождения + обход | 6.1 Просканированные дескрипторы (каждый разобранный манифест) · 6.2 Игнорируемые директории (отсечённые пути + правило) · 6.3 Методология, источники данных и ограничения (свежесть источников данных, конфигурация запуска, явное заявление о том, что fad-checker не оценивает) |
| Риск цепочки поставок (сквозной) | OSV MAL-… + эвристика имён | Известно-вредоносные пакеты (всегда блокируют CI-гейт, на любом уровне --fail-on) и подозреваемые тайпсквоты (--typosquat: имя в npm/PyPI, отличающееся на одну правку от популярного пакета; lodahs↔lodash) |