blitzstrike 2.4.172 → 2.4.174
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 +20 -0
- package/dist/index.js +133 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,26 @@ 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.174] — 2026-10-11
|
|
9
|
+
|
|
10
|
+
### Added — observation ledger + lineage (third write-back channel)
|
|
11
|
+
|
|
12
|
+
- New `facts` engine + 3 tools: `record_fact` (record an exploration observation
|
|
13
|
+
with observed/inferred confidence + optional parent_ids), `list_facts`, and
|
|
14
|
+
`lineage` (trace a fact's ancestors up + descendants down).
|
|
15
|
+
- Completes the three write-back channels: findings (vulns), assets (asset_discovery),
|
|
16
|
+
and facts (neutral/negative observations that would otherwise be lost).
|
|
17
|
+
|
|
18
|
+
## [2.4.173] — 2026-10-11
|
|
19
|
+
|
|
20
|
+
### Added — goal tracking + prove_goal (completion signal)
|
|
21
|
+
|
|
22
|
+
- New `goals` engine + 3 tools: `goal_set` (register free-text goals + optional
|
|
23
|
+
quantitative condition), `prove_goal` (mark met with evidence + reason), and
|
|
24
|
+
`goal_status` (list goals + `all_met` — the task's completion signal).
|
|
25
|
+
- A goal with a quantitative condition must have its measured value verified before
|
|
26
|
+
proving it met; the task is complete only when `all_met` is true.
|
|
27
|
+
|
|
8
28
|
## [2.4.172] — 2026-10-11
|
|
9
29
|
|
|
10
30
|
### Added — operation constraint registry (deterministic red lines)
|
package/dist/index.js
CHANGED
|
@@ -63918,6 +63918,81 @@ function checkConstraint(action, target) {
|
|
|
63918
63918
|
return { allowed: true, mode: "denylist", matched: null, reason: "denylist mode: no deny rule matches — default allow" };
|
|
63919
63919
|
}
|
|
63920
63920
|
|
|
63921
|
+
// src/goals.ts
|
|
63922
|
+
var goals = [];
|
|
63923
|
+
var counter2 = 0;
|
|
63924
|
+
function nextId2() {
|
|
63925
|
+
counter2 += 1;
|
|
63926
|
+
return `G-${String(counter2).padStart(3, "0")}`;
|
|
63927
|
+
}
|
|
63928
|
+
function setGoals(texts) {
|
|
63929
|
+
for (const t of texts) {
|
|
63930
|
+
const text = typeof t === "string" ? t : t.text;
|
|
63931
|
+
const condition = typeof t === "string" ? undefined : t.condition;
|
|
63932
|
+
const now = new Date().toISOString();
|
|
63933
|
+
goals.push({ id: nextId2(), text, condition, status: "pending", created: now, updated: now });
|
|
63934
|
+
}
|
|
63935
|
+
return [...goals];
|
|
63936
|
+
}
|
|
63937
|
+
function proveGoal(id, evidence, reason) {
|
|
63938
|
+
const g = goals.find((x) => x.id === id);
|
|
63939
|
+
if (!g)
|
|
63940
|
+
return { ok: false, error: `no goal '${id}'` };
|
|
63941
|
+
g.status = "met";
|
|
63942
|
+
g.met_evidence = evidence;
|
|
63943
|
+
g.met_reason = reason;
|
|
63944
|
+
g.updated = new Date().toISOString();
|
|
63945
|
+
return { ok: true, goal: { ...g } };
|
|
63946
|
+
}
|
|
63947
|
+
function goalStatus() {
|
|
63948
|
+
const met = goals.filter((g) => g.status === "met").length;
|
|
63949
|
+
return { goals: [...goals], all_met: goals.length > 0 && met === goals.length, met, total: goals.length };
|
|
63950
|
+
}
|
|
63951
|
+
|
|
63952
|
+
// src/facts.ts
|
|
63953
|
+
var facts = [];
|
|
63954
|
+
var counter3 = 0;
|
|
63955
|
+
function nextId3() {
|
|
63956
|
+
counter3 += 1;
|
|
63957
|
+
return `FACT-${String(counter3).padStart(3, "0")}`;
|
|
63958
|
+
}
|
|
63959
|
+
function recordFact(input) {
|
|
63960
|
+
const fact = {
|
|
63961
|
+
id: nextId3(),
|
|
63962
|
+
text: input.text,
|
|
63963
|
+
confidence: input.confidence,
|
|
63964
|
+
target: input.target,
|
|
63965
|
+
parent_ids: input.parent_ids ?? [],
|
|
63966
|
+
created: new Date().toISOString()
|
|
63967
|
+
};
|
|
63968
|
+
facts.push(fact);
|
|
63969
|
+
return fact;
|
|
63970
|
+
}
|
|
63971
|
+
function listFacts() {
|
|
63972
|
+
return [...facts];
|
|
63973
|
+
}
|
|
63974
|
+
function lineage(id) {
|
|
63975
|
+
const fact = facts.find((f) => f.id === id);
|
|
63976
|
+
if (!fact)
|
|
63977
|
+
return { error: `no fact '${id}'` };
|
|
63978
|
+
const ancestors = [];
|
|
63979
|
+
const seen = new Set([id]);
|
|
63980
|
+
const queue = [...fact.parent_ids];
|
|
63981
|
+
while (queue.length) {
|
|
63982
|
+
const pid = queue.shift();
|
|
63983
|
+
if (seen.has(pid))
|
|
63984
|
+
continue;
|
|
63985
|
+
seen.add(pid);
|
|
63986
|
+
const p = facts.find((f) => f.id === pid);
|
|
63987
|
+
if (p) {
|
|
63988
|
+
ancestors.push(p);
|
|
63989
|
+
queue.push(...p.parent_ids);
|
|
63990
|
+
}
|
|
63991
|
+
}
|
|
63992
|
+
const descendants = facts.filter((f) => f.parent_ids.includes(id));
|
|
63993
|
+
return { fact, ancestors, descendants };
|
|
63994
|
+
}
|
|
63995
|
+
|
|
63921
63996
|
// src/sibling-scan.ts
|
|
63922
63997
|
var SIBLING_SUFFIXES = [
|
|
63923
63998
|
"export",
|
|
@@ -65854,6 +65929,64 @@ ${statusLine}` : statusLine },
|
|
|
65854
65929
|
}, async ({ id }) => {
|
|
65855
65930
|
return { content: [{ type: "text", text: JSON.stringify({ removed: clearConstraint(id), id }) }] };
|
|
65856
65931
|
});
|
|
65932
|
+
server.registerTool("goal_set", {
|
|
65933
|
+
title: "Register engagement goals",
|
|
65934
|
+
description: "GOALS: register one or more free-text goals (each with an optional quantitative condition like 'coverage >= 80%'). goal_status then tracks which are met; the task is COMPLETE only when all_met is true. Use before planning routes so every route traces back to a goal.",
|
|
65935
|
+
inputSchema: {
|
|
65936
|
+
goals: array(object2({ text: string2(), condition: string2().optional() })).describe("Goals to register (text + optional quantitative condition)")
|
|
65937
|
+
}
|
|
65938
|
+
}, async ({ goals }) => {
|
|
65939
|
+
setGoals(goals);
|
|
65940
|
+
return { content: [{ type: "text", text: JSON.stringify(goalStatus()) }] };
|
|
65941
|
+
});
|
|
65942
|
+
server.registerTool("prove_goal", {
|
|
65943
|
+
title: "Mark a goal met with evidence",
|
|
65944
|
+
description: "GOALS: mark a goal met, citing the evidence that proved it + a reason. Before proving a goal with a QUANTITATIVE condition, verify the measured value (coverage %, findings count, privilege) actually meets it — never stamp a goal met early. When the last pending goal is proven, the task is complete.",
|
|
65945
|
+
inputSchema: {
|
|
65946
|
+
id: string2().describe("Goal id (G-XXX) from goal_status"),
|
|
65947
|
+
evidence: string2().describe("Evidence id / artifact that proved this goal (e.g. finding id, coverage value)"),
|
|
65948
|
+
reason: string2().describe("Why this goal is met")
|
|
65949
|
+
}
|
|
65950
|
+
}, async ({ id, evidence, reason }) => {
|
|
65951
|
+
const r = proveGoal(id, evidence, reason);
|
|
65952
|
+
return { content: [{ type: "text", text: JSON.stringify({ ...r, ...goalStatus() }) }] };
|
|
65953
|
+
});
|
|
65954
|
+
server.registerTool("goal_status", {
|
|
65955
|
+
title: "List goals + completion state",
|
|
65956
|
+
description: "GOALS: return every goal with its status + all_met flag (true when every goal is met — the task's completion signal). Check this before declaring the engagement complete; any pending goal means the work is not done.",
|
|
65957
|
+
inputSchema: {}
|
|
65958
|
+
}, async () => {
|
|
65959
|
+
return { content: [{ type: "text", text: JSON.stringify(goalStatus()) }] };
|
|
65960
|
+
});
|
|
65961
|
+
server.registerTool("record_fact", {
|
|
65962
|
+
title: "Record an exploration observation (fact)",
|
|
65963
|
+
description: "FACTS: record an observation/conclusion that is NOT a vuln (finding_create) and NOT an asset (asset_discovery) — e.g. 'admin panel is behind SSO', 'upload strips .php', 'param id is reflected'. Pass text, confidence (observed = you triggered it; inferred = deduced from a fingerprint/diff — never report inferred as confirmed), optional target, and optional parent_ids (facts this derives from). Use this so negative/neutral observations are written down instead of lost.",
|
|
65964
|
+
inputSchema: {
|
|
65965
|
+
text: string2().describe("The observation/conclusion"),
|
|
65966
|
+
confidence: _enum(["observed", "inferred"]).describe("observed (directly triggered) or inferred (deduced, not yet triggered)"),
|
|
65967
|
+
target: string2().optional().describe("Optional host/endpoint/param the fact is about"),
|
|
65968
|
+
parent_ids: array(string2()).optional().describe("Optional ids of facts this one derives from")
|
|
65969
|
+
}
|
|
65970
|
+
}, async ({ text, confidence, target, parent_ids }) => {
|
|
65971
|
+
const fact = recordFact({ text, confidence, target, parent_ids });
|
|
65972
|
+
return { content: [{ type: "text", text: JSON.stringify(fact) }] };
|
|
65973
|
+
});
|
|
65974
|
+
server.registerTool("list_facts", {
|
|
65975
|
+
title: "List all recorded facts",
|
|
65976
|
+
description: "FACTS: return every recorded observation with its confidence + lineage parent_ids. Use before re-testing a direction — a solid observed fact (or a recorded dead-end) saves re-probing the same thing.",
|
|
65977
|
+
inputSchema: {}
|
|
65978
|
+
}, async () => {
|
|
65979
|
+
return { content: [{ type: "text", text: JSON.stringify(listFacts()) }] };
|
|
65980
|
+
});
|
|
65981
|
+
server.registerTool("lineage", {
|
|
65982
|
+
title: "Trace a fact's lineage (ancestors + descendants)",
|
|
65983
|
+
description: "FACTS: walk a fact's lineage — its ancestors (the facts it derived from, up the parent chain) and descendants (facts derived from it). Use to understand where a conclusion came from and what it enabled.",
|
|
65984
|
+
inputSchema: {
|
|
65985
|
+
id: string2().describe("Fact id (FACT-XXX) to trace")
|
|
65986
|
+
}
|
|
65987
|
+
}, async ({ id }) => {
|
|
65988
|
+
return { content: [{ type: "text", text: JSON.stringify(lineage(id)) }] };
|
|
65989
|
+
});
|
|
65857
65990
|
server.registerTool("hunting_doctrine", {
|
|
65858
65991
|
title: "High-ROI hunting doctrine (sibling rule, A→B, follow-the-money)",
|
|
65859
65992
|
description: "Return the hunting doctrine — the high-ROI heuristics the agent applies while selecting targets/endpoints/classes: the Sibling Rule (check every sibling endpoint — ~30% of paid IDOR/auth bugs), A→B Signal Method, impact-first, follow-the-money, less-saturated classes, new==unreviewed, two-account IDOR test, PoC escalation, credential-proof, CI/CD + SAML/SSO attack surface, 20-minute rotation, plus the always-rejected kill-list. Use when deciding WHAT to hunt next.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.174",
|
|
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": {
|