blitzstrike 2.4.110 → 2.4.112
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 +36 -0
- package/dist/index.js +42 -10
- package/intelligence/cve-corpus.json +37023 -0
- package/intelligence/watchlist.json +195 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,42 @@ All notable changes to Blitz Strike are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
7
7
|
|
|
8
|
+
## [2.4.112] — 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Added — nuclei-templates CVE corpus (watchlist 35 → 4,100+ fingerprints)
|
|
11
|
+
|
|
12
|
+
- New `intelligence/cve-corpus.json` (4,113 CVEs) derived from the canonical
|
|
13
|
+
`projectdiscovery/nuclei-templates` `http/cves/**` tree via
|
|
14
|
+
`scripts/sync-cve-corpus.py` (re-runnable after `nuclei -update-templates`).
|
|
15
|
+
Each entry carries product name + severity + EPSS + CWE + a word-boundary
|
|
16
|
+
`match` regex built from product-name tokens + fofa/shodan query keywords
|
|
17
|
+
(NOT matcher payload words, which are too generic).
|
|
18
|
+
- `watchlistCveMatches` / `live_recon` now match against the hand-curated
|
|
19
|
+
watchlist (version-precise) AND the corpus (long-tail), ranked by EPSS then
|
|
20
|
+
severity, capped at 20, with the hand-curated entry overriding the corpus for
|
|
21
|
+
the same CVE. Generic infra tokens (php/apache/mysql/powered/…) are excluded
|
|
22
|
+
so a plain PHP/HTML target yields ZERO false matches — regression-tested
|
|
23
|
+
(plain php → 0; vite/gradio/ollama/n8n → their specific CVEs).
|
|
24
|
+
|
|
25
|
+
## [2.4.111] — 2026-09-17
|
|
26
|
+
|
|
27
|
+
### Added — CVE watchlist expanded 18 → 35 (2025-2026 fingerprints)
|
|
28
|
+
|
|
29
|
+
- Added 17 actively-exploited 2025-2026 CVEs to `intelligence/watchlist.json`
|
|
30
|
+
with fingerprints + fixed versions, wired into `watchlistCveMatches` /
|
|
31
|
+
`live_recon` fingerprint-first: n8n unauth/auth RCE (CVE-2026-21858/21877),
|
|
32
|
+
D-Link DSL RCE (CVE-2026-0625), Veeam RCE (CVE-2025-59470), Cisco SD-WAN
|
|
33
|
+
auth bypass (CVE-2026-20127), Gradio path-traversal + SSRF
|
|
34
|
+
(CVE-2026-28414/28416), FortiOS LDAP leak (CVE-2026-25815), Dell
|
|
35
|
+
RecoverPoint hardcoded creds (CVE-2026-22769), Statamic XSS
|
|
36
|
+
(CVE-2026-28426), Chartbrew SQLi + MongoDB RCE (CVE-2026-27005/25887),
|
|
37
|
+
Apache Camel header injection (CVE-2026-31650), Jenkins script-console RCE
|
|
38
|
+
(CVE-2026-30170), GraphQL introspection leak (CVE-2026-29812), Ollama path
|
|
39
|
+
traversal (CVE-2026-32154), Spring Boot actuator env leak (CVE-2026-33001).
|
|
40
|
+
- Tightened two over-broad fingerprint regexes (dropped the standalone
|
|
41
|
+
"workflow" keyword that false-positived n8n↔Kibana); regression-tested
|
|
42
|
+
fingerprint precision (n8n ≠ kibana).
|
|
43
|
+
|
|
8
44
|
## [2.4.110] — 2026-09-17
|
|
9
45
|
|
|
10
46
|
### Added — hash length extension + concrete payload enrichment
|
package/dist/index.js
CHANGED
|
@@ -36376,6 +36376,27 @@ function loadWatchlist() {
|
|
|
36376
36376
|
const data = JSON.parse(raw);
|
|
36377
36377
|
return { cwe_frequency: data.cwe_frequency ?? [], cve_watchlist: data.cve_watchlist ?? [] };
|
|
36378
36378
|
}
|
|
36379
|
+
function loadCorpus() {
|
|
36380
|
+
try {
|
|
36381
|
+
const raw = readFileSync11(join12(ROOT4, "intelligence", "cve-corpus.json"), "utf8");
|
|
36382
|
+
const data = JSON.parse(raw);
|
|
36383
|
+
return (data.cves ?? []).map((c) => ({
|
|
36384
|
+
cve: String(c.cve ?? ""),
|
|
36385
|
+
name: String(c.name ?? ""),
|
|
36386
|
+
product: String(c.product ?? ""),
|
|
36387
|
+
class: "",
|
|
36388
|
+
epss: typeof c.epss === "number" ? c.epss : parseFloat(String(c.epss ?? "0")) || 0,
|
|
36389
|
+
reports: 0,
|
|
36390
|
+
fingerprint: String(c.product ?? ""),
|
|
36391
|
+
match: typeof c.match === "string" ? c.match : undefined,
|
|
36392
|
+
fixed_in: null,
|
|
36393
|
+
version_key: null,
|
|
36394
|
+
severity: typeof c.severity === "string" ? c.severity : undefined
|
|
36395
|
+
}));
|
|
36396
|
+
} catch {
|
|
36397
|
+
return [];
|
|
36398
|
+
}
|
|
36399
|
+
}
|
|
36379
36400
|
function fmtPayout(min, max) {
|
|
36380
36401
|
if (min == null || max == null)
|
|
36381
36402
|
return "n/a";
|
|
@@ -36417,31 +36438,42 @@ function semverLt(a, b) {
|
|
|
36417
36438
|
}
|
|
36418
36439
|
return false;
|
|
36419
36440
|
}
|
|
36420
|
-
function watchlistCveMatches(techs, headers = {}, body = "", versions = []) {
|
|
36441
|
+
function watchlistCveMatches(techs, headers = {}, body = "", versions = [], max = 20) {
|
|
36421
36442
|
const { cve_watchlist } = loadWatchlist();
|
|
36443
|
+
const corpus = loadCorpus();
|
|
36422
36444
|
const haystack = `${techs.join(" ")} ${Object.keys(headers).join(" ")} ${Object.values(headers).join(" ")} ${body}`.toLowerCase();
|
|
36423
|
-
|
|
36445
|
+
const curated = new Map(cve_watchlist.map((c) => [c.cve, c]));
|
|
36446
|
+
const merged = [...corpus.filter((c) => !curated.has(c.cve)), ...cve_watchlist];
|
|
36447
|
+
const matched = merged.filter((c) => {
|
|
36424
36448
|
const m = c.match;
|
|
36425
36449
|
if (!m)
|
|
36426
36450
|
return false;
|
|
36427
|
-
let
|
|
36451
|
+
let ok = false;
|
|
36428
36452
|
try {
|
|
36429
|
-
|
|
36453
|
+
ok = new RegExp(m, "i").test(haystack);
|
|
36430
36454
|
} catch {
|
|
36431
|
-
|
|
36455
|
+
ok = false;
|
|
36432
36456
|
}
|
|
36433
|
-
if (!
|
|
36457
|
+
if (!ok)
|
|
36434
36458
|
return false;
|
|
36435
36459
|
const fixedIn = c.fixed_in;
|
|
36436
36460
|
const vkey = c.version_key;
|
|
36437
36461
|
if (fixedIn && vkey) {
|
|
36438
36462
|
const v = versions.find((x) => x.product.toLowerCase().includes(vkey.toLowerCase()));
|
|
36439
|
-
if (v?.version && !semverLt(v.version, fixedIn))
|
|
36463
|
+
if (v?.version && !semverLt(v.version, fixedIn))
|
|
36440
36464
|
return false;
|
|
36441
|
-
}
|
|
36442
36465
|
}
|
|
36443
36466
|
return true;
|
|
36444
36467
|
});
|
|
36468
|
+
const sevRank = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
36469
|
+
matched.sort((a, b) => {
|
|
36470
|
+
const ea = a.epss ?? 0;
|
|
36471
|
+
const eb = b.epss ?? 0;
|
|
36472
|
+
if (ea !== eb)
|
|
36473
|
+
return eb - ea;
|
|
36474
|
+
return (sevRank[a.severity ?? ""] ?? 9) - (sevRank[b.severity ?? ""] ?? 9);
|
|
36475
|
+
});
|
|
36476
|
+
return matched.slice(0, max);
|
|
36445
36477
|
}
|
|
36446
36478
|
|
|
36447
36479
|
// src/surface-map.ts
|
|
@@ -59801,7 +59833,7 @@ function loadDir(dir) {
|
|
|
59801
59833
|
} catch {}
|
|
59802
59834
|
return entries;
|
|
59803
59835
|
}
|
|
59804
|
-
function
|
|
59836
|
+
function loadCorpus2() {
|
|
59805
59837
|
return [...loadDir(CORPUS), ...loadDir(CAPTURED_CORPUS_DIR)];
|
|
59806
59838
|
}
|
|
59807
59839
|
function captureFalsePositive(input) {
|
|
@@ -59858,7 +59890,7 @@ function detect(entry) {
|
|
|
59858
59890
|
return { detected: false };
|
|
59859
59891
|
}
|
|
59860
59892
|
function runBenchmark() {
|
|
59861
|
-
const entries =
|
|
59893
|
+
const entries = loadCorpus2();
|
|
59862
59894
|
const results = entries.map((entry) => {
|
|
59863
59895
|
const { detected, sinkKind } = detect(entry);
|
|
59864
59896
|
const outcome = entry.vulnerable ? detected ? "tp" : "fn" : detected ? "fp" : "tn";
|