
Auditor delle dipendenze buildless che analizza 10 ecosistemi offline, segnalando CVE prioritizzate secondo CISA KEV ed EPSS, pacchetti EOL, licenze, chiavi committate e binari con esportazioni SBOM e SARIF.
Formidable Auditor's Dependency Checker
AKA Fuckin' Autonomous Dependency Checker
fad-checker analizza Maven · Gradle · npm · Yarn · pnpm · Composer · PyPI · NuGet · Go · Ruby, JavaScript vendorizzato, binari nativi committati e materiale crittografico (certificati e chiavi private/pubbliche) in qualsiasi albero sorgente; multi-modulo, monorepo, poliglotta; e produce un report HTML + Word autonomo (CVE prioritizzate per EPSS + CISA KEV, EOL, obsolete, non aggiornate, licenze) più esportazioni . ; legge lockfile e manifest direttamente dal disco.

mvn/gradle/npm install/pip/dotnet restore/go build, niente node_modules/. Il grafo Maven viene risolto come lo risolve Maven. → come--offline, testato in regressione e riproducibile sotto unshare -rn. Su Maven recupera 657/657 del risultato online di OSV-Scanner senza alcuna interfaccia di rete, contro 45 / 40 / 37 degli altri. → Benchmark · Air-gapped--typosquat).SHA256SUMS; gli audit differenziali confrontano con una esecuzione precedente (--baseline) e la CI può fare gating solo sui nuovi findings.--help che sta in una schermata; la lunga coda di switch si riduce a quattro flag — -d eol,nvd disattiva cose, -a licenses,snyk attiva ciò che è disattivato di default, -r html,json sceglie gli output, -o dice dove. I singoli flag funzionano ancora e --help-all li elenca.--lang fr).doc con --report-doc), CycloneDX 1.6 SBOM, CSAF 2.0 VEX, SARIF 2.1.0, JSON; gate con --fail-on, triage con --ignore/--vex. Registry privati per ogni ecosistema.Cosa fa per un audit che gli altri non fanno. Stesso set di colonne e stessa disciplina di sourcing di
docs/COMPARISON.md — ⚠️ significa parziale e indica come, le celle sono pensate per essere
verificabili.
| Cosa un auditor deve effettivamente fare | fad | OSV | Trivy | Grype+Syft | OWASP DC | Snyk |
|---|---|---|---|---|---|---|
| Analizzare un monorepo poliglotta da 100 moduli in un solo comando, con nessun toolchain installato ¹ | ✅ 105 moduli | ⚠️ reactor saltato | ⚠️ richiede ~/.m2 | ⚠️ opt-in | ⚠️ build Java | ⚠️ build mvn |
| Scansionare offline / air-gapped senza perdere dipendenze transitive ² | ✅ 657/657 | ❌ | ⚠️ ~/.m2 | ⚠️ opt-in | ⚠️ mirror | ❌ |
| Identificare le dipendenze private/interne in un grande progetto ³ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Estrarre descrittori di dipendenze ripuliti in una directory esterna ⁴ | ✅ -t | ❌ | ❌ | ❌ | ❌ | ❌ |
| Segnalare framework e dipendenze EOL / deprecati, incluse quelle transitive ⁵ | ✅ | ⚠️ solo deprecati | ⚠️ solo distro OS | ❌ | ❌ | ⚠️ solo web UI |
| Segnalare chiavi e certificati committati ⁶ | ✅ | ❌ | ⚠️ regola chiave | ❌ | ❌ | ❌ |
Individuare binari committati (.dll, .exe, …) e verificarli contro i loro checksum ⁷ | ✅ | ❌ | ⚠️ alcuni | ⚠️ pattern | ❌ | ❌ |
| Elencare chiaramente ciò che è stato scansionato — prima che il cliente lo chieda ⁸ |
¹ Niente mvn/go/npm/pip/dotnet — i manifest vengono analizzati dal disco, nulla installato o eseguito. 105 × pom.xml in un solo passaggio: 790 coppie contro le 657 di OSV-Scanner, 133 solo fad, versioni mediate per modulo non appiattite.
² 657 su 657 del risultato Maven online di OSV-Scanner, sotto unshare -rn — nessuna interfaccia di rete. Testato con tripwire; solo coordinate pubbliche lasciano mai l'enclave.
³ Il capitolo 0 nomina ogni coordinata per cui ogni registry configurato ha risposto 404 — Maven, npm, PyPI, NuGet, Composer, Go e RubyGems — con il/i manifest che la dichiara. Un registry che è andato in timeout o in errore non viene mai conteggiato: una risposta inconcludente accuserebbe altrimenti un cliente di distribuire pacchetti interni perché il suo proxy era instabile. -e <regex> le esclude poi.
⁴ -t <dir>: POM normalizzati più ogni lockfile non-Maven rispecchiato, coordinate private rimosse. Archiviabile e scansionabile da qualsiasi cosa — --snyk incluso.
⁵ endoflife.date, suddiviso diretto vs transitivo così sai quale dipendenza aggiornare, più deprecati / abbandonati / yanked e non aggiornati. Trivy copre solo le distro OS; la salute dei pacchetti di Snyk è solo web.
⁶ Inventario e verdetti: scadenza, RSA<2048, MD5/SHA1, self-signed; chiavi private vs pubbliche; JKS/PKCS#12. Parser offline. La regola sui secret di Trivy trova il file, non il difetto.
⁷ Identificati tramite hash via deps.dev + CIRCL → dovrebbe-essere-dichiarato / nome≠checksum / sconosciuto / malevolo. I pattern di Syft nominano una versione, non un'identità.
⁸ Il capitolo 0 segnala ciò che questa scansione non ha potuto raggiungere (lockfile mancanti, versioni solo-BOM, Yarn Berry, runtime PHP indeterminabile); il capitolo 6.3 dichiara ciò che il tool non valuta mai. Altrove il primo è una riga di log che l'audit non vede mai, il secondo non è scritto da nessuna parte.
⁹ Manifest di provenienza: tool, runtime, modalità, configurazione di esecuzione e freschezza della cache per tutte le 13 fonti. Grype e Dependency-Check portano la data di una fonte, non dell'esecuzione.
¹⁰ Capitoli da 0→6 con un executive summary e ricette di fix, HTML autonomo più un gemello Word .doc. Nessuno degli altri emette Word.
¹¹ Quattro grafici SVG inline — CWE per severità peggiore, transitive vulnerabili per dipendenza radice, i tuoi moduli più vulnerabili (diretto vs transitivo su un progetto mono-modulo), fasce di priorità di fix — renderizzati anche nel .doc, con copia con un clic come PNG (o una tabella come HTML ricco) che si incolla in Word formattata. Ogni CVE mantiene il suo vettore CVSS, CWE, riferimenti, configurazione CPE e via-path dietro un drill-down, con zero asset esterni.
¹² --baseline aggiunge un capitolo Δ (nuovi / risolti / invariati); --fail-on-new fa gating solo sui nuovi findings. Snyk traccia questo sulla sua piattaforma, non come diff locale.
Dove perde — container/pacchetti OS, PR di auto-fix e copertura CVE rispetto al feed curato di Snyk → docs/COMPARISON.md ·
il divario, misurato.
Deliberatamente non un obiettivo: la raggiungibilità. Un finding è una versione vulnerabile sul grafo delle dipendenze, e il report dice esattamente questo (cap. 6.3) invece di indovinare i call path. Decidere se il codice vulnerabile è raggiungibile in questa applicazione è compito dell'auditor, preso con il contesto applicativo che nessuno scanner ha.
[!WARNING] fad-checker è nuovo e potrebbe ancora contenere ( rari ) bug. Tratta il suo output come una solida prima passata, ricontrolla qualsiasi cosa critica e per favore segnala i problemi; vengono risolti rapidamente.
npm install -g fad-checker fad-checker -s ./my-project # → ./fad-checker-report/cve-report.html
Una [chiave API NVD](https://nvd.nist.gov/developers/request-an-api-key) gratuita (immediata) offre un arricchimento 10× più veloce: `fad-checker --set-nvd-key YOUR_KEY`. Alcune esecuzioni comuni; elenco completo tramite `fad-checker --help` o [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
Cosa fa effettivamente -t <dir>. È un passo di estrazione, non un adattatore Snyk. Scrive un
albero parallelo di descrittori di dipendenze normalizzati: ogni pom.xml ridotto ai
nodi rilevanti per le dipendenze (coordinate, properties, dependencyManagement, dependencies,
modules), i parent del reactor ricablati al loro reale relativePath nell'albero, ${…} risolti nelle
coordinate — più ogni lockfile/manifest non-Maven rispecchiato allo stesso percorso relativo
(package-lock/yarn.lock/pnpm-lock, composer.lock, poetry/Pipfile/uv/pdm,
*.csproj/packages.lock.json, go.mod/go.sum, Gemfile.lock, e companion come
Directory.Packages.props o nuget.config). Online sonda anche ogni coordinata contro
i repository Maven configurati e segnala quelle che non esistono lì — i tuoi
moduli privati/interni — che -e <regex> poi rimuove dai POM riscritti. Poi si
ferma: nessuna passata CVE/EOL e nessun report a meno che tu non passi anche --snyk, un --report-<type>,
--fail-on* o --baseline. Quello che ottieni è un inventario di dipendenze sanificato e senza build che puoi
archiviare come evidenza di audit, consegnare a un cliente o a una revisione legale, o puntare a qualsiasi scanner — Snyk via
--snyk essendo uno di questi.
[!IMPORTANT]
--offlinelegge la cache, non la sostituisce. Su una cache fredda non c'è nulla con cui confrontarsi, quindi una prima esecuzione offline riporta legittimamente 0 CVE / 0 EOL / 0 obsoleti; quella è una cache vuota, non un progetto pulito. Scalda la cache una volta (una normale esecuzione online su qualsiasi progetto, o--import-cache), poi--offlinerestituisce il set completo di risultati con zero chiamate di rete. Le macchine air-gapped ottengono la loro cache tramite--export-cache/--import-cache.
Un singolo binario autonomo (senza Node), l'installazione da sorgente e il completamento shell sono in → docs/USAGE.md.
Il report è organizzato in capitoli radice (ciascuno raggruppa sotto-capitoli correlati):
| Capitolo | Fonte | Cosa rileva |
|---|---|---|
| 0. Avvisi (in alto) | euristiche locali | Lockfile mancanti, versioni Maven non risolte (gestite da BOM), librerie private non su Maven Central |
Δ. Modifiche dalla baseline (in alto, con --baseline) | diff vs JSON precedente | Rilievi nuovi / risolti / invariati per categoria + l'elenco delle nuove CVE di produzione; per audit ripetuti e gating CI con --fail-on-new |
| 1. CVE (X dirette, Y indirette, Z dev) | CVEProject + OSV.dev + NVD + CPE | 1.1 Produzione; CVE pubbliche / GHSA nelle dipendenze di prod, per ecosistema, per manifest, prioritizzate per CISA KEV + EPSS + CVSS · 1.2 Vulnerabilità JS vendored (retire.js) · 1.3 Dev (test/provided, dev/optional/peer) · 1.4 Probabili falsi positivi (filtrati per CPE) |
| 2. Componenti non gestiti / senza versione | deps.dev + CIRCL (per checksum), retire.js, X.509 integrato | 2.1 Binari incorporati; CVE in librerie incluse dentro .jar/.war/.ear committati (fat-jar, uber-jar shaded) · 2.2 Binari nativi (.dll/.exe/.so/.dylib) identificati per hash, segnalati come dovrebbero-essere-gestiti / nome≠checksum / sconosciuto / malevolo · 2.3 Inventario JavaScript vendored (jQuery, Bootstrap, …) vulnerabile o no · 2.4 Certificati e materiale di chiave; certificati committati (scadenza / chiave debole / firma debole / auto-firmati), chiavi private vs pubbliche (PEM/OpenSSH/PuTTY/PGP/SSH) e keystore, tutto analizzato offline |
| 3. Manutenzione / ciclo di vita (X EOL, Y obsoleti, Z non aggiornati) | endoflife.date · flag curati + registry · Maven Central / npm / Packagist / PyPI / NuGet | 3.1 End-of-Life framework (+ una fascia "Fuori supporto attivo" con --eol-support; Symfony/Laravel raggruppati come una riga per framework; runtime PHP quando il vincolo Composer lo dimostra), suddivisi in (dichiarati / ereditati dal parent-POM — aggiorna questi) vs (aggiorna la dipendenza che li trascina) · · (versione più recente disponibile, con date di rilascio; solo dipendenze dirette) |
Il report HTML si apre in qualsiasi browser, contiene ogni dettaglio (vettori CVSS, riferimenti, descrizioni complete, configurazioni CPE, via-path per i transitivi) e include un gemello .doc compatibile con Word. Ogni corrispondenza porta una priorità composita (sfruttata da KEV > probabilità EPSS > severità CVSS), e l'esecuzione può inoltre emettere un SBOM CycloneDX 1.6 (--report-sbom, vulnerabilità inline) e un CSAF 2.0 VEX (--report-csaf) per strumenti a valle.

Nessuno strumento trova tutto. fad-checker è in testa all'87% di un'unione di 908 coppie, e 131 coppie sono tornate da Snyk e non da esso. Valutate una per una contro OSV, nessuna è un bug di recall:
| Verdetto | |
|---|---|
| 57 | artefatto errato — l'advisory si lega a una coordinata diversa |
| 31 | fuori intervallo — la versione è al di fuori di ogni intervallo affetto dichiarato |
| 23 | non in OSV — 19 id SNYK-* proprietari, 4 che solo NVD porta |
| 19 | nessun binding Maven — l'advisory non si lega ad alcun pacchetto Maven |
| 1 | già riportato, sotto l'alias CVE |
| 0 | mancato rilevamento confermato |
Due terzi contraddicono il registro pubblico, quindi riportarli significherebbe spedire falsi
positivi. CVE-2023-6481 è l'esempio limpido: rivendicata su [email protected], si lega
a logback-core a [1.2.12, 1.2.13) — artefatto errato, e una versione pubblicata prima che il difetto
esistesse.
Ambito. Tutte le 131 sono di Snyk: OSV-Scanner, Trivy e Grype+Syft hanno contribuito ciascuno con 0 rilevamenti che nessun altro aveva. E tutte sono sul target Maven — fuori da Maven il grafo è nel lockfile, ogni scanner legge lo stesso input, e il benchmark misura set di rilevamenti identici su npm, RubyGems e Composer.
Ecco perché esiste --snyk. fad-checker prende l'output di snyk test come input e lo unisce, così ottieni
l'unione invece di scegliere una parte. Una scelta di copertura, non una correzione.
Metodo, avvertenze e i verdetti per coppia → docs/BENCHMARK.md; riproduci
con scripts/adjudicate-gap.js.
Garanzia di zero dati inviati. Sotto
--offline, fad-checker non effettua alcuna chiamata di rete di sorta; legge solo le cache riscaldate in~/.fad-checker/e non trasmette mai una dipendenza, un percorso o un rilevamento fuori dalla macchina. È testato per regressioni (test/offline-guarantee.test.js, un fetcher tripwire che lancia un'eccezione se toccato) e riproducibile dall'auditor:unshare -rn node fad-checker.js -s ./proj --offline …lo esegue in un namespace con nessuna interfaccia di rete e produce rilevamenti identici byte per byte. A differenza dei scanner OSS mainstream, fad risolve anche il grafo transitivo Maven offline; quindi su un progetto multi-modulo air-gapped trova le CVE transitive che loro non riescono a trovare.
Quando il sistema sottoposto ad audit è offline / riservato (tipico di un audit regolamentato o air-gapped) non può raggiungere OSV / NVD / Maven Central / npm. Suddividi il lavoro tra macchine mantenendo zero informazioni sull'ambiente fuori dall'enclave sicura: un descrittore anonimizzato porta solo coordinate di pacchetti pubblici; nessun percorso filesystem, nessun URL di registry, nessun hostname/username; e il report dettagliato è prodotto di nuovo sulla macchina offline.
Il trasferimento si basa su una proprietà delle cache di fad-checker: sono indicizzate per coordinata o id di vulnerabilità, mai per percorso, quindi sono indipendenti dalla macchina. Il passo online si limita a riscaldare le cache; il passo offline riproduce la scansione e ottiene cache hit.```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
Cosa contiene il descrittore (`fad-deps/1`) rispetto a cosa scarta:
| Mantenuto (necessario per la scansione) | Scartato (ambiente) |
| --- | --- |
| ecosystem, ecosystemType | percorsi manifest / percorsi pom |
| namespace, name | URL del registry risolti |
| version, versions | hash di integrità |
| scope, isDev | catene parent, tipo di lockfile |
Il report della fase online è esso stesso privo di percorsi; i risultati sul JavaScript vendored (retire.js) vengono prodotti **offline nella fase 3**, poiché retire necessita dei file `.js` effettivi; il suo database delle firme viene riscaldato online (fase 2) e trasportato da `--export-cache`. Controllo completo offline/cache →
[`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md).
## Documentazione
- [`docs/USAGE.md`](https://github.com/9pings/fad-checker/blob/main/docs/USAGE.md); ogni flag e workflow: controllo offline/cache, registry privati, file di configurazione, ricette, barriere di sicurezza.
- [`docs/ARCHITECTURE.md`](https://github.com/9pings/fad-checker/blob/main/docs/ARCHITECTURE.md); funzionamento interno: codec, raccolta, matching, pipeline di report.
- [`docs/COMPARISON.md`](https://github.com/9pings/fad-checker/blob/main/docs/COMPARISON.md); rispetto a OSV-Scanner / Trivy / Grype / OWASP DC / Snyk, e come rimane build-free.
- [`docs/BENCHMARK.md`](https://github.com/9pings/fad-checker/blob/main/docs/BENCHMARK.md) — benchmark di recall riproducibile in air-gapped rispetto a OSV-Scanner su un progetto pubblico di 105 moduli.
- [`docs/DATA-SOURCES.md`](https://github.com/9pings/fad-checker/blob/main/docs/DATA-SOURCES.md); i dataset pubblici usati da fad-checker + le loro licenze.
- [`docs/SPEC-audit-pro.md`](https://github.com/9pings/fad-checker/blob/main/docs/SPEC-audit-pro.md); le funzionalità di livello audit (provenienza, audit differenziale, metodologia/integrità) e perché ciascuna è stata costruita in quel modo.
- [`CHANGELOG.md`](https://github.com/9pings/fad-checker/blob/main/CHANGELOG.md) · [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md); cronologia delle release · orientamento a livello di codice per i contributori.
## Contribuire
Il contributo più utile per uno scanner giovane è **dirgli dove sbaglia**: eseguilo su un
progetto reale e apri una [segnalazione di falso positivo / falso negativo](https://github.com/9pings/fad-checker/issues/new?template=false_positive.yml)
con la coordinata e lo snippet di manifest che l'ha prodotta. Setup di sviluppo, regole di base e il
punto di estensione dei codec → [`CONTRIBUTING.md`](https://github.com/9pings/fad-checker/blob/main/CONTRIBUTING.md). Vulnerabilità in fad-checker
stesso → [`SECURITY.md`](https://github.com/9pings/fad-checker/blob/main/SECURITY.md) (si prega di segnalare in privato).
**Sull'assistenza AI:** questo codebase è scritto con un uso intenso di Claude Code; [`CLAUDE.md`](https://github.com/9pings/fad-checker/blob/main/CLAUDE.md)
nella root del repository è esattamente ciò che sembra. L'asticella a cui è tenuto è quella che puoi verificare
tu stesso: **847 test** (`npm test`), la garanzia di zero-network imposta da un test tripwire e
riproducibile sotto `unshare -rn`, e numeri di copertura misurati rispetto a una baseline Snyk anziché
asseriti. `fad-checker` stesso non usa **nessun LLM a runtime**; i risultati provengono da database
pubblici di vulnerabilità e parser deterministici, e nessun testo di report viene generato. Dichiarazione
completa, incluso dove la revisione ha effettivamente individuato un risultato errato →
[`AI_POLICY.md`](https://github.com/9pings/fad-checker/blob/main/AI_POLICY.md). Dove il codice non raggiunge quell'asticella, quella è una segnalazione di bug che voglio.
## Licenza
MIT; vedi [`LICENSE`](https://github.com/9pings/fad-checker/blob/main/LICENSE).
| ✅ cap. 0 + 6.3 |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| ⚠️ log |
| Rispondere "contro quali dati?" sei mesi dopo ⁹ | ✅ | ❌ | ❌ | ⚠️ data DB | ⚠️ data NVD | ❌ |
| Inviare un report, non un dump JSON ¹⁰ | ✅ HTML + .doc | ⚠️ lista HTML | ⚠️ template | ❌ | ⚠️ lista HTML | ⚠️ snyk-to-html |
| Grafici, drill-down per CVE e una copia Word incollabile ¹¹ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Produrre report delta che mostrano solo ciò che è cambiato ¹² | ✅ --baseline | ❌ | ❌ | ❌ | ❌ | ⚠️ cloud |
4. Licenze (opt-in: --licenses) | metadati registry + POM Maven → policy SPDX | La licenza di ogni dipendenza normalizzata a SPDX e classificata; copyleft (GPL/AGPL/LGPL/MPL), proprietarie e sconosciute segnalate per revisione |
| 5. Raccomandazioni di correzione | calcolate | Ricette di pin per ecosistema: Maven <dependencyManagement>, Gradle constraints { }, npm overrides, yarn resolutions, composer require, pip install, dotnet add package |
| 6. Contesto di scansione e limitazioni | manifest di provenienza + walk | 6.1 Descrittori scansionati (ogni manifest analizzato) · 6.2 Directory ignorate (percorsi potati + regola) · 6.3 Metodologia, fonti dati e limitazioni (freschezza delle fonti dati, configurazione di esecuzione, dichiarazione esplicita di ciò che fad-checker non valuta) |
| Rischio supply-chain (trasversale) | OSV MAL-… + euristica sui nomi | Pacchetti noti come malevoli (bloccano sempre il gate CI, a qualsiasi livello --fail-on) e presunti typosquat (--typosquat: un nome npm/PyPI a una modifica da un pacchetto popolare; lodahs↔lodash) |