MIT · zero-build MavenGradlenpmpnpm ComposerPyPINuGet GoRubyNative bins

Audit every dependency.No build. No leaks.

A polyglot CVE · EOL · outdated · license scanner that reads your source tree directly — no mvn, no npm install, no Docker. Findings merged from CVEProject, OSV, NVD & retire.js, prioritised with EPSS + CISA KEV, an audit-ready HTML & Word report (plus CycloneDX SBOM & CSAF VEX), and an air-gapped mode for confidential code.

$npm i -g fad-checker && fad -s ./your-project

⚠️ Young project — expect rough edges. fad-checker is new and under active development, so it may still contain bugs (false positives / negatives). Treat its output as a strong first pass, double-check anything critical, and report issues — they get fixed fast.

fad-checker animated terminal demo: a [n/N] checklist warming each vulnerability database, then CVE results coloured by severity with KEV badges
One tool, one pass

Ten ecosystems + vendored JS + embedded JARs + native binaries

Point it at any checkout — multi-module, monorepo, polyglot. It parses manifests and lockfiles directly, and falls back to best-effort (pinned versions) when there's no lockfile.

Maven · pom.xmlGradle · build.gradle(.kts) + libs.versions.tomlnpm · package-lockYarn · v1 + Berry pnpm · v5/6/9Composer · composer.lockPyPI · poetry/uv/pdm/pip NuGet · .csproj/.fsproj/.vbprojGo · go.mod/go.sum Ruby · Gemfile.lockVendored JS · retire.js Embedded JARs · full inventory (ch.1B) Native bins · .dll/.so/.exe/.dylib
Why it's different

Built for audits, not just CI

01

No build, polyglot

Reads pom.xml, build.gradle & lockfiles across all ten ecosystems. No JDK, no install, no Docker — audit a checkout you can't even compile. It even cracks open committed .jar/.war/.ear binaries (fat-jars, shaded uber-jars) in-memory to scan the libraries shaded inside them.

02

Merged sources, fewer false positives

CVEProject + OSV.dev + NVD + retire.js, merged & deduped, then cross-checked against NVD CPE version ranges to filter noise.

03

Risk-based priority

Every CVE enriched with EPSS (FIRST.org exploit-prediction) and CISA KEV (known-exploited). A composite score puts exploited-in-the-wild first, not just the highest CVSS.

04

Beyond CVEs

Flags end-of-life (endoflife.date, with a Source column tracing each verdict to its mapping rule), deprecated / abandoned / yanked, outdated versions, and licenses (SPDX + copyleft policy) — signals most scanners skip.

05

Reports you can hand over

One self-contained HTML + Word-compatible .doc, organised by ecosystem and by the manifest that declares each dep, with per-tool fix recipes.

06

Exports & CI gating

Emit CycloneDX 1.6 SBOM, CSAF 2.0 VEX, flat JSON and SARIF 2.1.0 (GitHub/GitLab code scanning). Gate with --fail-on critical|kev or — for repeat audits — on new findings only with --baseline + --fail-on-new; triage false-positives via --ignore / --vex.

07

Air-gapped

Export an anonymized descriptor (public coordinates only), enrich online, report offline. The confidential codebase never leaves the enclave.

08

Maven private-dep cleanup

Strip private/internal dependencies into a parallel tree of cleaned POMs, ready to feed straight into Snyk.

09

Native binaries, by checksum

Committed .dll/.exe/.so/.dylib (magic-byte confirmed — images/assets are never picked up) are identified by hash via deps.dev + CIRCL: flags tampered/unknown files and libraries that should be declared dependencies. No malware/AV lane.

10

Private registries & config files

Point it at private Nexus/Artifactory (Maven), Verdaccio/GitHub Packages (npm), devpi (PyPI), Gemfury (Ruby), GOPROXY (Go), Azure Artifacts/BaGet (NuGet) or Satis/Private Packagist (Composer) — tried first, public last, Basic or Bearer auth. Stash reusable defaults in .fad-env.json / --config or the FAD_CHECKER_ENV variable, and prune sub-paths with gitignore-style --exclude-path — every skipped directory is listed back in the report's Ignored directories appendix.

11

Unmanaged vendored JS, inventoried

Every standalone JS lib committed into the tree (jQuery, Bootstrap, PDF.js, …) that no package manager governs is inventoried — vulnerable or not (via retire.js --verbose). A cyber-hygiene constat on unknown-provenance third-party code, the JS twin of the native-binary scan.

12

Audit-grade & reproducible

Every report carries a provenance manifest (data-source freshness + run config) and a Methodology, data sources & limitations chapter that states what fad doesn't assess. Artifacts ship a SHA256SUMS integrity manifest (sha256sum -c). Differential audits diff a scan against a prior run (--baseline, or fad diff a.json b.json) so CI can fail on new findings only.

13

Certificates & keys

Finds committed X.509 certificates (flags expired, expiring, weak key RSA<2048, weak signature MD5/SHA1, self-signed), private & public keys — each labelled private (a leaked secret) or public — across PEM, OpenSSH every algorithm, PuTTY, PGP and one-line SSH (id_rsa, authorized_keys, known_hosts), plus JKS/PKCS#12 keystores. Parsed 100% offline with the built-in X.509 parser — no network.

The deliverable

An executive summary, then the detail

Severity tiles, a CVE table with a priority column (KEV / EPSS), CWE & fix versions, EOL / obsolete / outdated / license chapters, and a "likely false positives" appendix — all in a single file you can email.

