blitzstrike 2.4.167 → 2.4.169
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 +27 -0
- package/dist/index.js +60 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ 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.169] — 2026-10-11
|
|
9
|
+
|
|
10
|
+
### Added — finding retest loop (post-confirmation lifecycle)
|
|
11
|
+
|
|
12
|
+
- The finding lifecycle no longer ends at `confirmed`: added `retesting`, `fixed`,
|
|
13
|
+
and `still_vulnerable` states with the transitions `confirmed -> retesting ->
|
|
14
|
+
fixed | still_vulnerable`, and `still_vulnerable -> retesting` (re-retest after
|
|
15
|
+
the next patch window; `fixed` is terminal).
|
|
16
|
+
- New `retest_finding` tool: pass a confirmed/still_vulnerable finding + a retest
|
|
17
|
+
verdict (`fixed` or `still_vulnerable`) + reason; it advances the lifecycle and
|
|
18
|
+
records the verdict + reason as evidence. Run `strike_verify` first to obtain the
|
|
19
|
+
live verdict, then record it here.
|
|
20
|
+
|
|
21
|
+
## [2.4.168] — 2026-10-11
|
|
22
|
+
|
|
23
|
+
### Fixed — blind_sqli_extract: space extraction + drift-proof time fallback
|
|
24
|
+
|
|
25
|
+
- Added SPACE (+ parens/comma) to the extraction linear-fallback charset, so
|
|
26
|
+
version/database strings with embedded spaces (e.g. "Microsoft SQL Server 2012")
|
|
27
|
+
extract fully instead of stopping at the first space.
|
|
28
|
+
- Auto-fall back to the TIME oracle when a marker-less byte-count boolean oracle
|
|
29
|
+
extracts nothing — the time oracle is deterministic and immune to page-size
|
|
30
|
+
drift on dynamic remote pages.
|
|
31
|
+
- Excluded WAF-sensitive chars (#, =, <, >, quotes, %, &, ;, |, *) from the
|
|
32
|
+
charset: a WAF that strips one of them turns the comparison into `= ''`
|
|
33
|
+
(always-true past the string end), which previously produced a false trailing run.
|
|
34
|
+
|
|
8
35
|
## [2.4.167] — 2026-10-11
|
|
9
36
|
|
|
10
37
|
### Fixed — blind_oracle detection false-negative + false-positive (real target)
|
package/dist/index.js
CHANGED
|
@@ -33277,7 +33277,10 @@ var LIFECYCLE_TRANSITIONS = {
|
|
|
33277
33277
|
triaged: ["hypothesis", "rejected", "out_of_scope"],
|
|
33278
33278
|
hypothesis: ["validating", "false_positive", "rejected", "blocked"],
|
|
33279
33279
|
validating: ["confirmed", "false_positive", "blocked", "out_of_scope"],
|
|
33280
|
-
confirmed: [],
|
|
33280
|
+
confirmed: ["retesting"],
|
|
33281
|
+
retesting: ["fixed", "still_vulnerable", "false_positive"],
|
|
33282
|
+
fixed: [],
|
|
33283
|
+
still_vulnerable: ["retesting"],
|
|
33281
33284
|
false_positive: [],
|
|
33282
33285
|
rejected: [],
|
|
33283
33286
|
blocked: [],
|
|
@@ -33440,6 +33443,17 @@ function rejectFinding(finding, status, reason, evidence) {
|
|
|
33440
33443
|
timestamps: { ...updated.timestamps, updated: new Date().toISOString() }
|
|
33441
33444
|
};
|
|
33442
33445
|
}
|
|
33446
|
+
function retestFinding(finding, opts) {
|
|
33447
|
+
const retesting = transition(finding, "retesting");
|
|
33448
|
+
const ev = opts.evidence?.map((e) => makeEvidence(e)) ?? [];
|
|
33449
|
+
const result = transition(retesting, opts.verdict);
|
|
33450
|
+
return {
|
|
33451
|
+
...result,
|
|
33452
|
+
remediation: { ...result.remediation, retest_note: opts.reason },
|
|
33453
|
+
evidence: [...result.evidence, ...ev],
|
|
33454
|
+
timestamps: { ...result.timestamps, updated: new Date().toISOString() }
|
|
33455
|
+
};
|
|
33456
|
+
}
|
|
33443
33457
|
|
|
33444
33458
|
// src/sinks.ts
|
|
33445
33459
|
init_secrets();
|
|
@@ -62729,7 +62743,7 @@ async function blindSqliExtract(baseUrl, param, value, dbms, target, opts = {})
|
|
|
62729
62743
|
}
|
|
62730
62744
|
}
|
|
62731
62745
|
}
|
|
62732
|
-
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_/.-:@";
|
|
62746
|
+
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789{}_/.-:@(), ";
|
|
62733
62747
|
const caseInsensitive = p.dbms === "mysql" || p.dbms === "mssql";
|
|
62734
62748
|
const bsCharset = caseInsensitive ? "0123456789abcdefghijklmnopqrstuvwxyz" : "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
62735
62749
|
const baseTpl = (channel === "time" ? p.extraction.time : p.extraction.boolean).replace(/^'/, ctx);
|
|
@@ -62792,6 +62806,9 @@ async function blindSqliExtract(baseUrl, param, value, dbms, target, opts = {})
|
|
|
62792
62806
|
out += ch;
|
|
62793
62807
|
}
|
|
62794
62808
|
out = out.trimEnd();
|
|
62809
|
+
if (out.length === 0 && channel === "boolean" && !marker) {
|
|
62810
|
+
return await blindSqliExtract(baseUrl, param, value, dbms, target, { ...opts, channel: "time" });
|
|
62811
|
+
}
|
|
62795
62812
|
return {
|
|
62796
62813
|
dbms,
|
|
62797
62814
|
target,
|
|
@@ -66338,7 +66355,7 @@ ${statusLine}` : statusLine },
|
|
|
66338
66355
|
});
|
|
66339
66356
|
server.registerTool("finding_transition", {
|
|
66340
66357
|
title: "Advance a finding lifecycle (STATEFUL)",
|
|
66341
|
-
description: "FINDINGS: advance a canonical Finding through its lifecycle (detected->triaged->hypothesis->validating->confirmed) and RETURN the updated finding. STATEFUL — pass the FULL finding JSON (from finding_create / run_engagement), not a status string. Rejects illegal transitions with the legal next states.
|
|
66358
|
+
description: "FINDINGS: advance a canonical Finding through its lifecycle (detected->triaged->hypothesis->validating->confirmed, then the retest loop confirmed->retesting->fixed|still_vulnerable) and RETURN the updated finding. STATEFUL — pass the FULL finding JSON (from finding_create / run_engagement), not a status string. Rejects illegal transitions with the legal next states. To confirm FROM a live verdict use strike_resolve; to re-verify a confirmed finding use retest_finding.",
|
|
66342
66359
|
inputSchema: {
|
|
66343
66360
|
finding: string2().describe("JSON of the canonical Finding object (from finding_create / run_engagement)"),
|
|
66344
66361
|
to: string2().describe("Target status (triaged/hypothesis/validating/confirmed/false_positive/rejected/blocked/out_of_scope)")
|
|
@@ -66367,6 +66384,46 @@ ${statusLine}` : statusLine },
|
|
|
66367
66384
|
}]
|
|
66368
66385
|
};
|
|
66369
66386
|
});
|
|
66387
|
+
server.registerTool("retest_finding", {
|
|
66388
|
+
title: "Re-verify a confirmed finding (retest loop)",
|
|
66389
|
+
description: "FINDINGS: re-verify a CONFIRMED (or still_vulnerable) finding to check whether the vendor patched it. Pass the full finding JSON + the retest verdict: 'fixed' (the exploit no longer reproduces — patch applied) or 'still_vulnerable' (still exploitable). Advances confirmed -> retesting -> fixed|still_vulnerable and records the verdict + reason as evidence. still_vulnerable findings can be re-retested later. Run strike_verify FIRST to get the live verdict, then record it here.",
|
|
66390
|
+
inputSchema: {
|
|
66391
|
+
finding: string2().describe("JSON of the canonical Finding object (status confirmed or still_vulnerable)"),
|
|
66392
|
+
verdict: _enum(["fixed", "still_vulnerable"]).describe("Retest outcome: fixed (patch applied) or still_vulnerable (still exploitable)"),
|
|
66393
|
+
reason: string2().describe("Short note: what changed / what still reproduces"),
|
|
66394
|
+
evidence: string2().optional().describe("Optional JSON array of evidence entries [{type, description, content}]")
|
|
66395
|
+
}
|
|
66396
|
+
}, async ({ finding, verdict, reason, evidence }) => {
|
|
66397
|
+
let f;
|
|
66398
|
+
try {
|
|
66399
|
+
f = JSON.parse(finding);
|
|
66400
|
+
} catch {
|
|
66401
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid finding JSON — pass the full Finding object" }) }] };
|
|
66402
|
+
}
|
|
66403
|
+
const from = f.status ?? "detected";
|
|
66404
|
+
if (!(from === "confirmed" || from === "still_vulnerable")) {
|
|
66405
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: `retest only valid from 'confirmed' or 'still_vulnerable', not '${from}'`, legal_next: LIFECYCLE_TRANSITIONS[from] ?? [] }) }] };
|
|
66406
|
+
}
|
|
66407
|
+
let ev = [];
|
|
66408
|
+
if (evidence) {
|
|
66409
|
+
try {
|
|
66410
|
+
ev = JSON.parse(evidence);
|
|
66411
|
+
} catch {
|
|
66412
|
+
ev = [];
|
|
66413
|
+
}
|
|
66414
|
+
}
|
|
66415
|
+
const updated = retestFinding(f, { verdict, reason, evidence: ev });
|
|
66416
|
+
return {
|
|
66417
|
+
content: [{
|
|
66418
|
+
type: "text",
|
|
66419
|
+
text: JSON.stringify({
|
|
66420
|
+
...updated,
|
|
66421
|
+
transition: `${from} -> retesting -> ${updated.status}`,
|
|
66422
|
+
...updated.status === "fixed" ? { hint: "FIXED — the vendor patched it. The retest closes this finding's loop." } : { hint: "STILL_VULNERABLE — re-retest later via retest_finding after the next patch window." }
|
|
66423
|
+
})
|
|
66424
|
+
}]
|
|
66425
|
+
};
|
|
66426
|
+
});
|
|
66370
66427
|
server.registerTool("capture_false_positive", {
|
|
66371
66428
|
title: "Capture a verified false positive (self-hardening)",
|
|
66372
66429
|
description: "SELF-HARDENING: record a VERIFIED false positive (a code pattern the detector flagged but live verification ruled out) into the writable benchmark corpus, so the next run_benchmark measures whether the detector STILL flags it. Pass the triggering CODE + language + detector + a short note. Every capture makes the detector more precise — close the loop, never just discard a refuted lead.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.169",
|
|
4
4
|
"description": "Blitz Strike — a universal MCP security-audit toolbelt. BLITZ sweeps the attack surface, EAGLE-EYE traces source-to-sink, STRIKE verifies live. 57 attack chains, 130-tool catalog, intelligence data layer. One server, every agent.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|