fad-checker 2.3.0 → 2.3.1

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
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/fad-checker.svg)](https://www.npmjs.com/package/fad-checker)
4
4
  [![npm downloads](https://img.shields.io/npm/dm/fad-checker.svg)](https://www.npmjs.com/package/fad-checker)
5
- [![license](https://img.shields.io/npm/l/fad-checker.svg)](https://github.com/n8tz/fad-checker/blob/main/package.json)
5
+ [![license](https://img.shields.io/npm/l/fad-checker.svg)](https://github.com/9pings/fad-checker/blob/main/package.json)
6
6
  [![node](https://img.shields.io/node/v/fad-checker.svg)](https://nodejs.org)
7
7
 
8
8
  > **F**abulous **A**utonomous **D**ependency **C**hecker<br>
@@ -10,7 +10,10 @@
10
10
 
11
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.
12
12
 
13
- 🌐 **[Project site & docs →](https://n8tz.github.io/fad-checker/)**
13
+ 🌐 **[Project site & docs →](https://9pings.github.io/fad-checker/)**
14
+
15
+ > [!WARNING]
16
+ > **Young project — expect rough edges.** fad-checker is new and under active development, so it may still contain bugs (including false positives and false negatives). Treat its output as a strong first pass, **double-check anything critical**, and please [report issues](https://github.com/9pings/fad-checker/issues) — they get fixed fast.
14
17
 
15
18
  <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>
16
19
 
@@ -129,7 +129,7 @@ module.exports = {
129
129
  const lockGoverned = lockedDirs.has(d) && !inBuildSrc(fp);
130
130
  if (lockGoverned) continue; // lockfile already provided resolved deps for this dir
131
131
  for (const dep of r.deps) addRec(dep, fp);
132
- if (!inBuildSrc(fp)) warnings.push({ type: "gradle-no-lockfile", manifestPath: fp, message: `no gradle.lockfile next to ${path.relative(dir, fp) || path.basename(fp)} — versions resolved best-effort from the build script + version catalog (dynamic/programmatic deps may be missed). Enable Gradle dependency locking for exact coverage.` });
132
+ if (!inBuildSrc(fp)) warnings.push({ type: "no-lockfile", manifestPath: fp, message: `no gradle.lockfile next to ${path.relative(dir, fp) || path.basename(fp)} — versions resolved best-effort from the build script + version catalog (dynamic/programmatic deps may be missed). Enable Gradle dependency locking for exact coverage.` });
133
133
  for (const u of r.unresolved) warnings.push({ type: "unresolved-versions", manifestPath: fp, message: `could not resolve the version variable for ${u.group}:${u.name} (${u.raw}) — excluded from CVE matching` });
134
134
  }
135
135
 
package/lib/cve-report.js CHANGED
@@ -1188,7 +1188,7 @@ function minorSection(title, contentHtml, opts = {}) {
1188
1188
  }
1189
1189
 
1190
1190
  const WARNING_HEADINGS = {
1191
- "no-lockfile": { icon: "⚠️", title: "JS manifest without lockfile" },
1191
+ "no-lockfile": { icon: "⚠️", title: "Manifest without a lockfile — best-effort (ranges skipped)" },
1192
1192
  "yarn-berry-unsupported": { icon: "⚠️", title: "Yarn 2+/Berry lockfile" },
1193
1193
  "unresolved-versions": { icon: "⚠️", title: "Maven deps without a concrete version — silently skipped, run a real Maven/Snyk scan to complete" },
1194
1194
  "private-libs": { icon: "🔒", title: "Private / internal libraries — not on Maven Central, not scanned" },
package/lib/osv.js CHANGED
@@ -121,18 +121,32 @@ function severityFromOsv(vuln) {
121
121
 
122
122
  function scoreFromVuln(vuln) { return cvssInfoFromVuln(vuln).score; }
123
123
 
124
- /** Extract the first fix version from OSV affected ranges (semver/ecosystem events). */
125
- function fixVersionFromOsv(vuln, depKey) {
124
+ /**
125
+ * Pick the fix version to recommend from OSV's affected ranges. A multi-branch advisory
126
+ * (e.g. Tomcat fixed in 9.0.118, 10.1.55 AND 11.0.22) lists one `fixed` per branch — the
127
+ * old code returned the FIRST, which for an 11.0.21 dep meant "upgrade to 9.0.118", i.e. a
128
+ * DOWNGRADE. Instead pick the smallest fix strictly ABOVE the current version: that's the
129
+ * next patched release on the dep's own branch. If none is greater (the branch has no
130
+ * published fix, or the dep is already patched), return null rather than suggest a downgrade.
131
+ */
132
+ function fixVersionFromOsv(vuln, depKey, depVersion) {
133
+ const { compareMavenVersions } = require("./maven-version");
134
+ const fixes = [];
126
135
  for (const a of vuln.affected || []) {
127
136
  const name = a.package?.name?.toLowerCase();
128
137
  if (name && name !== depKey.toLowerCase()) continue;
129
138
  for (const r of a.ranges || []) {
130
139
  for (const ev of r.events || []) {
131
- if (ev.fixed) return ev.fixed;
140
+ if (ev.fixed) fixes.push(String(ev.fixed));
132
141
  }
133
142
  }
134
143
  }
135
- return null;
144
+ if (!fixes.length) return null;
145
+ const cmp = (x, y) => { try { return compareMavenVersions(x, y); } catch { return String(x).localeCompare(String(y)); } };
146
+ const sorted = [...fixes].sort(cmp);
147
+ if (!depVersion) return sorted[0]; // no current version to compare against → lowest published fix
148
+ const upgrades = sorted.filter(f => cmp(f, depVersion) > 0);
149
+ return upgrades.length ? upgrades[0] : null;
136
150
  }
137
151
 
138
152
  /** Pick the best CVE id from an OSV vuln (prefer CVE-* aliases over GHSA-*). */
@@ -188,7 +202,7 @@ function vulnToMatch(dep, vuln) {
188
202
  ...(cvss.version ? { cvssVersion: `CVSS:${cvss.version}` } : {}),
189
203
  description,
190
204
  summary,
191
- fixVersion: fixVersionFromOsv(vuln, osvPkgName(dep)),
205
+ fixVersion: fixVersionFromOsv(vuln, osvPkgName(dep), dep.version),
192
206
  ghsa: (vuln.aliases || []).find(a => a.startsWith("GHSA-")) || (vuln.id?.startsWith("GHSA-") ? vuln.id : null),
193
207
  published: vuln.published || null,
194
208
  modified: vuln.modified || null,
@@ -116,7 +116,7 @@ function buildSarif(matches, opts = {}) {
116
116
  driver: {
117
117
  name: "fad-checker",
118
118
  version: String(toolVersion),
119
- informationUri: "https://github.com/n8tz/fad-checker",
119
+ informationUri: "https://github.com/9pings/fad-checker",
120
120
  rules: [...rulesById.values()],
121
121
  },
122
122
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fad-checker",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "Scan ALL Maven, Gradle, npm, Yarn, Composer, Python, C#/.NET, Go & Ruby dependencies — plus embedded JARs (fat-jars/war/ear) — in a source tree ONE SHOT without mvn/python/etc — CVE (EPSS/KEV-prioritised), EOL, obsolete, outdated & licenses, with SBOM/CSAF/SARIF/JSON exports, CI gating and fix recos",
5
5
  "keywords": [
6
6
  "sca",
@@ -45,9 +45,9 @@
45
45
  "cli"
46
46
  ],
47
47
  "license": "MIT",
48
- "repository": "https://github.com/n8tz/fad-checker",
49
- "homepage": "https://github.com/n8tz/fad-checker#readme",
50
- "bugs": "https://github.com/n8tz/fad-checker/issues",
48
+ "repository": "https://github.com/9pings/fad-checker",
49
+ "homepage": "https://github.com/9pings/fad-checker#readme",
50
+ "bugs": "https://github.com/9pings/fad-checker/issues",
51
51
  "author": "pp9Ping <pp9Ping@gmail.com>",
52
52
  "maintainers": [
53
53
  "pp9Ping <pp9Ping@gmail.com>"