fad-checker 2.1.2 → 2.2.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/CHANGELOG.md +37 -0
- package/README.md +93 -20
- package/fad-checker.js +164 -45
- package/lib/codecs/binary/scan.js +71 -0
- package/lib/codecs/binary/sniff.js +37 -0
- package/lib/codecs/binary.codec.js +54 -0
- package/lib/codecs/composer.codec.js +7 -3
- package/lib/codecs/go/registry.js +19 -11
- package/lib/codecs/go.codec.js +7 -3
- package/lib/codecs/index.js +9 -4
- package/lib/codecs/maven/jar-scan.js +8 -3
- package/lib/codecs/maven.codec.js +4 -2
- package/lib/codecs/npm/parse.js +5 -2
- package/lib/codecs/npm/registry.js +29 -18
- package/lib/codecs/npm.codec.js +7 -5
- package/lib/codecs/nuget.codec.js +7 -3
- package/lib/codecs/pypi/registry.js +16 -10
- package/lib/codecs/pypi.codec.js +7 -3
- package/lib/codecs/recipes.js +9 -1
- package/lib/codecs/ruby/registry.js +16 -10
- package/lib/codecs/ruby.codec.js +7 -3
- package/lib/config.js +34 -23
- package/lib/core.js +9 -5
- package/lib/cve-match.js +3 -2
- package/lib/cve-report.js +56 -5
- package/lib/dep-record.js +12 -9
- package/lib/hash-id.js +78 -0
- package/lib/json-export.js +8 -1
- package/lib/options-env.js +113 -0
- package/lib/parallel-walk.js +5 -2
- package/lib/path-filter.js +58 -0
- package/lib/registries.js +112 -0
- package/lib/retire.js +66 -0
- package/lib/scan-completeness.js +7 -1
- package/lib/unmanaged.js +82 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,43 @@
|
|
|
3
3
|
All notable changes to `fad-checker` are documented here.
|
|
4
4
|
This project adheres to [Semantic Versioning](https://semver.org/).
|
|
5
5
|
|
|
6
|
+
## [Unreleased]
|
|
7
|
+
|
|
8
|
+
### Added
|
|
9
|
+
- **Custom registries for npm, PyPI, Ruby and Go** (previously Maven-only). Point
|
|
10
|
+
fad-checker at private Verdaccio/Artifactory/GitHub Packages (npm), devpi (PyPI),
|
|
11
|
+
Gemfury/Geminabox (Ruby) or a private GOPROXY/Athens (Go). They are tried in
|
|
12
|
+
declared order, the public registry last; auth via `--auth user:pass` (→ Basic)
|
|
13
|
+
or `--token TOK` (→ Bearer), inline `https://user:pass@host/` also accepted.
|
|
14
|
+
CRUD: `--add-repo <eco> <name> <url>`, `--remove-repo <eco> <name>`,
|
|
15
|
+
`--list-repos` (grouped by ecosystem); one-off repeatable `--repo <eco>=<url>`.
|
|
16
|
+
New `lib/registries.js`; per-codec fetchers honour `opts.registries`.
|
|
17
|
+
- **Layered configuration.** Defaults can come from a JSON config file
|
|
18
|
+
(`--config <file.json>`, else auto-discovered `./.fad-env.json`) and from the
|
|
19
|
+
`FAD_CHECKER_ENV` environment variable (a string of CLI flags). Precedence:
|
|
20
|
+
**CLI flag > config file > `FAD_CHECKER_ENV` > `~/.fad-checker/config.json` >
|
|
21
|
+
defaults**; `registries` are unioned across every layer. New `lib/options-env.js`.
|
|
22
|
+
- **`--source` alias** for `-s`/`--src` (and the JSON config key `"source"`/`"src"`).
|
|
23
|
+
- **Vendored-JS inventory (report chapter 1D + JSON `vendoredJs`).** retire.js now
|
|
24
|
+
runs with `--verbose`, so fad lists **every** identified standalone JS library
|
|
25
|
+
committed into the tree (jQuery, Bootstrap, PDF.js, …) — **vulnerable or not** —
|
|
26
|
+
as a cyber-hygiene inventory of unmanaged third-party code (the JS twin of the
|
|
27
|
+
native-binary chapter 1C). Each entry: component, version, file, detection
|
|
28
|
+
method, and vulnerability status. Vulnerable libs remain detailed in chapter 2.
|
|
29
|
+
On by default; `--no-vendored-js-inventory` keeps only the vulnerable findings.
|
|
30
|
+
- **`--exclude-path <glob...>`** — ignore sub-paths during the directory walk,
|
|
31
|
+
gitignore-style (matched relative to `--src`, prunes the dir + its subtree),
|
|
32
|
+
across every ecosystem. Repeatable; also `excludePath: [...]` in `.fad-env.json`,
|
|
33
|
+
unioned across config layers. **`--no-default-excludes`** walks the normally
|
|
34
|
+
pruned dirs (`node_modules`, `vendor`, `target`, `.git`, …). New `lib/path-filter.js`.
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
- **BREAKING:** the persisted-registry store moved from the Maven-only
|
|
38
|
+
`maven_repos` config key + 2-arg `--add-repo <name> <url>` to a per-ecosystem
|
|
39
|
+
`registries` map + `--add-repo <ecosystem> <name> <url>`. `--repo` now requires
|
|
40
|
+
the `<ecosystem>=<url>` form (a bare URL is rejected). Re-add any private Maven
|
|
41
|
+
repos with `--add-repo maven <name> <url>`.
|
|
42
|
+
|
|
6
43
|
## [2.1.0]
|
|
7
44
|
|
|
8
45
|
### Added
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
> **F**ucking **A**utonomous **D**ependency **C**hecker
|
|
9
9
|
|
|
10
|
-
`fad-checker` scans **Maven**, **npm**, **Yarn**, **Composer (PHP)**, **PyPI (Python)**, **NuGet (C#/.NET)**, **Go**, **Ruby** and **
|
|
10
|
+
`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**.
|
|
11
11
|
|
|
12
12
|
🌐 **[Project site & docs →](https://n8tz.github.io/fad-checker/)**
|
|
13
13
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
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
17
|
|
|
18
|
-
> **Supported ecosystems: Maven, npm, Yarn (v1 + Berry/v2+), pnpm, Composer, PyPI, NuGet, Go, Ruby.** 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`).
|
|
18
|
+
> **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
19
|
|
|
20
20
|
---
|
|
21
21
|
|
|
@@ -48,8 +48,10 @@ Exactly **one** runtime dependencies must be on PATH (or installed automatically
|
|
|
48
48
|
| **0. Warnings** | local heuristics | Missing lockfiles, unresolved Maven versions (BOM-managed), private libs not on Maven Central |
|
|
49
49
|
| **1. CVE (production)** | CVEProject + OSV.dev + NVD + CPE | Public CVE / GHSA in production deps, per ecosystem, per manifest file — each row **prioritised** by CISA KEV + EPSS + CVSS |
|
|
50
50
|
| **1B. Embedded binaries** | same, on coords read from archives | CVEs in libraries **shipped inside committed `.jar`/`.war`/`.ear`** (vendored libs, Spring-Boot fat-jars, shaded uber-jars) — not declared in any `pom.xml`. Grouped by containing archive |
|
|
51
|
-
| **
|
|
52
|
-
| **
|
|
51
|
+
| **1C. Unmanaged / vendored binaries** | deps.dev + CIRCL (by checksum) | Committed **native binaries** (`.dll`/`.exe`/`.so`/`.dylib`) no package manager governs — identified by hash, flagged **should-be-managed** (exists in a registry), **name≠checksum** (filename disagrees with the hash), **unknown** (no source knows it) or **malicious** (free CIRCL signal) |
|
|
52
|
+
| **1D. Unmanaged / vendored JavaScript** | [retire.js](https://retirejs.github.io/) (`--verbose`) | **Inventory of every standalone JS lib** committed into the tree (jQuery, Bootstrap, PDF.js, …) that no package manager governs — vulnerable *or not*. A cyber-hygiene constat: unknown provenance/integrity/patch story. `--no-vendored-js-inventory` to skip |
|
|
53
|
+
| **2. Vendored JS (vulnerable)** | [retire.js](https://retirejs.github.io/) | The subset of the above with known CVEs/advisories — old jQuery/Bootstrap/Angular/PDF.js copies with no lockfile |
|
|
54
|
+
| **3. CVE in dev deps** | same | Same as chapter 1, but for `test`/`provided` (Maven) and `dev`/`optional`/`peer` (npm) |
|
|
53
55
|
| **4. EOL frameworks** | endoflife.date | Spring Boot 2.5, Hibernate 4.x, EOL JDKs, AngularJS, Laravel/Symfony, Django, .NET, etc. |
|
|
54
56
|
| **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` |
|
|
55
57
|
| **6. Outdated libraries** | Maven Central + npm / Packagist / PyPI / NuGet registries | Available newer versions, with release dates |
|
|
@@ -83,9 +85,13 @@ fad-checker --set-nvd-key YOUR_KEY
|
|
|
83
85
|
# Read-only full scan (default: all sources on)
|
|
84
86
|
fad-checker -s ./proj
|
|
85
87
|
|
|
86
|
-
# Exclude private/internal libs by groupId regex
|
|
88
|
+
# Exclude private/internal libs by groupId/name regex
|
|
87
89
|
fad-checker -s ./proj -e "^(com\.acme|org\.private)\."
|
|
88
90
|
|
|
91
|
+
# Ignore whole sub-paths during the walk (gitignore-style glob, relative to -s)
|
|
92
|
+
fad-checker -s ./proj --exclude-path "packages/legacy/**" --exclude-path "**/fixtures/**"
|
|
93
|
+
fad-checker -s ./proj --no-default-excludes # walk everything (incl. node_modules/.git)
|
|
94
|
+
|
|
89
95
|
# Also write cleaned POMs (private deps stripped, ready for Snyk)
|
|
90
96
|
fad-checker -s ./proj -t ../proj-clean -e "^com\.acme\."
|
|
91
97
|
|
|
@@ -102,6 +108,12 @@ fad-checker -s ./proj --offline
|
|
|
102
108
|
fad-checker -s ./proj --ecosystem maven # Maven only
|
|
103
109
|
fad-checker -s ./proj --ecosystem maven,npm,pypi # several
|
|
104
110
|
fad-checker -s ./proj --no-nuget --no-composer # or opt out per codec
|
|
111
|
+
fad-checker -s ./proj --no-binaries # skip the native-binary scan
|
|
112
|
+
|
|
113
|
+
# Private registry + reusable defaults (see "Configuration file & environment")
|
|
114
|
+
fad-checker --add-repo npm verdaccio https://npm.acme.com/ --token "$NPM_TOKEN"
|
|
115
|
+
fad-checker --config ./ci/fad-env.json # all options from a JSON file
|
|
116
|
+
fad-checker --source ./proj # --source / --src are aliases
|
|
105
117
|
```
|
|
106
118
|
|
|
107
119
|
Run `fad-checker --help` for the full flag list.
|
|
@@ -184,7 +196,20 @@ fad-checker --completion zsh > ~/.zsh/completions/_fad-checker
|
|
|
184
196
|
|
|
185
197
|
## How it scans without any build tool
|
|
186
198
|
|
|
187
|
-
|
|
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
|
+
The rest of this section is the detail behind that table.
|
|
188
213
|
|
|
189
214
|
- **Maven** — `pom.xml` files are parsed with xml2js. Property substitution (`${jackson.version}`), parent inheritance, local BOM imports (`<scope>import</scope>`) and every profile are resolved in-process. Transitive deps are walked by fetching child POMs from Maven Central (cached forever — POMs are immutable). When the project uses an **external BOM** (`spring-boot-dependencies` etc.), the deps whose version comes from that BOM can't be resolved without `mvn` itself — those are surfaced in chapter 0 as "unresolved-versions" so you know what's missing.
|
|
190
215
|
- **npm / Yarn / pnpm** — `package-lock.json` (v1, v2, v3), `yarn.lock` (v1 + Berry/v2+, via `js-yaml`) and `pnpm-lock.yaml` (v5/v6/v9, via `js-yaml`) are parsed directly. Lockfiles already contain every transitive version. No `node_modules/` traversal, no `npm install`.
|
|
@@ -194,8 +219,9 @@ This is the surprising bit. The whole point is that you can run `fad-checker` ag
|
|
|
194
219
|
- **Go** — `go.mod` `require` entries are the selected versions (full pruned graph on Go ≥1.17; `// indirect` → transitive), `go.sum` as fallback. OSV "Go" ecosystem for recall, the Go module proxy for outdated.
|
|
195
220
|
- **Ruby** — `Gemfile.lock` `specs:` give the resolved gem set. OSV "RubyGems" for recall, the RubyGems API for outdated + licenses.
|
|
196
221
|
- **Lockfile-first, best-effort fallback** — when a lockfile is present it wins. When it's absent, the loose manifest (`package.json` / `composer.json` / `pyproject.toml` / `requirements.txt` / `*.csproj`) is still parsed for its **pinned exact versions**, with ranges skipped and a `no-lockfile` warning in chapter 0 flagging the partial coverage.
|
|
197
|
-
- **Vendored JavaScript** — `retire.js` shells out and scans `.js` / `.min.js` files by signature
|
|
222
|
+
- **Vendored JavaScript** — `retire.js` shells out (with `--verbose`) and scans `.js` / `.min.js` files by signature. Two outputs: a full **inventory of every identified standalone lib** — jQuery, Bootstrap, Angular, PDF.js copies that no lockfile knows about, *vulnerable or not* (chapter 1D, a cyber-hygiene constat on unmanaged third-party code; `--no-vendored-js-inventory` to skip) — and the **vulnerable subset** with its CVEs/advisories (chapter 2).
|
|
198
223
|
- **Embedded JARs** — committed `.jar` / `.war` / `.ear` archives are unzipped **in memory** (via `fflate` — nested fat-jar libs are recursed without ever touching disk, so there's no zip-slip risk) and each artifact's Maven coordinate is read from `META-INF/maven/.../pom.properties` (authoritative), then `MANIFEST.MF`, then the file name. Those coordinates run through the same CVE/OSV/NVD matching as declared deps but report in their own **Embedded binaries** chapter, grouped by containing archive. An archive whose coordinate can't be resolved is flagged in chapter 0 rather than scanned blindly. Auto when archives are present; disable with `--no-jars`. (Embedded coords don't trigger Maven Central transitive resolution — a fat-jar already ships its dependencies, which the recursion finds directly.)
|
|
224
|
+
- **Committed native binaries** — `.dll` / `.exe` / `.so` / `.dylib` files are found by a magic-byte-confirmed walk (extension **and** PE/ELF/Mach-O signature must agree, so an image renamed `.so` or any asset is rejected), hashed (SHA-1 + SHA-256), then **identified by checksum** online: **deps.dev** query-by-hash returns the exact package coordinate (so the file is byte-identical to a published artifact → *pristine*, and ought to be a declared dependency), and **CIRCL hashlookup** recognises known OS/distro/CDN/NSRL files (→ *known-good*) plus a free `KnownMalicious` flag. Files no source knows are flagged *unknown*; a filename that disagrees with the resolved identity is flagged *name≠checksum*. Reported in their own **Unmanaged / vendored binaries** chapter (1C) and the JSON export. Cached + `--offline`-aware; disable with `--no-binaries`. No malware/AV lane and no binary-metadata parsing — identity is hash-lookup, integrity is hash-comparison.
|
|
199
225
|
- **CVE data** — three independent sources merged:
|
|
200
226
|
- **CVEProject** (the canonical `cvelistV5` bundle, filtered to Maven-relevant entries)
|
|
201
227
|
- **OSV.dev** (Google + GitHub Security Lab, multi-ecosystem)
|
|
@@ -222,6 +248,7 @@ All cached data lives in `~/.fad-checker/`:
|
|
|
222
248
|
| CISA KEV catalogue | `kev-cache.json` | 24 h |
|
|
223
249
|
| Go module proxy (latest) | `go-proxy-cache.json` | 24 h |
|
|
224
250
|
| RubyGems (latest + licenses) | `rubygems-cache.json` | 24 h |
|
|
251
|
+
| Binary identity (deps.dev + CIRCL by hash) | `hash-id-cache.json` | 24 h |
|
|
225
252
|
| endoflife.date cycles | `eol-cache.json` | 7 d |
|
|
226
253
|
| Maven Central latest versions | `version-cache.json` | 24 h |
|
|
227
254
|
| Transitive POMs from Maven Central | `poms-cache/<g>__<a>__<v>.pom` | ∞ (immutable) |
|
|
@@ -288,24 +315,68 @@ DB is warmed online (phase 2) and carried by `--export-cache`.
|
|
|
288
315
|
|
|
289
316
|
---
|
|
290
317
|
|
|
291
|
-
## Custom
|
|
318
|
+
## Custom repositories & registries
|
|
292
319
|
|
|
293
|
-
Out of the box `fad-checker` queries Maven Central
|
|
320
|
+
Out of the box `fad-checker` queries each ecosystem's **public** registry (Maven Central, registry.npmjs.org, PyPI, RubyGems, the Go module proxy). If your project pulls artifacts from a private **Nexus / Artifactory / JBoss** (Maven), **Verdaccio / GitHub Packages** (npm), **devpi / Artifactory** (PyPI), **Gemfury / Geminabox** (Ruby) or a private **GOPROXY / Athens** (Go), register them so transitive resolution, outdated checks, deprecation and license lookups work end-to-end.
|
|
321
|
+
|
|
322
|
+
Custom registries for **`maven`, `npm`, `pypi`, `ruby`, `go`**:
|
|
294
323
|
|
|
295
324
|
```bash
|
|
296
|
-
# Persist a
|
|
297
|
-
fad-checker --add-repo nexus
|
|
298
|
-
fad-checker --add-repo
|
|
299
|
-
fad-checker --
|
|
300
|
-
fad-checker --
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
325
|
+
# Persist a registry (lives in ~/.fad-checker/config.json, keyed by ecosystem)
|
|
326
|
+
fad-checker --add-repo maven nexus https://nexus.acme.com/repository/maven-public/ --auth alice:s3cr3t
|
|
327
|
+
fad-checker --add-repo npm verdaccio https://npm.acme.com/ --token "$NPM_TOKEN"
|
|
328
|
+
fad-checker --add-repo pypi devpi https://pypi.acme.com/root/pypi/+simple/ --auth alice:s3cr3t
|
|
329
|
+
fad-checker --list-repos # grouped by ecosystem
|
|
330
|
+
fad-checker --remove-repo npm verdaccio
|
|
331
|
+
|
|
332
|
+
# One-off (not persisted) — repeatable, always ecosystem-scoped as <eco>=<url>
|
|
333
|
+
fad-checker -s ./proj --repo npm=https://npm.acme.com/ --repo maven=https://nexus.acme.com/repository/maven-public/
|
|
304
334
|
# Inline auth in the URL also works:
|
|
305
|
-
fad-checker -s ./proj --repo https://alice:s3cr3t@nexus.acme.com/repository/maven-public/
|
|
335
|
+
fad-checker -s ./proj --repo maven=https://alice:s3cr3t@nexus.acme.com/repository/maven-public/
|
|
306
336
|
```
|
|
307
337
|
|
|
308
|
-
|
|
338
|
+
Registries are tried **in declared order, the public registry last**. Auth is `--auth user:pass` → `Basic <base64>` or `--token TOK` → `Bearer TOK` (inline `https://user:pass@host/` also works). Responses are cached per coordinate, so subsequent runs are free even against a private registry.
|
|
339
|
+
|
|
340
|
+
> **PyPI / Ruby caveat:** the custom base must expose the **same JSON API** as the public one (`<base>/<pkg>/json`, `<base>/<gem>.json`). A pure PEP 503 *simple-index* mirror that only lists files won't yield latest/yanked/license metadata — point at the JSON-capable endpoint (Artifactory/devpi/Nexus all have one). **NuGet** and **Composer** private feeds aren't supported yet (their service-index / `packages.json` discovery is a separate follow-up).
|
|
341
|
+
|
|
342
|
+
---
|
|
343
|
+
|
|
344
|
+
## Configuration file & environment
|
|
345
|
+
|
|
346
|
+
Don't retype flags every run. `fad-checker` reads defaults from three places, **lowest priority first**, all overridable on the command line:
|
|
347
|
+
|
|
348
|
+
| Layer | Where | Format |
|
|
349
|
+
| --- | --- | --- |
|
|
350
|
+
| **CLI flags** | the command line | flags (always win) |
|
|
351
|
+
| **Config file** | `--config <file.json>`, else `./.fad-env.json` | **JSON** object, keys = option names |
|
|
352
|
+
| **`FAD_CHECKER_ENV`** | environment variable | a **string of CLI flags** (what you'd type) |
|
|
353
|
+
| **Global config** | `~/.fad-checker/config.json` | persisted NVD key + `registries` |
|
|
354
|
+
|
|
355
|
+
Effective precedence: **CLI flag > config file > `FAD_CHECKER_ENV` > global config > built-in defaults.** A file/env value only fills an option you did *not* pass on the CLI; **registries are merged (unioned) across every layer**, never overridden.
|
|
356
|
+
|
|
357
|
+
```jsonc
|
|
358
|
+
// ./.fad-env.json — JSON, keys mirror the CLI options (camelCase)
|
|
359
|
+
{
|
|
360
|
+
"source": "./my-project", // alias of --src (so is "src")
|
|
361
|
+
"exclude": "^(com\\.acme|client)\\.",
|
|
362
|
+
"excludePath": ["packages/legacy/**", "**/fixtures/**"],
|
|
363
|
+
"failOn": "high",
|
|
364
|
+
"noNuget": true,
|
|
365
|
+
"registries": {
|
|
366
|
+
"npm": [{ "name": "verdaccio", "url": "https://npm.acme.com/", "token": "…" }],
|
|
367
|
+
"maven":[{ "name": "nexus", "url": "https://nexus.acme.com/repository/maven-public/", "auth": "user:pass" }]
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
fad-checker --config ./ci/fad-env.json # explicit file (beats ./.fad-env.json)
|
|
374
|
+
FAD_CHECKER_ENV='--fail-on high --no-nuget --repo npm=https://npm.acme.com/' fad-checker -s ./proj
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
The **source directory** accepts three spellings everywhere: `-s`, `--src`, `--source` (and the JSON key `"source"`/`"src"`).
|
|
378
|
+
|
|
379
|
+
> **`-e/--exclude` vs `--exclude-path`:** `--exclude` is a regex on the **coordinate** (groupId/name) — it drops matching *dependencies*. `--exclude-path` is a gitignore-style glob on the **directory path** (relative to `--src`) — it prunes the *walk* so nothing under it is read. They compose. `--exclude-path` is repeatable, unioned across config layers, and `--no-default-excludes` lets you walk the normally-pruned dirs (`node_modules`, `vendor`, `target`, `.git`, …).
|
|
309
380
|
|
|
310
381
|
---
|
|
311
382
|
|
|
@@ -328,6 +399,8 @@ Repos are tried **in declared order, Maven Central last**. Auth is sent as a `Ba
|
|
|
328
399
|
| [NuGet](https://www.nuget.org/) | Latest stable + per-version `deprecation` | Free public service | `GET api.nuget.org/v3/registration5-gz-semver2/<id>/index.json` |
|
|
329
400
|
| [Go module proxy](https://proxy.golang.org/) | Latest module version (outdated) | Free public service | `GET proxy.golang.org/<module>/@latest` |
|
|
330
401
|
| [RubyGems](https://rubygems.org/) | Latest stable + licenses | Free public service | `GET rubygems.org/api/v1/gems/<gem>.json` |
|
|
402
|
+
| [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>` |
|
|
403
|
+
| [CIRCL hashlookup](https://hashlookup.circl.lu/) | Known-good file identity (NSRL/distro/CDN) + KnownMalicious | Free public service | `GET hashlookup.circl.lu/lookup/sha256/<hash>` |
|
|
331
404
|
| [retire.js](https://retirejs.github.io/retire.js/) | Vendored-JS signature DB + scanner | Apache-2.0 | npm package `retire`, executed locally |
|
|
332
405
|
| [Snyk](https://snyk.io/) (optional) | Additional CVE source via `snyk test --all-projects --json` | Per Snyk EULA; needs a Snyk account | Local CLI `snyk` |
|
|
333
406
|
| [MITRE CWE](https://cwe.mitre.org/) | Weakness category links in the report | Free public reference | Linked by URL only, no API call |
|
|
@@ -355,7 +428,7 @@ of thing a security consultant or an ANSSI-PASSI engagement needs.
|
|
|
355
428
|
|
|
356
429
|
| | **fad-checker** | OSV-Scanner | Trivy | Grype + Syft | OWASP DC | Snyk OSS |
|
|
357
430
|
| --- | --- | --- | --- | --- | --- | --- |
|
|
358
|
-
| Ecosystems it targets¹ | Maven, npm, Yarn, **pnpm**, Composer, PyPI, NuGet, Go, Ruby + vendored JS | 11+ langs / 19+ lockfiles | 20+ | 20+ | Java/.NET (others exp.) | many |
|
|
431
|
+
| 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 |
|
|
359
432
|
| Reads lockfiles without `install`/build | ✅ | ✅ | ✅ | ✅ | ⚠️ Java needs Maven Central/build | ❌ build required |
|
|
360
433
|
| Best-effort when **no lockfile** (pinned versions) | ✅ | ❌ | ❌ | ❌ | ⚠️ | ⚠️ |
|
|
361
434
|
| Vulnerability sources | CVEProject + OSV + NVD + EPSS + KEV + retire.js (+ Snyk), merged | OSV.dev | Aqua DB | Anchore DB | NVD / CPE | Snyk DB |
|