fad-checker 2.2.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,40 +8,44 @@
8
8
  > **F**abulous **A**utonomous **D**ependency **C**hecker<br>
9
9
  > AKA **F**uckin' **A**utonomous **D**ependency **C**hecker<br>
10
10
 
11
- `fad-checker` scans **Maven**, **npm**, **Yarn**, **Composer (PHP)**, **PyPI (Python)**, **NuGet (C#/.NET)**, **Go**, **Ruby**, **vendored JavaScript** and **committed native binaries** in any source tree — multi-module, monorepo, polyglot, whatever you've got — and produces a single self-contained HTML report with CVE (prioritised by **EPSS + CISA KEV**), EOL, obsolete, outdated and **license** findings, plus per-ecosystem fix recipes. It also exports a **CycloneDX 1.6 SBOM** and a **CSAF 2.0 VEX**.
12
-
11
+ `fad-checker` audits **Maven · Gradle · npm · Yarn · pnpm · Composer · PyPI · NuGet · Go · Ruby**, vendored JavaScript and committed native binaries in any source tree — multi-module, monorepo, polyglot — and produces a self-contained **HTML + Word report** (CVE prioritised by EPSS + CISA KEV, EOL, obsolete, outdated, licenses) plus **CycloneDX SBOM / CSAF VEX / SARIF / JSON** exports. **No build tools, no Docker, no network needed** — it reads lockfiles and manifests straight off disk.
13
12
 
14
13
  🌐 **[Project site & docs →](https://n8tz.github.io/fad-checker/)**
15
14
 
16
- <p align="center"><img src="docs/assets/cli.png" alt="fad-checker terminal output — a [n/N] checklist warming each vulnerability database, then CVE findings coloured by severity" height="760"></p>
15
+ <p align="center"><img src="docs/assets/demo.gif" alt="fad-checker animated terminal demo — a [n/N] checklist warming each vulnerability database, then CVE findings coloured by severity with KEV badges" height="600"></p>
17
16
 
18
- It runs against the source files alone. **No `mvn`, no `npm install`, no `composer install`, no `pip`, no `dotnet restore`, no Docker.** It reads `pom.xml`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `composer.lock`, `poetry.lock`/`Pipfile.lock`/`uv.lock`/`pdm.lock`/`pyproject.toml`/`requirements.txt`, and `packages.lock.json`/`*.csproj`/`*.fsproj`/`*.vbproj`/`packages.config` directly.
17
+ ## Features
19
18
 
20
- > **Supported ecosystems: Maven, npm, Yarn (v1 + Berry/v2+), pnpm, Composer, PyPI, NuGet, Go, Ruby + committed native binaries.** Each is a self-contained **codec** (`lib/codecs/`) — adding another is adding a codec, no orchestrator surgery. Vendored JS (jQuery, Bootstrap, PDF.js, etc.) is also scanned via retire.js. **Embedded JARs** committed into the tree — vendored libs, Spring-Boot fat-jars, shaded uber-jars inside `.jar`/`.war`/`.ear` — are unzipped in-memory and their Maven coordinates scanned too (disable with `--no-jars`). **Committed native binaries** (`.dll`/`.exe`/`.so`/`.dylib`) are detected (magic-byte confirmed, so images/assets are never picked up) and **identified by checksum** via deps.dev + CIRCL — to flag tampered/unknown files and libraries that ought to be declared dependencies (disable with `--no-binaries`).
19
+ - **10 ecosystems in one pass** Maven, **Gradle**, npm/Yarn/pnpm, Composer (PHP), PyPI, NuGet, Go, Ruby; plus **vendored JS** (retire.js), committed **native binaries** (`.dll`/`.exe`/`.so`/`.dylib`, identified by checksum via deps.dev + CIRCL) and **embedded JARs** (fat-jars/war/ear, unzipped in-memory).
20
+ - **No build tools** — reads `pom.xml`, `build.gradle(.kts)`/`gradle.lockfile`/`libs.versions.toml`, `package-lock`/`yarn.lock`/`pnpm-lock`, `composer.lock`, `poetry`/`Pipfile`/`uv`/`pdm` locks, `packages.lock.json`/`*.csproj`, `go.mod`, `Gemfile.lock` directly. No `mvn`/`gradle`/`npm install`/`pip`/`dotnet restore`/`go build`/`bundle`, no `node_modules/`. → [how it stays build-free](docs/COMPARISON.md#how-its-autonomous-no-build-tools)
21
+ - **CVE, merged & prioritised** — CVEProject + OSV.dev + NVD, CPE/version cross-checked to cut false positives, ranked **CISA KEV → EPSS → CVSS**.
22
+ - **Per-module Maven version mediation** — recovers vulnerable transitive versions that a global `<dependencyManagement>` pin hides in another module (lifted Snyk-corroborated coverage **156 → 181** on a real 25-module reactor, finding CVEs a single Snyk scan missed).
23
+ - **Air-gapped** — **zero network under `--offline`** (regression-tested), offline Maven transitive resolution, and `--osv-db` for cache-independent offline OSV recall. → [Air-gapped](#air-gapped-audits)
24
+ - **Supply-chain risk** — known-**malicious** advisories (`MAL-`, always block the CI gate) + suspected **typosquats** (`--typosquat`).
25
+ - **Lifecycle** — EOL (endoflife.date), obsolete/deprecated, outdated — across every ecosystem.
26
+ - **Licenses** *(opt-in `--licenses`)* — SPDX-normalised, copyleft/proprietary flagged.
27
+ - **Outputs & CI** — HTML + Word `.doc`, CycloneDX 1.6 SBOM, CSAF 2.0 VEX, SARIF 2.1.0, JSON; gate with `--fail-on`, triage with `--ignore`/`--vex`.
21
28
 
22
- ---
29
+ 📖 **[Usage & all flags](docs/USAGE.md)** · **[Architecture](docs/ARCHITECTURE.md)** · **[Comparison vs other tools](docs/COMPARISON.md)** · **[Data sources](docs/DATA-SOURCES.md)**
23
30
 
24
- ## Why "Autonomous"?
31
+ ## Quick start
25
32
 
26
- Because it doesn't need anything you don't already have on disk:
33
+ ```bash
34
+ npm install -g fad-checker
35
+ fad-checker -s ./my-project # → ./fad-checker-report/cve-report.html
36
+ ```
27
37
 
28
- | You don't need | Why |
29
- | --- | --- |
30
- | Maven installed | `pom.xml` files are parsed directly with xml2js. Properties, profiles and local BOMs are resolved in-process. Transitive deps fetched from Maven Central if `--transitive` (cached forever). |
31
- | `mvn dependency:tree` | Same as above. We walk the tree ourselves. |
32
- | `npm install` / a `node_modules/` | `package-lock.json` (v1/v2/v3), `yarn.lock` (v1 + Berry/v2+) and `pnpm-lock.yaml` (v5/v6/v9) are parsed as text/JSON/YAML. Versions come from the lockfile — no installation. |
33
- | `yarn install` / `pnpm install` | Same. We read `yarn.lock` (v1 + Berry) and `pnpm-lock.yaml` directly. |
34
- | `composer install` | `composer.lock` is parsed directly (concrete versions + transitive). `composer.json` alone → best-effort on pinned versions + warning. |
35
- | `pip` / `poetry` / a venv | `poetry.lock`, `Pipfile.lock`, `uv.lock`, `pdm.lock` are parsed for concrete versions; `pyproject.toml` (PEP 621 + poetry) and `requirements.txt` (following `-r`/`-c` includes) are best-effort on exact pins. Names normalised per PEP 503. |
36
- | `dotnet restore` | `packages.lock.json` is parsed; otherwise `*.csproj`/`*.fsproj`/`*.vbproj` (+ `Directory.Packages.props` Central Package Management) and legacy `packages.config`, best-effort on pinned versions. |
37
- | `go build` / a Go toolchain | `go.mod` is parsed (the full pruned graph on Go ≥1.17, `// indirect` → transitive); `go.sum` is the fallback. No module download. |
38
- | `bundle install` | `Gemfile.lock` is parsed for the resolved gem set. No Ruby, no bundler. |
39
- | `snyk` binary | Built-in CVE matching via CVEProject + OSV + NVD (merged), prioritised with EPSS + CISA KEV (see below). Snyk is *optional* (`--snyk`). |
40
- | A network connection | First run downloads CVE / OSV / EOL data; subsequent runs use cached copies (`--offline` to force). |
38
+ A free [NVD API key](https://nvd.nist.gov/developers/request-an-api-key) (instant) gives 10× faster enrichment: `fad-checker --set-nvd-key YOUR_KEY`. A few common runs — full list via `fad-checker --help` or [docs/USAGE.md](docs/USAGE.md):
41
39
 
42
- Exactly **one** runtime dependencies must be on PATH (or installed automatically through npm): Node ≥ 20. Everything else is bundled or fetched lazily.
40
+ ```bash
41
+ fad-checker -s ./proj -e "^com\.acme\." # exclude private libs (coord regex)
42
+ fad-checker -s ./proj -t ../clean -e "^com\.acme\." --snyk # cleaned POM tree + merge Snyk
43
+ fad-checker -s ./proj --offline # fully offline (zero network)
44
+ fad-checker -s ./proj --osv-db --typosquat # offline-complete OSV + typosquat
45
+ fad-checker -s ./proj --licenses --fail-on high # license chapter + CI gate
46
+ ```
43
47
 
44
- ---
48
+ A single self-contained binary (no Node), from-source install and shell completion are in → [docs/USAGE.md](docs/USAGE.md).
45
49
 
46
50
  ## What it finds
47
51
 
@@ -59,188 +63,13 @@ Exactly **one** runtime dependencies must be on PATH (or installed automatically
59
63
  | **5. Obsolete libraries** | curated list (Maven) + registry maintainer flags | log4j 1.x, jackson-mapper-asl, joda-time, …; npm `deprecated`, Composer `abandoned`, PyPI `yanked`/inactive, NuGet `deprecation` |
60
64
  | **6. Outdated libraries** | Maven Central + npm / Packagist / PyPI / NuGet registries | Available newer versions, with release dates |
61
65
  | **7. Licenses** *(opt-in: `--licenses`)* | registry metadata + Maven POMs → SPDX policy | Each dep's license normalised to SPDX and classified; copyleft (GPL/AGPL/LGPL/MPL), proprietary and unknown flagged for review |
62
- | **8. Fix Recommendations** | computed | Per-ecosystem pin recipes: Maven `<dependencyManagement>`, npm `overrides`, yarn `resolutions`, `composer require`, `pip install`, `dotnet add package` |
66
+ | **8. Fix Recommendations** | computed | Per-ecosystem pin recipes: Maven `<dependencyManagement>`, Gradle `constraints { }`, npm `overrides`, yarn `resolutions`, `composer require`, `pip install`, `dotnet add package` |
63
67
 
64
68
  The HTML report opens in any browser, contains every detail (CVSS vectors, references, full descriptions, CPE configurations, via-paths for transitives) and ships a Word-compatible `.doc` twin. Every match carries a **composite priority** (KEV-exploited > EPSS likelihood > CVSS severity), and the run can additionally emit a **CycloneDX 1.6 SBOM** (`--report-sbom`, vulnerabilities inline) and a **CSAF 2.0 VEX** (`--report-csaf`) for downstream tooling.
65
69
 
66
- ---
67
-
68
- ## Quick start
69
-
70
- ```bash
71
- npm install -g fad-checker
72
- fad-checker -s ./my-project
73
- ```
74
-
75
- That's it. The report lands in `./fad-checker-report/cve-report.html`.
76
-
77
- Want a 10× faster NVD enrichment? [Get a free NVD API key](https://nvd.nist.gov/developers/request-an-api-key) (instant), then:
78
-
79
- ```bash
80
- fad-checker --set-nvd-key YOUR_KEY
81
- ```
82
-
83
- ---
84
-
85
- ## Common runs
86
-
87
- ```bash
88
- # Read-only full scan (default: all sources on)
89
- fad-checker -s ./proj
90
-
91
- # Exclude private/internal libs by groupId/name regex
92
- fad-checker -s ./proj -e "^(com\.acme|org\.private)\."
93
-
94
- # Ignore whole sub-paths during the walk (gitignore-style glob, relative to -s)
95
- fad-checker -s ./proj --exclude-path "packages/legacy/**" --exclude-path "**/fixtures/**"
96
- fad-checker -s ./proj --no-default-excludes # walk everything (incl. node_modules/.git)
97
-
98
- # Also write cleaned POMs (private deps stripped, ready for Snyk)
99
- fad-checker -s ./proj -t ../proj-clean -e "^com\.acme\."
100
-
101
- # Then run Snyk on the cleaned tree and merge findings
102
- fad-checker -s ./proj -t ../proj-clean -e "^com\.acme\." --snyk
103
-
104
- # Faster: skip Maven Central / no transitive walk
105
- fad-checker -s ./proj --no-all-libs --no-transitive
106
-
107
- # Fully offline (uses cached data only) — zero network, guaranteed (see Air-gapped below)
108
- fad-checker -s ./proj --offline
109
-
110
- # Offline-COMPLETE OSV recall (Maven): import the full OSV DB once, then match offline
111
- # regardless of the per-dep cache (the OSV-Scanner air-gap model)
112
- fad-checker -s ./proj --osv-db # online: download (~9 MB) + match
113
- fad-checker -s ./proj --osv-db --offline # offline: match against the imported DB
114
-
115
- # Supply-chain risk: known-malicious packages always flagged; add the typosquat heuristic
116
- fad-checker -s ./proj --typosquat
117
-
118
- # License + copyleft-policy chapter (off by default)
119
- fad-checker -s ./proj --licenses
120
-
121
- # Pick ecosystems — --ecosystem is a list: auto (default) | all | comma list
122
- fad-checker -s ./proj --ecosystem maven # Maven only
123
- fad-checker -s ./proj --ecosystem maven,npm,pypi # several
124
- fad-checker -s ./proj --no-nuget --no-composer # or opt out per codec
125
- fad-checker -s ./proj --no-binaries # skip the native-binary scan
126
-
127
- # Private registry + reusable defaults (see "Configuration file & environment")
128
- fad-checker --add-repo npm verdaccio https://npm.acme.com/ --token "$NPM_TOKEN"
129
- fad-checker --config ./ci/fad-env.json # all options from a JSON file
130
- fad-checker --source ./proj # --source / --src are aliases
131
- ```
132
-
133
- Run `fad-checker --help` for the full flag list.
134
-
135
- ---
136
-
137
- ## What a report looks like
138
-
139
70
  <p align="center"><img src="docs/assets/report.png" alt="fad-checker HTML report — executive summary with severity tiles and a detailed CVE table with CWE, descriptions and fix versions" width="900"></p>
140
71
 
141
- The console prints a summary; the full detail lives in the self-contained HTML/`.doc`:
142
-
143
- ```
144
- ╭───────────────────────────────────────────────────╮
145
- │ fad-checker v2.2.1 · Autonomous Dependency Checker │
146
- ╰───────────────────────────────────────────────────╯
147
- Executive Summary [CRITICAL] — 1708 dependencies scanned
148
- • 81 CVE in production deps (critical=5, high=53, medium=12, low=11)
149
- • 32 CVE in dev/test deps · 17 vulnerable vendored JS (retire.js)
150
- • 2 EOL frameworks · 13 obsolete/deprecated · 172 outdated
151
- • 4 scan-completeness alerts — see chapter 0
152
- ```
153
-
154
- The HTML report organises this into chapters (0 Warnings, 1 CVE prod, 1B embedded JARs,
155
- 1C native binaries, 1D vendored-JS inventory, 2 vendored-JS vulns, 3 dev CVE, 4 EOL,
156
- 5 obsolete, 6 outdated, 7 Licenses *(opt-in)*, 8 Fix Recommendations), each grouped by
157
- ecosystem and manifest. Every CVE row carries: severity badge · CVE/GHSA id · coord &
158
- version · declaring manifest · source(s) · fix-version · priority (KEV/EPSS) — click for
159
- the full panel (CVSS vectors, references, transitive paths, CPE configs).
160
-
161
- ---
162
-
163
- ## Install
164
-
165
- ### As a global CLI
166
-
167
- ```bash
168
- npm install -g fad-checker
169
- ```
170
-
171
- ### From source
172
-
173
- ```bash
174
- git clone <repo-url> fad-checker
175
- cd fad-checker
176
- npm install
177
- node fad-checker.js --help
178
- ```
179
-
180
- ### Single-binary build (no Node required)
181
-
182
- ```bash
183
- npm install # one-time, brings in bun
184
- npm run build # → dist/fad-checker-linux + dist/fad-checker.exe
185
- ```
186
-
187
- ### Shell completion
188
-
189
- ```bash
190
- fad-checker --completion bash > /etc/bash_completion.d/fad-checker
191
- # or for zsh:
192
- fad-checker --completion zsh > ~/.zsh/completions/_fad-checker
193
- ```
194
-
195
- ---
196
-
197
- ## How it scans without any build tool
198
-
199
- **TL;DR** — `fad-checker` never runs your build. For each ecosystem it reads the **lockfile** (or, failing that, the manifest's pinned versions) straight off disk to learn the exact dependency versions, then matches those coordinates against vulnerability/EOL/registry data over the network (cached, `--offline`-able). No `mvn`, `npm install`, `pip`, `dotnet restore`, `go build` or `bundle` — and no `node_modules/`.
200
-
201
- | Ecosystem | Read directly | Transitive versions come from |
202
- | --- | --- | --- |
203
- | Maven | `pom.xml` (+ parents, BOMs, profiles) | child POMs fetched from Maven Central (cached) |
204
- | npm / Yarn / pnpm | `package-lock.json` · `yarn.lock` (v1+Berry) · `pnpm-lock.yaml` | the lockfile itself |
205
- | Composer | `composer.lock` (else `composer.json`) | the lockfile |
206
- | PyPI | `poetry.lock` · `Pipfile.lock` · `uv.lock` · `pdm.lock` (else `pyproject.toml`/`requirements.txt`) | the lockfile |
207
- | NuGet | `packages.lock.json` (else `*.csproj`/`packages.config`) | the lockfile |
208
- | Go | `go.mod` (`// indirect` → transitive; `go.sum` fallback) | the module graph in `go.mod` |
209
- | Ruby | `Gemfile.lock` (`specs:`) | the lockfile |
210
- | Vendored JS / binaries | the committed `.js` / `.jar` / `.so` files themselves | n/a (read in place) |
211
-
212
- Highlights of the matching layer: **three CVE sources merged** (CVEProject + OSV.dev + NVD), **CPE/version cross-check** to drop false positives, **EPSS + CISA KEV** prioritisation, lockfile-first with a **best-effort pinned-version fallback** when no lockfile, in-memory **embedded-JAR** unzip (no disk, no zip-slip), and **checksum identity** for native binaries. Outputs: HTML + `.doc` by default, plus opt-in `--report-sbom`/`-csaf`/`-json`/`-sarif`; CI gating via `--fail-on` with `--ignore`/`--vex` triage.
213
-
214
- Two things set the Maven path apart for multi-module / air-gapped work:
215
-
216
- - **Per-module version mediation** (automatic). The global transitive pass resolves the whole reactor as one tree; that can let a `<dependencyManagement>` pin in one module hide an *older, vulnerable* transitive of the same library in another module. fad re-resolves each module with **only its own** effective depMgmt and recovers those masked versions — on a real 25-module project that lifted Snyk-corroborated coverage **156 → 181**, recovering CVEs (e.g. `poi 3.11` / CVE-2017-12626) that a single Snyk scan of the tree missed.
217
- - **Offline-complete OSV** (`--osv-db`). Imports the full OSV database (Maven) once, then matches every dep against it offline — so air-gapped recall no longer depends on which deps the per-dep OSV cache happened to warm (the [OSV-Scanner](https://github.com/google/osv-scanner) `--download-offline-databases` model). On a cold-cache offline run that's the difference between **6** and **117** of 202 findings covered.
218
-
219
- > Full per-ecosystem and per-stage detail lives in **[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)** and **[`docs/USAGE.md`](docs/USAGE.md)**.
220
-
221
- ---
222
-
223
- ## Caching
224
-
225
- All cached data lives in `~/.fad-checker/` — every source is hit at most once per its
226
- TTL (12 h–7 d, transitive POMs forever as they're immutable). Full per-cache TTL table
227
- in [`docs/USAGE.md`](docs/USAGE.md). Export the lot to share between machines:
228
-
229
- ```bash
230
- fad-checker --export-cache fad-cache.tar.gz
231
- # on the other box:
232
- fad-checker --import-cache fad-cache.tar.gz
233
- ```
234
-
235
- `--include-config` ships the NVD API key too (off by default).
236
-
237
- > The cache export bundles **everything** under `~/.fad-checker/` (except `config.json`),
238
- > including the retire.js findings **and** the warmed retire.js signature DB — so a
239
- > machine that imports it can scan vendored JavaScript fully offline.
240
-
241
- ---
242
-
243
- ## Air-gapped / PASSI audits: anonymized dependency descriptor
72
+ ## Air-gapped audits
244
73
 
245
74
  > **Zero-data-sent guarantee.** Under `--offline`, fad-checker makes **no network calls
246
75
  > whatsoever** — it reads only the warmed `~/.fad-checker/` caches and never transmits a
@@ -249,10 +78,9 @@ fad-checker --import-cache fad-cache.tar.gz
249
78
  > auditor-reproducible: `unshare -rn node fad-checker.js -s ./proj --offline …` runs it in a
250
79
  > namespace with **no network interface** and yields byte-identical findings. Unlike the
251
80
  > mainstream OSS scanners, fad also resolves the **Maven transitive graph** offline — so on
252
- > an air-gapped multi-module project it finds the transitive CVEs they can't (see
253
- > `docs/USAGE.md` → *Zero-data-sent guarantee*).
81
+ > an air-gapped multi-module project it finds the transitive CVEs they can't.
254
82
 
255
- When the audited system is **offline / confidential** (typical of a PASSI engagement) it
83
+ When the audited system is **offline / confidential** (typical of a regulated or air-gapped audit) it
256
84
  can't reach OSV / NVD / Maven Central / npm. Split the work across machines while keeping
257
85
  **zero environment information** off the secure enclave: an anonymized descriptor carries
258
86
  only **public package coordinates** — no filesystem paths, no registry URLs, no
@@ -289,140 +117,16 @@ What the descriptor (`fad-deps/1`) contains vs. drops:
289
117
 
290
118
  The online phase report is itself path-free; vendored-JavaScript (retire.js) findings are
291
119
  produced **offline in phase 3**, since retire needs the actual `.js` files — its signature
292
- DB is warmed online (phase 2) and carried by `--export-cache`.
293
-
294
- ---
295
-
296
- ## Custom repositories & registries
297
-
298
- Register private **Nexus / Artifactory / Verdaccio / devpi / GOPROXY** registries (for **`maven`, `npm`, `pypi`, `ruby`, `go`**) so transitive resolution, outdated/deprecation and license lookups reach them:
299
-
300
- ```bash
301
- fad-checker --add-repo maven nexus https://nexus.acme.com/repository/maven-public/ --auth alice:s3cr3t
302
- fad-checker --add-repo npm verdaccio https://npm.acme.com/ --token "$NPM_TOKEN"
303
- fad-checker -s ./proj --repo npm=https://npm.acme.com/ # one-off, repeatable
304
- ```
305
-
306
- Tried in declared order, public registry last; auth via `--auth user:pass` / `--token TOK` / inline URL; responses cached per coordinate. NuGet/Composer private feeds aren't supported yet. **Full details, the PyPI/Ruby JSON-API caveat and `--list-repos`/`--remove-repo` → [`docs/USAGE.md`](docs/USAGE.md).**
307
-
308
- ---
309
-
310
- ## Configuration file & environment
311
-
312
- Don't retype flags every run. Precedence: **CLI flag > `--config <file.json>` / `./.fad-env.json` (JSON, keys = camelCase options) > `FAD_CHECKER_ENV` (a string of CLI flags) > `~/.fad-checker/config.json` > defaults.** A file/env value only fills an option you didn't pass; **registries are merged across every layer**.
313
-
314
- ```bash
315
- fad-checker --config ./ci/fad-env.json
316
- FAD_CHECKER_ENV='--fail-on high --no-nuget' fad-checker -s ./proj
317
- ```
318
-
319
- `-s` / `--src` / `--source` are aliases. **`-e/--exclude`** is a regex on the **coordinate** (drops deps); **`--exclude-path`** is a gitignore-style glob on the **path** (prunes the walk). Full `.fad-env.json` schema → [`docs/USAGE.md`](docs/USAGE.md).
320
-
321
- ---
322
-
323
- ## Data sources & acknowledgments
324
-
325
- `fad-checker` is glue around several outstanding public datasets. Each is used per its license terms.
326
-
327
- | Source | What we use | License | API / endpoint |
328
- | --- | --- | --- | --- |
329
- | [CVEProject `cvelistV5`](https://github.com/CVEProject/cvelistV5) | Daily bulk CVE bundle, filtered to Maven-relevant entries | CC0-1.0 | GitHub release asset (zip) |
330
- | [OSV.dev](https://osv.dev/) (Google + GitHub Security Lab) | Per-dep vulnerability lookup (Maven, npm, Packagist, PyPI, NuGet, …) | CC-BY 4.0 | `POST api.osv.dev/v1/querybatch`, `GET api.osv.dev/v1/vulns/{id}` |
331
- | [NIST NVD](https://nvd.nist.gov/) | Canonical CVE description + CVSS vectors + CPE configurations + CWE | US-gov public domain | `GET services.nvd.nist.gov/rest/json/cves/2.0?cveId=…` — free [API key](https://nvd.nist.gov/developers/request-an-api-key) bumps the rate limit 10× |
332
- | [FIRST.org EPSS](https://www.first.org/epss/) | Exploit-prediction score + percentile per CVE | CC-BY 4.0 | `GET api.first.org/data/v1/epss?cve=…` (batched) |
333
- | [CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) | Known-exploited-vulnerability catalogue membership | US-gov public domain | `GET cisa.gov/sites/default/files/feeds/known_exploited_vulnerabilities.json` |
334
- | [endoflife.date](https://endoflife.date/) | Framework / runtime EOL cycle data | MIT | `GET endoflife.date/api/{product}.json` |
335
- | [Maven Central](https://search.maven.org/) | Latest-version lookups + transitive POM fetches | Free public service | Solr `search.maven.org/solrsearch/select?q=…` + `repo1.maven.org/maven2/<coord>` |
336
- | [npm registry](https://registry.npmjs.org/) | Per-version `deprecated` + `dist-tags.latest` | Free public service | `GET registry.npmjs.org/<pkg>` |
337
- | [Packagist](https://packagist.org/) | Latest stable + `abandoned` flag | Free public service | `GET packagist.org/packages/<vendor>/<pkg>.json` |
338
- | [PyPI](https://pypi.org/) | Latest + `yanked` + "Inactive" classifier | Free public service | `GET pypi.org/pypi/<pkg>/json` |
339
- | [NuGet](https://www.nuget.org/) | Latest stable + per-version `deprecation` | Free public service | `GET api.nuget.org/v3/registration5-gz-semver2/<id>/index.json` |
340
- | [Go module proxy](https://proxy.golang.org/) | Latest module version (outdated) | Free public service | `GET proxy.golang.org/<module>/@latest` |
341
- | [RubyGems](https://rubygems.org/) | Latest stable + licenses | Free public service | `GET rubygems.org/api/v1/gems/<gem>.json` |
342
- | [deps.dev](https://deps.dev/) | Native-binary identity by checksum (→ package coordinate) | Free public API (CC-BY) | `GET api.deps.dev/v3/query?hash.type=SHA1&hash.value=<base64>` |
343
- | [CIRCL hashlookup](https://hashlookup.circl.lu/) | Known-good file identity (NSRL/distro/CDN) + KnownMalicious | Free public service | `GET hashlookup.circl.lu/lookup/sha256/<hash>` |
344
- | [retire.js](https://retirejs.github.io/retire.js/) | Vendored-JS signature DB + scanner | Apache-2.0 | npm package `retire`, executed locally |
345
- | [Snyk](https://snyk.io/) (optional) | Additional CVE source via `snyk test --all-projects --json` | Per Snyk EULA; needs a Snyk account | Local CLI `snyk` |
346
- | [MITRE CWE](https://cwe.mitre.org/) | Weakness category links in the report | Free public reference | Linked by URL only, no API call |
347
-
348
- Persistent caches mean each source is hit at most once per its TTL (see [Caching](#caching) table). No telemetry, no third-party analytics — every request listed above is made directly to the named endpoint with a `User-Agent: fad-checker-*` header.
349
-
350
- ---
351
-
352
- ## Safety rails
353
-
354
- Built-in guardrails that fire **before** any disk write:
355
-
356
- - `--target` is required unless you're running read-only (no `-t`).
357
- - `--target` may not equal or be a subdirectory of `--src`.
358
- - `--target` is `rimraf`'d before being rewritten — never point it at anything precious.
359
-
360
- ---
361
-
362
- ## Comparison
363
-
364
- `fad-checker` is **not** a Trivy/Grype competitor — those are container-and-SBOM supply-chain
365
- scanners. It targets a narrower job: a **zero-setup, multi-ecosystem audit of a source
366
- checkout, with an audit-ready report and a confidential / air-gapped workflow** — the kind
367
- of thing a security consultant or an ANSSI-PASSI engagement needs.
368
-
369
- | | **fad-checker** | OSV-Scanner | Trivy | Grype + Syft | OWASP DC | Snyk OSS |
370
- | --- | --- | --- | --- | --- | --- | --- |
371
- | Ecosystems it targets¹ | Maven, npm, Yarn, **pnpm**, Composer, PyPI, NuGet, Go, Ruby + vendored JS + **native binaries** | 11+ langs / 19+ lockfiles | 20+ | 20+ | Java/.NET (others exp.) | many |
372
- | Reads lockfiles without `install`/build | ✅ | ✅ | ✅ | ✅ | ⚠️ Java needs Maven Central/build | ❌ build required |
373
- | Best-effort when **no lockfile** (pinned versions) | ✅ | ❌ | ❌ | ❌ | ⚠️ | ⚠️ |
374
- | Vulnerability sources | CVEProject + OSV + NVD + EPSS + KEV + retire.js (+ Snyk), merged | OSV.dev | Aqua DB | Anchore DB | NVD / CPE | Snyk DB |
375
- | False-positive control | CPE/version cross-check | ecosystem-aware | ecosystem-aware | ecosystem-aware | ⚠️ CPE → noisy | ecosystem-aware |
376
- | **EOL** (end-of-life) detection | ✅ endoflife.date | ❌ | ❌ | ❌ | ❌ | ~ |
377
- | **Outdated / deprecated** | ✅ registries + curated | ❌ | ❌ | ❌ | ❌ | ~ |
378
- | Containers / OS packages | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ |
379
- | SBOM (CycloneDX/SPDX) | ✅ CycloneDX 1.6 (+ CSAF 2.0 VEX) | ✅ | ✅ | ✅ (Syft) | ~ | ✅ |
380
- | License compliance | ✅ SPDX + copyleft policy | ~ | ✅ | ~ | ❌ | ✅ |
381
- | EPSS / KEV prioritization | ✅ FIRST.org EPSS + CISA KEV | ~ | ✅ | ✅ | ❌ | ✅ |
382
- | CI gating (`--fail-on`) + triage | ✅ severity/KEV + ignore/VEX | ✅ | ✅ | ✅ | ⚠️ | ✅ |
383
- | Auto-remediation / PRs | ❌ (fix recipes only) | ✅ `fix` | ❌ | ❌ | ❌ | ✅ |
384
- | Offline | ✅ cache | ✅ local DB | ✅ | ✅ | ✅ feed | ❌ mostly online |
385
- | Offline Maven **transitive** graph³ | ✅ cached POMs | ❌ disabled offline | ❌ | ❌ | ⚠️ mirror | ❌ |
386
- | **Scan without exposing the codebase**² | ✅ anonymized descriptor | ❌ | ❌ | ❌ | ❌ | ❌ |
387
- | **Maven private-dep cleanup** (→ Snyk) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
388
- | Output | **HTML + Word `.doc`** + JSON / SARIF / CycloneDX / CSAF | table/JSON/SARIF | table/JSON/SARIF | table/JSON/SARIF | HTML/XML/JSON | JSON / cloud UI |
389
-
390
- ¹ Narrower language coverage — no Rust/Dart/Swift (Go and Ruby are now covered).
391
-
392
- ² Phase 1 exports only public coordinates; the online scan never sees your source tree —
393
- see [Air-gapped / PASSI](#air-gapped--passi-audits-anonymized-dependency-descriptor). OSV-Scanner
394
- has an offline mode, but it still needs the **source on the scanning machine**.
395
-
396
- ³ Measured on a 25-module Spring/JSF project, fully air-gapped: fad covered **181/202**
397
- Snyk-corroborated findings vs OSV-Scanner v2.3.8's **64/202** — **0 on Maven**, because its
398
- transitive resolution is disabled without network. fad resolves the Maven graph from cached
399
- POMs (and `--osv-db` makes its offline OSV recall cache-independent).
400
-
401
- **Where it fits:** a one-shot audit of a polyglot source code, needing a
402
- presentable HTML/Word deliverable, and confidential / air-gapped engagements.
403
-
404
- **Where it doesn't:** container/OS scanning,
405
- reachability analysis, auto-fix PRs — reach for **Trivy** or **Grype + Syft**.
406
-
407
- You don't have to choose — `fad-checker` takes Snyk's results as input (`--snyk`) and merges them.
408
-
409
- > Sources: [OSV-Scanner lockfiles](https://google.github.io/osv-scanner/supported-languages-and-lockfiles/) ·
410
- > [Trivy Java/`pom.xml` (Maven Central, `--offline-scan`)](https://trivy.dev/docs/latest/coverage/language/java/) ·
411
- > [Syft `java-pom-cataloger` (source dirs)](https://github.com/anchore/syft/issues/676) ·
412
- > [OWASP DC needs internet/build for Java](https://jeremylong.github.io/DependencyCheck/data/index.html) ·
413
- > [Snyk requires building the project](https://docs.snyk.io/supported-languages/technical-specifications-and-guidance) ·
414
- > [EOL/outdated "most tools skip" (Aikido)](https://www.aikido.dev/code/outdated-eol-software)
415
-
416
- ---
120
+ DB is warmed online (phase 2) and carried by `--export-cache`. Full offline/cache control →
121
+ [`docs/USAGE.md`](docs/USAGE.md).
417
122
 
418
123
  ## Docs
419
124
 
420
- - [`docs/USAGE.md`](docs/USAGE.md) — every flag, every workflow, examples.
125
+ - [`docs/USAGE.md`](docs/USAGE.md) — every flag and workflow: offline/cache control, private registries, config files, recipes, safety rails.
421
126
  - [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — internals: codecs, collection, matching, report pipeline.
422
- - [`CHANGELOG.md`](CHANGELOG.md) — release history.
423
- - [`CLAUDE.md`](CLAUDE.md) — code-level orientation for contributors.
424
-
425
- ---
127
+ - [`docs/COMPARISON.md`](docs/COMPARISON.md) — vs OSV-Scanner / Trivy / Grype / OWASP DC / Snyk, and how it stays build-free.
128
+ - [`docs/DATA-SOURCES.md`](docs/DATA-SOURCES.md) — the public datasets fad-checker uses + their licenses.
129
+ - [`CHANGELOG.md`](CHANGELOG.md) · [`CLAUDE.md`](CLAUDE.md) — release history · code-level orientation for contributors.
426
130
 
427
131
  ## License
428
132