blitzstrike 1.0.47 → 1.0.48
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 +18 -0
- package/dist/index.js +80 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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
|
+
## [1.0.48] — 2026-09-13
|
|
9
|
+
|
|
10
|
+
### Added — Autonomous Security Engine (phase 8: coverage-driven scheduler)
|
|
11
|
+
|
|
12
|
+
- **Coverage-driven Scheduler** (`src/mission/coverage.ts`, §13):
|
|
13
|
+
- `computeCoverage()` — 10 dimensions (attack surface, endpoints, technologies,
|
|
14
|
+
source files, sink classes, auth/authorization boundaries, vulnerability
|
|
15
|
+
classes, attack vectors, escalation chains).
|
|
16
|
+
- `coverageGaps()` — dimensions below a threshold.
|
|
17
|
+
- `scheduleCoverageTasks()` — auto-generates tasks for under-covered
|
|
18
|
+
dimensions, skipping already-attempted agents and mode-inappropriate ones
|
|
19
|
+
(e.g. no `@web` for source audits; endpoints/technologies resolve locally).
|
|
20
|
+
- `gapAgent()` — mode-aware dimension→agent mapping.
|
|
21
|
+
- Mission Control's `replan` now runs the coverage scheduler and persists
|
|
22
|
+
per-dimension coverage into `mission.coverage.dimensions`.
|
|
23
|
+
- `@recon` now links discovered endpoints into the Security Graph (so coverage
|
|
24
|
+
reflects real endpoint exploration).
|
|
25
|
+
|
|
8
26
|
## [1.0.47] — 2026-09-13
|
|
9
27
|
|
|
10
28
|
### Added — Autonomous Security Engine (phase 7: adaptive planner)
|
package/dist/index.js
CHANGED
|
@@ -18301,11 +18301,18 @@ var init_agents = __esm(() => {
|
|
|
18301
18301
|
};
|
|
18302
18302
|
}
|
|
18303
18303
|
const r = enrichScan(ctx.mission.target, 500);
|
|
18304
|
+
let graph = { nodes: [], edges: [] };
|
|
18305
|
+
const tid = `target:${ctx.mission.target}`;
|
|
18306
|
+
for (const ep of r.hits.filter((h) => h.type === "endpoint").slice(0, 50)) {
|
|
18307
|
+
const epId = `endpoint:${ep.file}:${ep.line}`;
|
|
18308
|
+
graph = upsertNode(graph, epId, "endpoint", { file: ep.file, line: ep.line, hook: ep.detail });
|
|
18309
|
+
graph = addEdge2(graph, tid, epId, "exposes");
|
|
18310
|
+
}
|
|
18304
18311
|
return {
|
|
18305
18312
|
ok: true,
|
|
18306
18313
|
output: { files_scanned: r.files_scanned, hits: r.hits.length, sink_signals: r.sink_signals, endpoints: r.hits.filter((h) => h.type === "endpoint").length },
|
|
18307
18314
|
hypotheses: [],
|
|
18308
|
-
graph
|
|
18315
|
+
graph
|
|
18309
18316
|
};
|
|
18310
18317
|
}
|
|
18311
18318
|
};
|
|
@@ -18582,6 +18589,71 @@ ${m.hypotheses.map((h) => `- [${h.status}] ${h.type} @ ${h.target} (confidence $
|
|
|
18582
18589
|
};
|
|
18583
18590
|
});
|
|
18584
18591
|
|
|
18592
|
+
// src/mission/coverage.ts
|
|
18593
|
+
function clamp012(n) {
|
|
18594
|
+
return Math.max(0, Math.min(1, n));
|
|
18595
|
+
}
|
|
18596
|
+
function computeCoverage(mission) {
|
|
18597
|
+
const byType = graphStats(mission.graph).by_type;
|
|
18598
|
+
const hyps = mission.hypotheses;
|
|
18599
|
+
const sinkCategories = new Set(mission.graph.nodes.filter((n) => n.type === "sink").map((n) => String(n.properties.category ?? n.properties.sink ?? "unknown")));
|
|
18600
|
+
const hypTypes = new Set(hyps.map((h) => h.type));
|
|
18601
|
+
return {
|
|
18602
|
+
attack_surface: clamp012(mission.graph.nodes.length / 25),
|
|
18603
|
+
endpoints: clamp012((byType.endpoint ?? 0) / 10),
|
|
18604
|
+
technologies: clamp012(mission.technologies.length / 6),
|
|
18605
|
+
source_files: clamp012((byType.sink ?? 0) / 15),
|
|
18606
|
+
sink_classes: clamp012(sinkCategories.size / 10),
|
|
18607
|
+
auth_boundaries: hyps.length ? clamp012(hyps.filter((h) => /auth/i.test(h.evidence)).length / hyps.length) : 0,
|
|
18608
|
+
authorization_boundaries: hyps.length ? clamp012(hyps.filter((h) => /missing_authorization/i.test(h.type)).length / hyps.length) : 0,
|
|
18609
|
+
vulnerability_classes: clamp012(hypTypes.size / 10),
|
|
18610
|
+
attack_vectors: clamp012(planNextActions(hyps, mission).length / 20),
|
|
18611
|
+
escalation_chains: clamp012((byType.attack_chain ?? 0) / 57)
|
|
18612
|
+
};
|
|
18613
|
+
}
|
|
18614
|
+
function coverageGaps(coverage, threshold = 0.5) {
|
|
18615
|
+
return Object.entries(coverage).filter(([, v]) => v < threshold).map(([k]) => k);
|
|
18616
|
+
}
|
|
18617
|
+
function gapAgent(dimension, isUrl) {
|
|
18618
|
+
if (dimension === "endpoints" && !isUrl)
|
|
18619
|
+
return "recon";
|
|
18620
|
+
if (dimension === "technologies" && !isUrl)
|
|
18621
|
+
return "source";
|
|
18622
|
+
return GAP_AGENT[dimension] ?? "analysis";
|
|
18623
|
+
}
|
|
18624
|
+
function scheduleCoverageTasks(mission, threshold = 0.5) {
|
|
18625
|
+
const coverage = computeCoverage(mission);
|
|
18626
|
+
const gaps = coverageGaps(coverage, threshold);
|
|
18627
|
+
const attempted = new Set(mission.tasks.map((t) => t.agent_type));
|
|
18628
|
+
const isUrl = /^https?:\/\//i.test(mission.target);
|
|
18629
|
+
const tasks = [];
|
|
18630
|
+
for (const gap of gaps) {
|
|
18631
|
+
const agent = gapAgent(gap, isUrl);
|
|
18632
|
+
if (attempted.has(agent))
|
|
18633
|
+
continue;
|
|
18634
|
+
if (!isUrl && agent === "web")
|
|
18635
|
+
continue;
|
|
18636
|
+
tasks.push(createTask({ objective: `close coverage gap: ${gap} (${coverage[gap].toFixed(2)})`, agent_type: agent, priority: 8 }));
|
|
18637
|
+
}
|
|
18638
|
+
return tasks;
|
|
18639
|
+
}
|
|
18640
|
+
var GAP_AGENT;
|
|
18641
|
+
var init_coverage = __esm(() => {
|
|
18642
|
+
init_planner();
|
|
18643
|
+
GAP_AGENT = {
|
|
18644
|
+
attack_surface: "recon",
|
|
18645
|
+
endpoints: "api",
|
|
18646
|
+
technologies: "web",
|
|
18647
|
+
source_files: "source",
|
|
18648
|
+
sink_classes: "source",
|
|
18649
|
+
auth_boundaries: "auth",
|
|
18650
|
+
authorization_boundaries: "auth",
|
|
18651
|
+
vulnerability_classes: "analysis",
|
|
18652
|
+
attack_vectors: "analysis",
|
|
18653
|
+
escalation_chains: "commander"
|
|
18654
|
+
};
|
|
18655
|
+
});
|
|
18656
|
+
|
|
18585
18657
|
// src/mission/control.ts
|
|
18586
18658
|
import { existsSync as existsSync8, statSync as statSync4 } from "node:fs";
|
|
18587
18659
|
function scopeAllowed(mission) {
|
|
@@ -18634,7 +18706,12 @@ function replan(mission) {
|
|
|
18634
18706
|
tasks = [...tasks, createTask({ objective: "generate the final report", agent_type: "reporter", risk: "low" })];
|
|
18635
18707
|
}
|
|
18636
18708
|
}
|
|
18637
|
-
|
|
18709
|
+
const coverage = computeCoverage(mission);
|
|
18710
|
+
const coverageTasks = scheduleCoverageTasks(mission);
|
|
18711
|
+
if (coverageTasks.length > 0) {
|
|
18712
|
+
tasks = [...tasks, ...coverageTasks];
|
|
18713
|
+
}
|
|
18714
|
+
return { ...mission, tasks, coverage: { dimensions: { ...mission.coverage.dimensions, ...coverage } } };
|
|
18638
18715
|
}
|
|
18639
18716
|
async function executeTask(task, mission, scope) {
|
|
18640
18717
|
const agent = agentFor(task.agent_type);
|
|
@@ -18738,6 +18815,7 @@ var init_control = __esm(() => {
|
|
|
18738
18815
|
init_state();
|
|
18739
18816
|
init_agents();
|
|
18740
18817
|
init_planner();
|
|
18818
|
+
init_coverage();
|
|
18741
18819
|
MODE_PROFILES = {
|
|
18742
18820
|
web: { agents: ["recon", "web", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
|
18743
18821
|
api: { agents: ["recon", "api", "auth", "validator", "reviewer", "reporter"], verify: true, risk: "medium" },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
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": {
|