
Auditor de dependências sem build que verifica 10 ecossistemas offline, reportando CVEs priorizados por CISA KEV e EPSS, pacotes EOL, licenças, chaves comprometidas e binários com exportações SBOM e SARIF.
Formidable Auditor's Dependency Checker
Também conhecido como Fuckin' Autonomous Dependency Checker
fad-checker audita Maven · Gradle · npm · Yarn · pnpm · Composer · PyPI · NuGet · Go · Ruby, JavaScript vendorizado, binários nativos commitados e material criptográfico (certificados e chaves privadas/públicas) em qualquer árvore de código-fonte; multi-módulo, monorepo, poliglota; e produz um relatório HTML + Word autocontido (CVE priorizados por EPSS + CISA KEV, EOL, obsoletos, desatualizados, licenças) mais exportações . ; lê lockfiles e manifestos diretamente do disco.

mvn/gradle/npm install/pip/dotnet restore/go build, sem node_modules/. O grafo Maven é resolvido da forma como o Maven o resolve. → como--offline, testado por regressão e reproduzível sob unshare -rn. No Maven recupera 657/657 do resultado online do OSV-Scanner sem qualquer interface de rede, contra 45 / 40 / 37 dos outros. → Benchmark · Air-gapped--typosquat).SHA256SUMS; auditorias diferenciais comparam com uma execução anterior (--baseline) e a CI pode fazer gate apenas em novos achados.--help que cabe num ecrã; a longa cauda de opções agrupa-se em quatro flags — -d eol,nvd desliga coisas, -a licenses,snyk liga o que está desligado por defeito, -r html,json escolhe as saídas, -o diz onde. As flags individuais continuam a funcionar e --help-all lista-as.--lang fr).doc com --report-doc), CycloneDX 1.6 SBOM, CSAF 2.0 VEX, SARIF 2.1.0, JSON; gate com --fail-on, triagem com --ignore/--vex. Registos privados para todos os ecossistemas.O que faz numa auditoria que os outros não fazem. Mesmo conjunto de colunas e disciplina de
sourcing que docs/COMPARISON.md — ⚠️ é parcial e diz como, as células
devem ser verificáveis.
| O que um auditor realmente precisa de fazer | fad | OSV | Trivy | Grype+Syft | OWASP DC | Snyk |
|---|---|---|---|---|---|---|
| Auditar um monorepo poliglota de 100 módulos num só comando, sem toolchain instalada ¹ | ✅ 105 módulos | ⚠️ reactor ignorado | ⚠️ precisa de ~/.m2 | ⚠️ opt-in | ⚠️ build Java | ⚠️ build mvn |
| Analisar offline / air-gapped sem perder dependências transitivas ² | ✅ 657/657 | ❌ | ⚠️ ~/.m2 | ⚠️ opt-in | ⚠️ mirror | ❌ |
| Identificar as dependências privadas/internas num projeto grande ³ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Extrair descritores de dependências limpos para um diretório externo ⁴ | ✅ -t | ❌ | ❌ | ❌ | ❌ | ❌ |
| Reportar frameworks e dependências EOL / depreciados, incluindo transitivos ⁵ | ✅ | ⚠️ apenas depreciados | ⚠️ apenas distros OS | ❌ | ❌ | ⚠️ apenas UI web |
| Reportar chaves e certificados commitados ⁶ | ✅ | ❌ | ⚠️ regra de chaves | ❌ | ❌ | ❌ |
Detetar binários commitados (.dll, .exe, …) e verificá-los contra os seus checksums ⁷ | ✅ | ❌ | ⚠️ alguns | ⚠️ padrões | ❌ | ❌ |
| Listar claramente o que foi analisado — antes de o cliente perguntar ⁸ |
¹ Sem mvn/go/npm/pip/dotnet — manifestos analisados do disco, nada instalado ou executado. 105 × pom.xml numa só passagem: 790 pares vs 657 do OSV-Scanner, 133 exclusivos do fad, versões mediadas por módulo e não achatadas.
² 657 de 657 do resultado Maven online do OSV-Scanner, sob unshare -rn — sem interface de rede. Testado com tripwire; apenas coordenadas públicas saem do enclave.
³ O capítulo 0 nomeia todas as coordenadas para as quais todos os registos configurados responderam 404 — Maven, npm, PyPI, NuGet, Composer, Go e RubyGems — com o(s) manifesto(s) que as declaram. Um registo que deu timeout ou erro nunca é contado: uma resposta inconclusiva acusaria de outro modo um cliente de enviar pacotes internos porque o seu proxy estava instável. -e <regex> exclui-os depois.
⁴ -t <dir>: POMs normalizados mais todos os lockfiles não-Maven espelhados, coordenadas privadas removidas. Arquivável e analisável por qualquer coisa — --snyk incluído.
⁵ endoflife.date, dividido em direto vs transitivo para saber qual dependência atualizar, mais depreciados / abandonados / yanked e desatualizados. O Trivy cobre apenas distros OS; a saúde de pacotes do Snyk é apenas web.
⁶ Inventário e veredictos: expiração, RSA<2048, MD5/SHA1, autoassinado; chaves privadas vs públicas; JKS/PKCS#12. Parser offline. A regra de segredos do Trivy encontra o ficheiro, não o defeito.
⁷ Identificados por hash via deps.dev + CIRCL → deveria-ser-declarado / nome≠checksum / desconhecido / malicioso. Os padrões do Syft nomeiam uma versão, não uma identidade.
⁸ O capítulo 0 assinala o que esta análise não conseguiu alcançar (lockfiles em falta, versões apenas-BOM, Yarn Berry, runtime PHP indeterminável); o capítulo 6.3 declara o que a ferramenta nunca avalia. Noutros casos o primeiro é uma linha de log que a auditoria nunca vê, o segundo não está escrito.
⁹ Manifesto de proveniência: ferramenta, runtime, modo, configuração de execução e frescura de cache para todas as 13 fontes. O Grype e o Dependency-Check trazem a data de uma fonte, não da execução.
¹⁰ Capítulos 0→6 com um sumário executivo e receitas de correção, HTML autocontido mais um gémeo Word .doc. Nenhum dos outros emite Word.
¹¹ Quatro gráficos SVG inline — CWE por pior severidade, transitivos vulneráveis por dependência raiz, os seus módulos mais vulneráveis (direto vs transitivo num projeto de módulo único), bandas de prioridade de correção — renderizados também no .doc, com cópia com um clique como PNG (ou uma tabela como HTML rico) que cola no Word formatado. Cada CVE mantém o seu vetor CVSS, CWE, referências, configuração CPE e via-path atrás de um drill-down, com zero recursos externos.
¹² --baseline adiciona um capítulo Δ (novo / corrigido / inalterado); --fail-on-new faz gate apenas em novos achados. O Snyk acompanha isto na sua plataforma, não como diff local.
Onde perde — contentores/pacotes OS, PRs de correção automática, e cobertura de CVE face ao feed
curado do Snyk → docs/COMPARISON.md ·
a lacuna, medida.
Deliberadamente não é um objetivo: alcançabilidade. Um achado é uma versão vulnerável no grafo de dependências, e o relatório diz exatamente isso (cap. 6.3) em vez de adivinhar caminhos de chamada. Decidir se o código vulnerável é alcançável nesta aplicação é decisão do auditor, tomada com contexto da aplicação que nenhum scanner tem.
[!WARNING] O fad-checker é novo e pode ainda conter ( raros ) bugs. Trate a sua saída como uma forte primeira passagem, verifique duas vezes qualquer coisa crítica, e por favor reporte problemas; são corrigidos rapidamente.
npm install -g fad-checker fad-checker -s ./my-project # → ./fad-checker-report/cve-report.html
Uma [chave de API do NVD](https://nvd.nist.gov/developers/request-an-api-key) gratuita (instantânea) proporciona enriquecimento 10× mais rápido: `fad-checker --set-nvd-key YOUR_KEY`. Algumas execuções comuns; lista completa via `fad-checker --help` ou [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
O que -t <dir> realmente faz. É um passo de extração, não um adaptador Snyk. Escreve uma
árvore paralela de descritores de dependências normalizados: cada pom.xml reduzido aos
nós relevantes para dependências (coordenadas, properties, dependencyManagement, dependencies,
modules), parents do reactor religados ao seu verdadeiro relativePath na árvore, ${…} resolvidos nas
coordenadas — mais todos os lockfiles/manifests não-Maven espelhados no mesmo caminho relativo
(package-lock/yarn.lock/pnpm-lock, composer.lock, poetry/Pipfile/uv/pdm,
*.csproj/packages.lock.json, go.mod/go.sum, Gemfile.lock, e companheiros como
Directory.Packages.props ou nuget.config). Online também sonda cada coordenada contra
os repositórios Maven configurados e reporta as que não existem lá — os teus
módulos privados/internos — que o -e <regex> depois remove dos POMs reescritos. Depois
para: sem passagem de CVE/EOL e sem relatório a menos que também passes --snyk, um --report-<type>,
--fail-on* ou --baseline. O que obténs é um inventário de dependências sanitizado e sem build que podes
arquivar como evidência de auditoria, entregar a um cliente ou a uma revisão legal, ou apontar qualquer scanner — Snyk via
--snyk sendo um deles.
[!IMPORTANT]
--offlinelê a cache, não a substitui. Numa cache fria não há nada para corresponder, por isso uma primeira execução offline reporta legitimamente 0 CVE / 0 EOL / 0 desatualizadas; isso é uma cache vazia, não um projeto limpo. Aquece-a uma vez (uma execução online normal em qualquer projeto, ou--import-cache), depois--offlinedevolve o conjunto completo de resultados com zero chamadas de rede. Máquinas air-gapped obtêm a sua cache via--export-cache/--import-cache.
Um único binário autónomo (sem Node), instalação a partir do código-fonte e autocompletar de shell estão em → docs/USAGE.md.
O relatório está organizado em capítulos raiz (cada um agrupando sub-capítulos relacionados):
| Capítulo | Fonte | O que deteta |
|---|---|---|
| 0. Avisos (topo) | heurísticas locais | Lockfiles em falta, versões Maven não resolvidas (geridas por BOM), libs privadas que não estão no Maven Central |
Δ. Alterações desde a baseline (topo, com --baseline) | diff vs JSON anterior | Achados novos / corrigidos / inalterados por categoria + a lista de novos CVEs de produção; para auditorias repetidas e gating de CI com --fail-on-new |
| 1. CVE (X diretos, Y indiretos, Z dev) | CVEProject + OSV.dev + NVD + CPE | 1.1 Produção; CVE público / GHSA em deps de produção, por ecossistema, por manifest, priorizados por CISA KEV + EPSS + CVSS · 1.2 Vulnerabilidades de JS vendorizado (retire.js) · 1.3 Dev (test/provided, dev/optional/peer) · 1.4 Prováveis falsos positivos (filtrados por CPE) |
| 2. Componentes não geridos / sem versão | deps.dev + CIRCL (por checksum), retire.js, X.509 incorporado | 2.1 Binários embutidos; CVEs em libs enviadas dentro de .jar/.war/.ear commitados (fat-jars, uber-jars com shading) · 2.2 Binários nativos (.dll/.exe/.so/.dylib) identificados por hash, sinalizados como deviam-ser-geridos / nome≠checksum / desconhecido / malicioso · 2.3 Inventário de JavaScript vendorizado (jQuery, Bootstrap, …) vulnerável ou não · 2.4 Certificados & material de chave; certificados commitados (expiração / chave fraca / assinatura fraca / autoassinado), chaves privadas vs públicas (PEM/OpenSSH/PuTTY/PGP/SSH) e keystores, tudo analisado offline |
| 3. Manutenção / ciclo de vida (X EOL, Y obsoletas, Z desatualizadas) | endoflife.date · flags curadas + de registry · Maven Central / npm / Packagist / PyPI / NuGet | 3.1 Fim-de-vida de frameworks (+ uma faixa "Fora de suporte ativo" com ; Symfony/Laravel agrupados como uma linha por framework; runtime PHP quando a restrição do Composer o prova), dividido em (declarados / herdados do parent-POM — atualiza estes) vs (atualiza a dep que os traz) · · (versão mais recente disponível, com datas de lançamento; apenas deps diretas) |
O relatório HTML abre em qualquer navegador, contém todos os detalhes (vetores CVSS, referências, descrições completas, configurações CPE, via-paths para transitivas) e inclui um gémeo .doc compatível com Word. Cada correspondência carrega uma prioridade composta (explorado por KEV > probabilidade EPSS > severidade CVSS), e a execução pode ainda emitir um SBOM CycloneDX 1.6 (--report-sbom, vulnerabilidades inline) e um CSAF 2.0 VEX (--report-csaf) para ferramentas a jusante.

Nenhuma ferramenta encontra tudo. O fad-checker lidera com 87% de uma união de 908 pares, e 131 pares vieram do Snyk e não dele. Julgados um a um contra o OSV, nenhum é um bug de recall:
| Veredicto | |
|---|---|
| 57 | artefacto errado — o advisory vincula uma coordenada diferente |
| 31 | fora do intervalo — a versão está fora de todos os intervalos afetados declarados |
| 23 | não está no OSV — 19 ids SNYK-* proprietários, 4 que só o NVD tem |
| 19 | sem vinculação Maven — o advisory não vincula nenhum pacote Maven |
| 1 | já reportado, sob o alias CVE |
| 0 | falha confirmada |
Dois terços contradizem o registo público, por isso reportá-los significaria enviar falsos
positivos. CVE-2023-6481 é o exemplo claro: reivindicado em [email protected], vincula
logback-core em [1.2.12, 1.2.13) — artefacto errado, e uma versão publicada antes de a falha
existir.
Âmbito. Todos os 131 são do Snyk: OSV-Scanner, Trivy e Grype+Syft contribuíram cada um com 0 achados que mais ninguém tinha. E todos são no alvo Maven — fora do Maven o grafo está no lockfile, todos os scanners leem a mesma entrada, e o benchmark mede conjuntos de achados idênticos em npm, RubyGems e Composer.
É por isso que --snyk existe. O fad-checker aceita a saída do snyk test como entrada e funde-a,
para obteres a união em vez de escolher um lado. Uma escolha de cobertura, não uma correção.
Método, ressalvas e os veredictos por par → docs/BENCHMARK.md; reproduz
com scripts/adjudicate-gap.js.
Garantia de zero dados enviados. Sob
--offline, o fad-checker não faz chamadas de rede de espécie alguma; lê apenas as caches aquecidas em~/.fad-checker/e nunca transmite uma dependência, caminho ou achado para fora da máquina. É testado contra regressões (test/offline-guarantee.test.js, um fetcher-armadilha que lança erro se for tocado) e reproduzível por auditores:unshare -rn node fad-checker.js -s ./proj --offline …executa-o num namespace com nenhuma interface de rede e produz achados idênticos byte a byte. Ao contrário dos scanners OSS mainstream, o fad também resolve o grafo transitivo Maven offline; por isso, num projeto multi-módulo air-gapped, encontra os CVEs transitivos que eles não conseguem.
Quando o sistema auditado está offline / confidencial (típico de uma auditoria regulada ou air-gapped) não consegue alcançar OSV / NVD / Maven Central / npm. Divide o trabalho entre máquinas mantendo zero informação do ambiente fora do enclave seguro: um descritor anonimizado transporta apenas coordenadas públicas de pacotes; sem caminhos de filesystem, sem URLs de registry, sem hostnames/usernames; e o relatório detalhado é produzido de volta na máquina offline.
A transferência baseia-se numa propriedade das caches do fad-checker: são indexadas por coordenada ou id de vulnerabilidade, nunca por caminho, por isso são independentes da máquina. O passo online apenas aquece as caches; o passo offline reproduz o scan e obtém cache hits.```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
O que o descritor (`fad-deps/1`) contém vs. descarta:
| Mantido (necessário para escanear) | Descartado (ambiente) |
| --- | --- |
| ecosystem, ecosystemType | caminhos de manifesto / caminhos de pom |
| namespace, name | URLs de registro resolvidas |
| version, versions | hashes de integridade |
| scope, isDev | cadeias pai, tipo de lockfile |
O relatório da fase online é, ele próprio, livre de caminhos; os achados de JavaScript vendorizado (retire.js) são
produzidos **offline na fase 3**, já que o retire precisa dos arquivos `.js` reais; seu banco de assinaturas
é aquecido online (fase 2) e carregado por `--export-cache`. Controle offline/cache completo →
[`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md).
## Docs
- [`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md); cada flag e fluxo de trabalho: controle offline/cache, registros privados, arquivos de configuração, receitas, trilhos de segurança.
- [`docs/ARCHITECTURE.md`](https://github.com/9pings/fad-checker/blob/main/docs/ARCHITECTURE.md); detalhes internos: codecs, coleta, correspondência, pipeline de relatórios.
- [`docs/COMPARISON.md`](https://github.com/9pings/fad-checker/blob/main/docs/COMPARISON.md); vs OSV-Scanner / Trivy / Grype / OWASP DC / Snyk, e como ele se mantém livre de build.
- [`docs/BENCHMARK.md`](https://github.com/9pings/fad-checker/blob/main/docs/BENCHMARK.md) — benchmark de recall reproduzível em ambiente air-gapped vs OSV-Scanner em um projeto público de 105 módulos.
- [`docs/DATA-SOURCES.md`](https://github.com/9pings/fad-checker/blob/main/docs/DATA-SOURCES.md); os conjuntos de dados públicos que o fad-checker usa + suas licenças.
- [`docs/SPEC-audit-pro.md`](https://github.com/9pings/fad-checker/blob/main/docs/SPEC-audit-pro.md); os recursos de nível de auditoria (proveniência, auditoria diferencial, metodologia/integridade) e por que cada um foi construído dessa forma.
- [`CHANGELOG.md`](https://github.com/9pings/fad-checker/blob/main/CHANGELOG.md) · [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md); histórico de releases · orientação em nível de código para contribuidores.
## Contribuindo
A contribuição mais útil para um scanner jovem é **dizer onde ele está errado**: execute-o em um
projeto real e registre um [relatório de falso positivo / falso negativo](https://github.com/9pings/fad-checker/issues/new?template=false_positive.yml)
com a coordenada e o trecho de manifesto que o produziu. Configuração de desenvolvimento, regras básicas e o
ponto de extensão de codec → [`CONTRIBUTING.md`](https://github.com/9pings/fad-checker/blob/main/CONTRIBUTING.md). Vulnerabilidades no próprio fad-checker
→ [`SECURITY.md`](https://github.com/9pings/fad-checker/blob/main/SECURITY.md) (por favor, reporte de forma privada).
**Sobre assistência de IA:** este código é escrito com uso intenso do Claude Code; [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md)
na raiz do repositório é exatamente o que parece. O padrão exigido é aquele que você mesmo pode verificar:
**847 testes** (`npm test`), a garantia de zero rede imposta por um teste tripwire e
reproduzível sob `unshare -rn`, e números de cobertura medidos contra uma linha de base do Snyk em vez
de afirmados. O próprio `fad-checker` **não usa LLM em tempo de execução**; os achados vêm de bancos de dados
públicos de vulnerabilidades e parsers determinísticos, e nenhum texto de relatório é gerado. Declaração
completa, incluindo onde a revisão realmente capturou um achado ruim →
[`AI_POLICY.md`](https://github.com/9pings/fad-checker/blob/main/AI_POLICY.md). Onde o código não atende a esse padrão, isso é um relatório de bug que eu quero.
## Licença
MIT; veja [`LICENSE`](https://github.com/9pings/fad-checker/blob/main/LICENSE).
| ✅ cap. 0 + 6.3 |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| Responder "contra que dados?" seis meses depois ⁹ | ✅ | ❌ | ❌ | ⚠️ data da BD | ⚠️ data NVD | ❌ |
| Enviar um relatório, não um dump JSON ¹⁰ | ✅ HTML + .doc | ⚠️ lista HTML | ⚠️ template | ❌ | ⚠️ lista HTML | ⚠️ snyk-to-html |
| Gráficos, drill-down por CVE e uma cópia Word colável ¹¹ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Fazer relatórios delta mostrando apenas o que mudou ¹² | ✅ --baseline | ❌ | ❌ | ❌ | ❌ | ⚠️ cloud |
--eol-support4. Licenças (opt-in: --licenses) | metadados de registry + POMs Maven → política SPDX | A licença de cada dep normalizada para SPDX e classificada; copyleft (GPL/AGPL/LGPL/MPL), proprietária e desconhecida sinalizadas para revisão |
| 5. Recomendações de correção | calculadas | Receitas de pin por ecossistema: Maven <dependencyManagement>, Gradle constraints { }, npm overrides, yarn resolutions, composer require, pip install, dotnet add package |
| 6. Contexto do scan & limitações | manifest de proveniência + percurso | 6.1 Descritores analisados (cada manifest parseado) · 6.2 Diretórios ignorados (caminhos podados + regra) · 6.3 Metodologia, fontes de dados & limitações (frescura das fontes de dados, configuração da execução, declaração explícita do que o fad-checker não avalia) |
| Risco de cadeia de abastecimento (transversal) | OSV MAL-… + heurística de nomes | Pacotes conhecidamente maliciosos (bloqueiam sempre o gate de CI, em qualquer nível de --fail-on) e typosquats suspeitos (--typosquat: um nome npm/PyPI a uma edição de distância de um pacote popular; lodahs↔lodash) |