fad-checker 2.2.2 → 2.2.3

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
@@ -5,7 +5,8 @@
5
5
  [![license](https://img.shields.io/npm/l/fad-checker.svg)](https://github.com/n8tz/fad-checker/blob/main/package.json)
6
6
  [![node](https://img.shields.io/node/v/fad-checker.svg)](https://nodejs.org)
7
7
 
8
- > **F**ucking **A**utonomous **D**ependency **C**hecker
8
+ > **F**abulous **A**utonomous **D**ependency **C**hecker<br>
9
+ > AKA **F**uckin' **A**utonomous **D**ependency **C**hecker<br>
9
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**.
11
12
 
@@ -53,6 +54,7 @@ Exactly **one** runtime dependencies must be on PATH (or installed automatically
53
54
  | **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 |
54
55
  | **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 |
55
56
  | **3. CVE in dev deps** | same | Same as chapter 1, but for `test`/`provided` (Maven) and `dev`/`optional`/`peer` (npm) |
57
+ | **Supply-chain risk** | OSV `MAL-…` + name heuristic | **Known-malicious** packages (always block the CI gate, any `--fail-on` level) and **suspected typosquats** (`--typosquat`: an npm/PyPI name one edit from a popular package — `lodahs`↔`lodash`) |
56
58
  | **4. EOL frameworks** | endoflife.date | Spring Boot 2.5, Hibernate 4.x, EOL JDKs, AngularJS, Laravel/Symfony, Django, .NET, etc. |
57
59
  | **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` |
58
60
  | **6. Outdated libraries** | Maven Central + npm / Packagist / PyPI / NuGet registries | Available newer versions, with release dates |
@@ -102,9 +104,17 @@ fad-checker -s ./proj -t ../proj-clean -e "^com\.acme\." --snyk
102
104
  # Faster: skip Maven Central / no transitive walk
103
105
  fad-checker -s ./proj --no-all-libs --no-transitive
104
106
 
105
- # Fully offline (uses cached data only)
107
+ # Fully offline (uses cached data only) — zero network, guaranteed (see Air-gapped below)
106
108
  fad-checker -s ./proj --offline
107
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
+
108
118
  # License + copyleft-policy chapter (off by default)
109
119
  fad-checker -s ./proj --licenses
110
120
 
@@ -201,6 +211,11 @@ fad-checker --completion zsh > ~/.zsh/completions/_fad-checker
201
211
 
202
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.
203
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
+
204
219
  > Full per-ecosystem and per-stage detail lives in **[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)** and **[`docs/USAGE.md`](docs/USAGE.md)**.
205
220
 
206
221
  ---
@@ -227,6 +242,16 @@ fad-checker --import-cache fad-cache.tar.gz
227
242
 
228
243
  ## Air-gapped / PASSI audits: anonymized dependency descriptor
229
244
 
245
+ > **Zero-data-sent guarantee.** Under `--offline`, fad-checker makes **no network calls
246
+ > whatsoever** — it reads only the warmed `~/.fad-checker/` caches and never transmits a
247
+ > dependency, path or finding off the machine. It is regression-tested
248
+ > (`test/offline-guarantee.test.js`, a tripwire fetcher that throws if touched) and
249
+ > auditor-reproducible: `unshare -rn node fad-checker.js -s ./proj --offline …` runs it in a
250
+ > namespace with **no network interface** and yields byte-identical findings. Unlike the
251
+ > 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*).
254
+
230
255
  When the audited system is **offline / confidential** (typical of a PASSI engagement) it
231
256
  can't reach OSV / NVD / Maven Central / npm. Split the work across machines while keeping
232
257
  **zero environment information** off the secure enclave: an anonymized descriptor carries
@@ -357,6 +382,7 @@ of thing a security consultant or an ANSSI-PASSI engagement needs.
357
382
  | CI gating (`--fail-on`) + triage | ✅ severity/KEV + ignore/VEX | ✅ | ✅ | ✅ | ⚠️ | ✅ |
358
383
  | Auto-remediation / PRs | ❌ (fix recipes only) | ✅ `fix` | ❌ | ❌ | ❌ | ✅ |
359
384
  | Offline | ✅ cache | ✅ local DB | ✅ | ✅ | ✅ feed | ❌ mostly online |
385
+ | Offline Maven **transitive** graph³ | ✅ cached POMs | ❌ disabled offline | ❌ | ❌ | ⚠️ mirror | ❌ |
360
386
  | **Scan without exposing the codebase**² | ✅ anonymized descriptor | ❌ | ❌ | ❌ | ❌ | ❌ |
361
387
  | **Maven private-dep cleanup** (→ Snyk) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
362
388
  | Output | **HTML + Word `.doc`** + JSON / SARIF / CycloneDX / CSAF | table/JSON/SARIF | table/JSON/SARIF | table/JSON/SARIF | HTML/XML/JSON | JSON / cloud UI |
@@ -367,7 +393,12 @@ of thing a security consultant or an ANSSI-PASSI engagement needs.
367
393
  see [Air-gapped / PASSI](#air-gapped--passi-audits-anonymized-dependency-descriptor). OSV-Scanner
368
394
  has an offline mode, but it still needs the **source on the scanning machine**.
369
395
 
370
- **Where it fits:** a one-shot audit of a polyglot checkout you may not be able to build, a
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
371
402
  presentable HTML/Word deliverable, and confidential / air-gapped engagements.
372
403
 
373
404
  **Where it doesn't:** container/OS scanning,
@@ -0,0 +1,39 @@
1
+ {
2
+ "_comment": "Curated list of widely-used npm + PyPI packages used as TYPOSQUAT TARGETS by lib/malware.js#detectTyposquats. A resolved dep whose name is edit-distance 1 from one of these (but isn't it) is flagged as a suspected typosquat/slopsquat. Not exhaustive — focused on the most-impersonated packages. Add names here to widen proactive coverage.",
3
+ "npm": [
4
+ "react", "react-dom", "lodash", "express", "axios", "chalk", "commander", "request",
5
+ "debug", "async", "moment", "underscore", "jquery", "webpack", "babel-core", "vue",
6
+ "angular", "typescript", "eslint", "prettier", "jest", "mocha", "chai", "bluebird",
7
+ "yargs", "glob", "minimist", "colors", "dotenv", "body-parser", "cors", "mongoose",
8
+ "redux", "next", "gatsby", "rxjs", "classnames", "prop-types", "uuid", "bcrypt",
9
+ "jsonwebtoken", "passport", "nodemon", "node-fetch", "cross-env", "rimraf", "fs-extra",
10
+ "semver", "validator", "winston", "morgan", "helmet", "sequelize", "knex", "mysql",
11
+ "redis", "ioredis", "dayjs", "date-fns", "ramda", "immutable", "styled-components",
12
+ "tailwindcss", "postcss", "autoprefixer", "browserify", "rollup", "parcel", "esbuild",
13
+ "husky", "lint-staged", "concurrently", "nanoid", "form-data", "tslib", "core-js",
14
+ "socket.io", "nodemailer", "puppeteer", "playwright", "cheerio", "inquirer", "ora",
15
+ "execa", "chokidar", "ws", "got", "undici", "zod", "yup", "formik", "react-router",
16
+ "react-router-dom", "react-redux", "vuex", "pinia", "svelte", "preact", "ant-design",
17
+ "bootstrap", "jquery-ui", "three", "d3", "chart.js", "leaflet", "highlight.js",
18
+ "marked", "handlebars", "ejs", "pug", "nunjucks", "graphql", "apollo-server",
19
+ "mongodb", "pg", "typeorm", "prisma", "jsdom", "supertest", "sinon", "nyc", "ava",
20
+ "babel-loader", "ts-loader", "css-loader", "style-loader", "html-webpack-plugin",
21
+ "colord"
22
+ ],
23
+ "pypi": [
24
+ "requests", "numpy", "pandas", "flask", "django", "scipy", "matplotlib", "pillow",
25
+ "setuptools", "wheel", "urllib3", "certifi", "pytest", "six", "click", "jinja2",
26
+ "werkzeug", "sqlalchemy", "boto3", "botocore", "pyyaml", "cryptography",
27
+ "beautifulsoup4", "lxml", "scikit-learn", "tensorflow", "keras", "scrapy",
28
+ "celery", "psycopg2", "pymongo", "fastapi", "uvicorn", "pydantic", "aiohttp",
29
+ "httpx", "tqdm", "colorama", "rich", "typer", "python-dateutil", "pytz", "attrs",
30
+ "packaging", "idna", "charset-normalizer", "markupsafe", "openpyxl", "tornado",
31
+ "gunicorn", "redis", "selenium", "paramiko", "fabric", "pyjwt", "passlib", "bcrypt",
32
+ "marshmallow", "flask-sqlalchemy", "flask-cors", "flask-restful", "django-rest-framework",
33
+ "djangorestframework", "gevent", "greenlet", "asgiref", "starlette", "anyio",
34
+ "httpcore", "sniffio", "wrapt", "decorator", "more-itertools", "toml", "tomli",
35
+ "pyparsing", "jsonschema", "protobuf", "grpcio", "boto", "awscli", "google-api-python-client",
36
+ "opencv-python", "imageio", "networkx", "sympy", "statsmodels", "seaborn", "plotly",
37
+ "dash", "streamlit", "jupyter", "ipython", "notebook", "nbconvert", "cython"
38
+ ]
39
+ }