blitzstrike 2.4.8 → 2.4.9
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 +12 -0
- package/dist/index.js +47 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,18 @@ 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.9] — 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added — evidence-first enforcement (findings are never born empty)
|
|
11
|
+
|
|
12
|
+
- `makeFinding` + `finding_create` now accept `evidence` at creation — a finding
|
|
13
|
+
can carry its observed artifact (headers/URL/response) the moment it is
|
|
14
|
+
created, instead of relying on a separate attach call that gets skipped.
|
|
15
|
+
- `finding_create` warns when a finding is created with no evidence.
|
|
16
|
+
- `reportMarkdown` now flags evidence-less findings with an explicit
|
|
17
|
+
"Evidence-first violation" block (ids listed) — detection without proof is
|
|
18
|
+
surfaced instead of silently shipped.
|
|
19
|
+
|
|
8
20
|
## [2.4.8] — 2026-09-14
|
|
9
21
|
|
|
10
22
|
### Added — MCP integration health checks
|
package/dist/index.js
CHANGED
|
@@ -31064,7 +31064,7 @@ function makeFinding(input) {
|
|
|
31064
31064
|
const status = input.status ?? "detected";
|
|
31065
31065
|
const factors = confidenceFactorsFor(input);
|
|
31066
31066
|
const confidence = computeConfidence(factors);
|
|
31067
|
-
|
|
31067
|
+
let finding = {
|
|
31068
31068
|
id: nextFindingId(),
|
|
31069
31069
|
status,
|
|
31070
31070
|
title: input.title,
|
|
@@ -31087,6 +31087,16 @@ function makeFinding(input) {
|
|
|
31087
31087
|
remediation: {},
|
|
31088
31088
|
timestamps: { created: now, updated: now }
|
|
31089
31089
|
};
|
|
31090
|
+
if (input.evidence?.length) {
|
|
31091
|
+
for (const e of input.evidence) {
|
|
31092
|
+
const ev = makeEvidence({
|
|
31093
|
+
type: e.type,
|
|
31094
|
+
description: e.description,
|
|
31095
|
+
artifacts: e.content ? [{ name: "artifact", kind: "evidence", content: e.content }] : []
|
|
31096
|
+
});
|
|
31097
|
+
finding = attachEvidence(finding, ev);
|
|
31098
|
+
}
|
|
31099
|
+
}
|
|
31090
31100
|
recordAudit("finding_created", { tool: "eagle-eye", target: input.target.host ?? input.target.endpoint, result: status, correlationId: finding.id });
|
|
31091
31101
|
return finding;
|
|
31092
31102
|
}
|
|
@@ -33009,11 +33019,15 @@ function summarize(findings) {
|
|
|
33009
33019
|
const byStatus = {};
|
|
33010
33020
|
const bySeverity = {};
|
|
33011
33021
|
let evidenceArtifacts = 0;
|
|
33022
|
+
let evidenceLess = 0;
|
|
33012
33023
|
for (const f of findings) {
|
|
33013
33024
|
byStatus[f.status ?? "detected"] = (byStatus[f.status ?? "detected"] ?? 0) + 1;
|
|
33014
33025
|
const sev = f.classification?.severity ?? "informational";
|
|
33015
33026
|
bySeverity[sev] = (bySeverity[sev] ?? 0) + 1;
|
|
33016
|
-
|
|
33027
|
+
const arts = f.evidence?.reduce((n, e) => n + (e.artifacts?.length ?? 0), 0) ?? 0;
|
|
33028
|
+
evidenceArtifacts += arts;
|
|
33029
|
+
if ((f.evidence ?? []).length === 0)
|
|
33030
|
+
evidenceLess += 1;
|
|
33017
33031
|
}
|
|
33018
33032
|
const groups = dedupFindings(findings);
|
|
33019
33033
|
return {
|
|
@@ -33023,7 +33037,8 @@ function summarize(findings) {
|
|
|
33023
33037
|
by_severity: bySeverity,
|
|
33024
33038
|
confirmed: byStatus["confirmed"] ?? 0,
|
|
33025
33039
|
false_positives: byStatus["false_positive"] ?? 0,
|
|
33026
|
-
evidence_artifacts: evidenceArtifacts
|
|
33040
|
+
evidence_artifacts: evidenceArtifacts,
|
|
33041
|
+
evidence_less_findings: evidenceLess
|
|
33027
33042
|
};
|
|
33028
33043
|
}
|
|
33029
33044
|
function reportMarkdown(findings, opts = {}) {
|
|
@@ -33047,6 +33062,11 @@ function reportMarkdown(findings, opts = {}) {
|
|
|
33047
33062
|
}
|
|
33048
33063
|
lines.push(`Detailed findings, reproduction steps, impact, and remediation follow in section 5.`);
|
|
33049
33064
|
lines.push("");
|
|
33065
|
+
if (summary.evidence_less_findings > 0) {
|
|
33066
|
+
const evLess = findings.filter((f) => (f.evidence ?? []).length === 0).map((f) => f.id).join(", ");
|
|
33067
|
+
lines.push(`> ⚠️ **Evidence-first violation:** **${summary.evidence_less_findings}** finding(s) carry NO evidence artifacts (${evLess}). ` + `Detection is not proof — every finding must carry the observed artifact (headers, URL, response body). Attach evidence via finding_attach_evidence before finalizing.`);
|
|
33068
|
+
lines.push("");
|
|
33069
|
+
}
|
|
33050
33070
|
lines.push("## 2. Scope");
|
|
33051
33071
|
lines.push("");
|
|
33052
33072
|
lines.push(`- **Target(s):** ${scope}`);
|
|
@@ -57170,7 +57190,7 @@ ${statusLine}` : statusLine },
|
|
|
57170
57190
|
});
|
|
57171
57191
|
server.registerTool("finding_create", {
|
|
57172
57192
|
title: "Create a canonical finding",
|
|
57173
|
-
description: "FINDINGS: create a canonical, evidence-first finding. Severity describes impact; confidence (deterministic) describes certainty. Default status=detected (hypothesis-pending).",
|
|
57193
|
+
description: "FINDINGS: create a canonical, evidence-first finding. Severity describes impact; confidence (deterministic) describes certainty. Default status=detected (hypothesis-pending). Pass `evidence` (JSON array of {type, description, content}) to attach observed artifacts AT CREATION — a finding must never be born empty when you already hold the artifact (headers, URL, response body).",
|
|
57174
57194
|
inputSchema: {
|
|
57175
57195
|
title: string2().describe("Finding title"),
|
|
57176
57196
|
target_type: string2().optional().describe("Target type (web/api/source/mobile/network/other)"),
|
|
@@ -57182,9 +57202,18 @@ ${statusLine}` : statusLine },
|
|
|
57182
57202
|
source_name: string2().describe("Source name"),
|
|
57183
57203
|
sink_type: string2().describe("Sink type (e.g. sql_execution, command_execution, file_operations)"),
|
|
57184
57204
|
sink_symbol: string2().optional().describe("Sink symbol (e.g. '->query(')"),
|
|
57185
|
-
chain_id: string2().optional().describe("Escalation chain id")
|
|
57205
|
+
chain_id: string2().optional().describe("Escalation chain id"),
|
|
57206
|
+
evidence: string2().optional().describe("JSON array of evidence entries: [{type, description, content?}] — attached at creation (redacted + SHA-256 tagged)")
|
|
57207
|
+
}
|
|
57208
|
+
}, async ({ title, target_type, host, endpoint, severity, cwe, source_type, source_name, sink_type, sink_symbol, chain_id, evidence }) => {
|
|
57209
|
+
let evs = [];
|
|
57210
|
+
if (evidence) {
|
|
57211
|
+
try {
|
|
57212
|
+
evs = JSON.parse(evidence);
|
|
57213
|
+
} catch {
|
|
57214
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid evidence JSON" }) }] };
|
|
57215
|
+
}
|
|
57186
57216
|
}
|
|
57187
|
-
}, async ({ title, target_type, host, endpoint, severity, cwe, source_type, source_name, sink_type, sink_symbol, chain_id }) => {
|
|
57188
57217
|
const f = makeFinding({
|
|
57189
57218
|
title,
|
|
57190
57219
|
target: { type: target_type ?? "web", host, endpoint },
|
|
@@ -57193,9 +57222,19 @@ ${statusLine}` : statusLine },
|
|
|
57193
57222
|
source: { type: source_type, name: source_name },
|
|
57194
57223
|
sink: { type: sink_type, symbol: sink_symbol },
|
|
57195
57224
|
chainId: chain_id ?? null,
|
|
57196
|
-
status: "detected"
|
|
57225
|
+
status: "detected",
|
|
57226
|
+
evidence: evs
|
|
57197
57227
|
});
|
|
57198
|
-
|
|
57228
|
+
const empty = (f.evidence ?? []).length === 0;
|
|
57229
|
+
return {
|
|
57230
|
+
content: [{
|
|
57231
|
+
type: "text",
|
|
57232
|
+
text: JSON.stringify({
|
|
57233
|
+
...f,
|
|
57234
|
+
_warning: empty ? "finding created with NO evidence — if you hold the observed artifact (headers/URL/body), attach it now via `evidence` or finding_attach_evidence" : undefined
|
|
57235
|
+
})
|
|
57236
|
+
}]
|
|
57237
|
+
};
|
|
57199
57238
|
});
|
|
57200
57239
|
server.registerTool("finding_transition", {
|
|
57201
57240
|
title: "Advance a finding lifecycle",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.9",
|
|
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": {
|