fad-checker HTML report: executive summary with severity tiles and a detailed CVE table with CWE, descriptions and fix versions
cve-report.html — generated by fad -s ./project
Confidential by design

Scan online. Never expose the code.

The vuln databases need the network; your client's code does not. The scan splits in three — only public coordinates ever leave the secure machine. Caches are keyed by coordinate, so warming them online and replaying offline just yields cache hits.

Designed for any air-gapped / confidential review. The online box only ever sees lodash@4.17.21 — never your repository.

# 1 — OFFLINE (audited machine): export anonymized descriptor
fad -s ./proj -e "^(client|internal)\." --export-anonymized deps.json

# 2 — ONLINE (any box, no source): warm the caches
fad --import-anonymized deps.json
fad --export-cache fad-cache.tar.gz

# 3 — OFFLINE again: full report, real paths
fad --import-cache fad-cache.tar.gz
fad -s ./proj --offline
Honest positioning

Where it fits

Not a Trivy/Grype replacement — those own containers and continuous CI. fad-checker owns the zero-setup source audit with an air-gapped story (and now emits SBOM/VEX, flags licenses and prioritises by EPSS/KEV too).

Capabilityfad-checkerOSV-ScannerTrivyGrype+SyftOWASP DCSnyk OSS
Reads lockfiles without build~Javabuild
Best-effort without a lockfile~~
EOL detection~
Outdated / deprecated~
EPSS / KEV prioritization~
License compliance~~
SBOM / VEX export✓ CDX+CSAF~
HTML + Word reportjsonjsonjsonhtmlcloud
Air-gapped, code never exposed
Containers / OS packages~

² For pom.xml, transitives need Maven Central once — after that fad-checker resolves the graph from its cached POMs, which is what makes the air-gapped run work. Snyk needs a real build, Trivy needs the network or a populated ~/.m2. Reach for Trivy or Grype+Syft for continuous CI, containers and SBOM pipelines.

³ EOL row is scoped to application frameworks and libraries. Trivy does compute an end-of-service-life status, but only for OS distributions. Snyk's package-health signal exists on its website, not in the CLI or CI output.

Measured, not asserted

Benchmark: Apache Dubbo 2.7.8

Five scanners, one public 105-module Maven reactor pinned to a commit, two questions. Every number below is recomputable from the tools' own JSON — the commands are in the benchmark doc.

1 · At full capability

Every scanner online, best configuration, populated ~/.m2. Union of all findings: 908 pairs.

ScannerFoundUnique to itMisses
fad-checker790 · 87.0%125118
OSV-Scanner 2.4.0657 · 72.4%0251
Snyk 1.1302.1 (mvn build)603 · 66.4%117305
Trivy 0.72.0546 · 60.1%0362
Grype 0.116.0 + Syft 1.49.045 · 5.0%0863

No tool finds everything, this one included. fad-checker's 118 misses all come from Snyk — 30 under a proprietary identifier no public database carries, and 88 public CVEs that public advisory data declares per release branch, routinely omitting old branches that never got a fix. That is what a hand-curated commercial feed buys, and no aggregation of public sources reproduces it. Trivy and Grype are container/SBOM scanners: a raw source checkout is not the job they are built for.

2 · With no network at all

Same tree, every scanner under unshare -rn — a namespace with no network interface, not just an offline flag. Reference: OSV-Scanner's own online output, 657 pairs.

Scanner, no networkRecovers
fad-checker --offline657 · 100%
Grype + Syft45 · 6.8%
Trivy --offline-scan, cold ~/.m240 · 6.1%
OSV-Scanner --offline37 · 5.6%

100% here means "recovers everything OSV-Scanner finds with network access", not "finds everything that exists" — table 1 is the answer to that. OSV-Scanner returns the identical 37 with and without the namespace: it behaves exactly as documented, its transitive resolution is disabled offline by design.

3 · Every other ecosystem

fad-checker claims ten ecosystems, and benchmarking one of them is not an answer. Same method on five more public projects, findings normalised to (package@version | CVE). Expect parity — that is the point. Outside Maven the transitive graph is already in the lockfile, so no scanner has a structural advantage and none should.

target apache/dubbo 2.7.8 · pinned 0be2a1bb · reads 105 × pom.xml

ScannerPairs
OSV-Scanner657
fad-checker790
communs657
fad seul133
OSV seul0

The one ecosystem where the graph is not in the tree: it must be resolved from the registry. That is why an offline gap exists here and nowhere else.

Equal CVE counts do not make two tools equivalent: on these same projects fad also reported 1 120 outdated dependencies on mastodon, 618 and 2 EOL frameworks on phpMyAdmin, 65 on poetry — questions OSV-Scanner does not attempt. Full per-ecosystem detail, targets and method → BENCHMARK.md.

Why --snyk exists

The benchmark is the argument for it. Snyk contributes 117 findings no other scanner produces, because its database is curated per artifact rather than assembled from public advisories. fad-checker takes snyk test output as an input and merges it — union beats either tool alone, and the merge is one flag.

# merge a Snyk run into the report
fad -s ./proj --snyk

Full method, per-tool configuration, the four bugs this benchmark found in fad-checker, and every caveat → BENCHMARK.md.

Documentation

Everything is documented

Per-flag usage, internals, and the full source — all in the repo.

# read-only full scan (default: all sources on)
fad -s ./proj

# pick ecosystems · go fully offline · skip the Maven Central queries
fad -s . --ecosystem maven,npm,pypi
fad -s . --offline

# write a cleaned POM tree (private deps stripped) for Snyk
fad -s ./proj -t ../pom-clean -e "^client\." --snyk