blitzstrike 2.4.21 → 2.4.22
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 +11 -0
- package/dist/index.js +134 -111
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ 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.22] — 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Added — on-disk report persistence (reports/ folder)
|
|
11
|
+
|
|
12
|
+
- `generate_report` now WRITES the HackerOne-grade markdown/JSON report to
|
|
13
|
+
`~/.blitzstrike/reports/<scope-slug>-<timestamp>.md` (override via
|
|
14
|
+
`BLITZSTRIKE_REPORT_DIR`) and returns the saved path — an engagement now
|
|
15
|
+
produces an on-disk deliverable, not just an in-memory string.
|
|
16
|
+
- `run_engagement` / `run_autonomous` also persist their inline report to the
|
|
17
|
+
same folder (report.report.saved).
|
|
18
|
+
|
|
8
19
|
## [2.4.21] — 2026-09-14
|
|
9
20
|
|
|
10
21
|
### Security — eliminate the last shell-interpolation sites
|
package/dist/index.js
CHANGED
|
@@ -15493,9 +15493,9 @@ async function checkMcpServers() {
|
|
|
15493
15493
|
var init_mcp_status = () => {};
|
|
15494
15494
|
|
|
15495
15495
|
// src/sync.ts
|
|
15496
|
-
import { mkdirSync as
|
|
15497
|
-
import { join as
|
|
15498
|
-
import { homedir as
|
|
15496
|
+
import { mkdirSync as mkdirSync6, writeFileSync as writeFileSync7, readFileSync as readFileSync18, readdirSync as readdirSync7, statSync as statSync4, rmSync as rmSync4 } from "node:fs";
|
|
15497
|
+
import { join as join17 } from "node:path";
|
|
15498
|
+
import { homedir as homedir7 } from "node:os";
|
|
15499
15499
|
import { fileURLToPath as fileURLToPath9 } from "node:url";
|
|
15500
15500
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
15501
15501
|
function dirExists(p) {
|
|
@@ -15511,7 +15511,7 @@ function countFiles(dir) {
|
|
|
15511
15511
|
const walk = (d) => {
|
|
15512
15512
|
for (const e of readdirSync7(d, { withFileTypes: true })) {
|
|
15513
15513
|
if (e.isDirectory())
|
|
15514
|
-
walk(
|
|
15514
|
+
walk(join17(d, e.name));
|
|
15515
15515
|
else
|
|
15516
15516
|
n++;
|
|
15517
15517
|
}
|
|
@@ -15524,9 +15524,9 @@ function countFiles(dir) {
|
|
|
15524
15524
|
}
|
|
15525
15525
|
function syncData() {
|
|
15526
15526
|
if (!dirExists(DATA_ROOT2))
|
|
15527
|
-
|
|
15528
|
-
const payloadsPath =
|
|
15529
|
-
const templatesPath =
|
|
15527
|
+
mkdirSync6(DATA_ROOT2, { recursive: true });
|
|
15528
|
+
const payloadsPath = join17(DATA_ROOT2, "payloads");
|
|
15529
|
+
const templatesPath = join17(DATA_ROOT2, "templates");
|
|
15530
15530
|
const hasPayloads = dirExists(payloadsPath) && countFiles(payloadsPath) > 0;
|
|
15531
15531
|
const hasTemplates = dirExists(templatesPath) && countFiles(templatesPath) > 0;
|
|
15532
15532
|
if (hasPayloads && hasTemplates) {
|
|
@@ -15536,8 +15536,8 @@ function syncData() {
|
|
|
15536
15536
|
data_root: DATA_ROOT2
|
|
15537
15537
|
};
|
|
15538
15538
|
}
|
|
15539
|
-
const localPayloads =
|
|
15540
|
-
const localTemplates =
|
|
15539
|
+
const localPayloads = join17(ROOT7, "payloads");
|
|
15540
|
+
const localTemplates = join17(ROOT7, "templates");
|
|
15541
15541
|
let payloadsSynced = false;
|
|
15542
15542
|
let templatesSynced = false;
|
|
15543
15543
|
if (!hasPayloads && dirExists(localPayloads)) {
|
|
@@ -15550,7 +15550,7 @@ function syncData() {
|
|
|
15550
15550
|
}
|
|
15551
15551
|
const gitOk = spawnSync4("git", ["--version"]).status === 0;
|
|
15552
15552
|
if (gitOk && (!dirExists(payloadsPath) || countFiles(payloadsPath) === 0 || !dirExists(templatesPath) || countFiles(templatesPath) === 0)) {
|
|
15553
|
-
const tmp =
|
|
15553
|
+
const tmp = join17(DATA_ROOT2, ".tmp-clone");
|
|
15554
15554
|
if (dirExists(tmp))
|
|
15555
15555
|
rmSync4(tmp, { recursive: true, force: true });
|
|
15556
15556
|
const r = spawnSync4("git", ["clone", "--depth", "1", "--filter=blob:none", "--sparse", GITHUB_REPO, tmp], { timeout: 120000 });
|
|
@@ -15558,11 +15558,11 @@ function syncData() {
|
|
|
15558
15558
|
const sparse = spawnSync4("git", ["-C", tmp, "sparse-checkout", "set", "payloads", "templates"], { timeout: 120000 });
|
|
15559
15559
|
if (sparse.status === 0) {
|
|
15560
15560
|
if (!dirExists(payloadsPath) || countFiles(payloadsPath) === 0) {
|
|
15561
|
-
copyDir(
|
|
15561
|
+
copyDir(join17(tmp, "payloads"), payloadsPath);
|
|
15562
15562
|
payloadsSynced = true;
|
|
15563
15563
|
}
|
|
15564
15564
|
if (!dirExists(templatesPath) || countFiles(templatesPath) === 0) {
|
|
15565
|
-
copyDir(
|
|
15565
|
+
copyDir(join17(tmp, "templates"), templatesPath);
|
|
15566
15566
|
templatesSynced = true;
|
|
15567
15567
|
}
|
|
15568
15568
|
}
|
|
@@ -15582,20 +15582,20 @@ function copyDir(src, dst) {
|
|
|
15582
15582
|
}
|
|
15583
15583
|
}
|
|
15584
15584
|
function manualCopy(src, dst) {
|
|
15585
|
-
|
|
15585
|
+
mkdirSync6(dst, { recursive: true });
|
|
15586
15586
|
for (const e of readdirSync7(src, { withFileTypes: true })) {
|
|
15587
|
-
const s =
|
|
15588
|
-
const d =
|
|
15587
|
+
const s = join17(src, e.name);
|
|
15588
|
+
const d = join17(dst, e.name);
|
|
15589
15589
|
if (e.isDirectory())
|
|
15590
15590
|
manualCopy(s, d);
|
|
15591
15591
|
else
|
|
15592
|
-
|
|
15592
|
+
writeFileSync7(d, readFileSync18(s));
|
|
15593
15593
|
}
|
|
15594
15594
|
}
|
|
15595
15595
|
var ROOT7, DATA_ROOT2, GITHUB_REPO = "https://github.com/shinthink/blitzstrike.git";
|
|
15596
15596
|
var init_sync = __esm(() => {
|
|
15597
|
-
ROOT7 =
|
|
15598
|
-
DATA_ROOT2 = process.env.BLITZSTRIKE_DATA ??
|
|
15597
|
+
ROOT7 = join17(fileURLToPath9(new URL(".", import.meta.url)), "..");
|
|
15598
|
+
DATA_ROOT2 = process.env.BLITZSTRIKE_DATA ?? join17(homedir7(), ".blitzstrike", "data");
|
|
15599
15599
|
});
|
|
15600
15600
|
|
|
15601
15601
|
// src/update.ts
|
|
@@ -15641,14 +15641,14 @@ var init_update = __esm(() => {
|
|
|
15641
15641
|
|
|
15642
15642
|
// src/release.ts
|
|
15643
15643
|
import { readFileSync as readFileSync20, existsSync as existsSync10 } from "node:fs";
|
|
15644
|
-
import { join as
|
|
15644
|
+
import { join as join18 } from "node:path";
|
|
15645
15645
|
import { fileURLToPath as fileURLToPath10 } from "node:url";
|
|
15646
15646
|
import { execSync as execSync2 } from "node:child_process";
|
|
15647
15647
|
function validateRelease() {
|
|
15648
15648
|
const checks = [];
|
|
15649
15649
|
checks.push({ name: "package.json version", ok: true, detail: VERSION });
|
|
15650
15650
|
try {
|
|
15651
|
-
const changelog = readFileSync20(
|
|
15651
|
+
const changelog = readFileSync20(join18(ROOT8, "CHANGELOG.md"), "utf8");
|
|
15652
15652
|
const m = changelog.match(/^##\s+\[([0-9]+\.[0-9]+\.[0-9]+)\]/m);
|
|
15653
15653
|
const changelogVersion = m?.[1] ?? null;
|
|
15654
15654
|
checks.push({
|
|
@@ -15680,22 +15680,22 @@ function validateRelease() {
|
|
|
15680
15680
|
return { version: VERSION, checks, consistent: checks.filter((c) => !c.soft).every((c) => c.ok) };
|
|
15681
15681
|
}
|
|
15682
15682
|
function lockfilePresent() {
|
|
15683
|
-
return existsSync10(
|
|
15683
|
+
return existsSync10(join18(ROOT8, "package-lock.json")) || existsSync10(join18(ROOT8, "bun.lock")) || existsSync10(join18(ROOT8, "bun.lockb"));
|
|
15684
15684
|
}
|
|
15685
15685
|
var ROOT8;
|
|
15686
15686
|
var init_release = __esm(() => {
|
|
15687
15687
|
init_version();
|
|
15688
|
-
ROOT8 =
|
|
15688
|
+
ROOT8 = join18(fileURLToPath10(new URL(".", import.meta.url)), "..");
|
|
15689
15689
|
});
|
|
15690
15690
|
|
|
15691
15691
|
// src/dependency.ts
|
|
15692
15692
|
import { readFileSync as readFileSync21 } from "node:fs";
|
|
15693
|
-
import { join as
|
|
15693
|
+
import { join as join19 } from "node:path";
|
|
15694
15694
|
import { fileURLToPath as fileURLToPath11 } from "node:url";
|
|
15695
15695
|
function checkDependencies() {
|
|
15696
15696
|
let pkg = {};
|
|
15697
15697
|
try {
|
|
15698
|
-
pkg = JSON.parse(readFileSync21(
|
|
15698
|
+
pkg = JSON.parse(readFileSync21(join19(ROOT9, "package.json"), "utf8"));
|
|
15699
15699
|
} catch {
|
|
15700
15700
|
return { install_scripts: [], git_dependencies: [], total_dependencies: 0, safe: false };
|
|
15701
15701
|
}
|
|
@@ -15718,13 +15718,13 @@ function checkDependencies() {
|
|
|
15718
15718
|
}
|
|
15719
15719
|
var ROOT9;
|
|
15720
15720
|
var init_dependency = __esm(() => {
|
|
15721
|
-
ROOT9 =
|
|
15721
|
+
ROOT9 = join19(fileURLToPath11(new URL(".", import.meta.url)), "..");
|
|
15722
15722
|
});
|
|
15723
15723
|
|
|
15724
15724
|
// src/cli.ts
|
|
15725
|
-
import { readFileSync as readFileSync22, existsSync as existsSync11, writeFileSync as
|
|
15726
|
-
import { join as
|
|
15727
|
-
import { homedir as
|
|
15725
|
+
import { readFileSync as readFileSync22, existsSync as existsSync11, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7 } from "node:fs";
|
|
15726
|
+
import { join as join20, dirname as dirname2 } from "node:path";
|
|
15727
|
+
import { homedir as homedir8 } from "node:os";
|
|
15728
15728
|
import { fileURLToPath as fileURLToPath12 } from "node:url";
|
|
15729
15729
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
15730
15730
|
function which(cmd) {
|
|
@@ -15768,7 +15768,7 @@ async function runDoctor() {
|
|
|
15768
15768
|
detail: h1 ? `X-HackerOne-Research: ${h1}` : "H1_USERNAME not set",
|
|
15769
15769
|
fix: h1 ? undefined : "export H1_USERNAME=<your-hackerone-username> (adds X-HackerOne-Research to outbound requests)"
|
|
15770
15770
|
});
|
|
15771
|
-
const dataOk = existsSync11(
|
|
15771
|
+
const dataOk = existsSync11(join20(ROOT10, "chains.json")) && existsSync11(join20(ROOT10, "tools-catalog.json"));
|
|
15772
15772
|
issues.push({
|
|
15773
15773
|
name: "Data layers (chains + tools-catalog)",
|
|
15774
15774
|
status: dataOk ? "ok" : "fail",
|
|
@@ -15819,14 +15819,14 @@ BlitzStrike — ${verdict}`);
|
|
|
15819
15819
|
function resolveCommand() {
|
|
15820
15820
|
if (which("blitzstrike"))
|
|
15821
15821
|
return { command: "blitzstrike", args: ["serve", "--mcp"] };
|
|
15822
|
-
const src =
|
|
15822
|
+
const src = join20(ROOT10, "src", "index.ts");
|
|
15823
15823
|
if (which("bun") && existsSync11(src))
|
|
15824
15824
|
return { command: "bun", args: ["run", src, "serve", "--mcp"] };
|
|
15825
15825
|
if (which("npx"))
|
|
15826
15826
|
return { command: "npx", args: ["-y", "blitzstrike", "serve", "--mcp"] };
|
|
15827
15827
|
if (which("bunx"))
|
|
15828
15828
|
return { command: "bunx", args: ["blitzstrike", "serve", "--mcp"] };
|
|
15829
|
-
const dist =
|
|
15829
|
+
const dist = join20(ROOT10, "dist", "index.js");
|
|
15830
15830
|
if (existsSync11(dist))
|
|
15831
15831
|
return { command: "bun", args: [dist, "serve", "--mcp"] };
|
|
15832
15832
|
return { command: "npx", args: ["-y", "blitzstrike", "serve", "--mcp"] };
|
|
@@ -15842,41 +15842,41 @@ function jsonMcpServersWrite(p) {
|
|
|
15842
15842
|
return (command, args) => {
|
|
15843
15843
|
const dir = dirname2(p);
|
|
15844
15844
|
if (!existsSync11(dir))
|
|
15845
|
-
|
|
15845
|
+
mkdirSync7(dir, { recursive: true });
|
|
15846
15846
|
const existing = readJson(p) ?? {};
|
|
15847
15847
|
existing.mcpServers = {
|
|
15848
15848
|
...existing.mcpServers ?? {},
|
|
15849
15849
|
blitzstrike: { command, args }
|
|
15850
15850
|
};
|
|
15851
|
-
|
|
15851
|
+
writeFileSync8(p, JSON.stringify(existing, null, 2));
|
|
15852
15852
|
};
|
|
15853
15853
|
}
|
|
15854
15854
|
function opencodeWrite(p) {
|
|
15855
15855
|
return (command, args) => {
|
|
15856
15856
|
const dir = dirname2(p);
|
|
15857
15857
|
if (!existsSync11(dir))
|
|
15858
|
-
|
|
15858
|
+
mkdirSync7(dir, { recursive: true });
|
|
15859
15859
|
const existing = readJson(p) ?? {};
|
|
15860
15860
|
existing.mcp = {
|
|
15861
15861
|
...existing.mcp ?? {},
|
|
15862
15862
|
blitzstrike: { type: "local", command: [command, ...args], enabled: true }
|
|
15863
15863
|
};
|
|
15864
|
-
|
|
15864
|
+
writeFileSync8(p, JSON.stringify(existing, null, 2));
|
|
15865
15865
|
copyOpenCodeAgents();
|
|
15866
15866
|
};
|
|
15867
15867
|
}
|
|
15868
15868
|
function copyOpenCodeAgents() {
|
|
15869
|
-
const srcDir =
|
|
15870
|
-
const dstDir =
|
|
15869
|
+
const srcDir = join20(ROOT10, "opencode-agents");
|
|
15870
|
+
const dstDir = join20(homedir8(), ".config", "opencode", "agents");
|
|
15871
15871
|
if (!existsSync11(srcDir))
|
|
15872
15872
|
return;
|
|
15873
15873
|
if (!existsSync11(dstDir))
|
|
15874
|
-
|
|
15874
|
+
mkdirSync7(dstDir, { recursive: true });
|
|
15875
15875
|
for (const f of ["Blitz Strike.md", "Blitz.md", "Eagle Eye.md", "Strike.md"]) {
|
|
15876
|
-
const src =
|
|
15877
|
-
const dst =
|
|
15876
|
+
const src = join20(srcDir, f);
|
|
15877
|
+
const dst = join20(dstDir, f);
|
|
15878
15878
|
if (existsSync11(src)) {
|
|
15879
|
-
|
|
15879
|
+
writeFileSync8(dst, readFileSync22(src, "utf8"));
|
|
15880
15880
|
}
|
|
15881
15881
|
}
|
|
15882
15882
|
}
|
|
@@ -15884,7 +15884,7 @@ function codexWrite(p) {
|
|
|
15884
15884
|
return (command, args) => {
|
|
15885
15885
|
const dir = dirname2(p);
|
|
15886
15886
|
if (!existsSync11(dir))
|
|
15887
|
-
|
|
15887
|
+
mkdirSync7(dir, { recursive: true });
|
|
15888
15888
|
let existing = existsSync11(p) ? readFileSync22(p, "utf8") : "";
|
|
15889
15889
|
if (!existing.trimEnd().endsWith(`
|
|
15890
15890
|
`))
|
|
@@ -15896,14 +15896,14 @@ function codexWrite(p) {
|
|
|
15896
15896
|
command = "${command}"
|
|
15897
15897
|
args = ${JSON.stringify(args)}
|
|
15898
15898
|
`;
|
|
15899
|
-
|
|
15899
|
+
writeFileSync8(p, existing);
|
|
15900
15900
|
};
|
|
15901
15901
|
}
|
|
15902
15902
|
function hermesWrite(p) {
|
|
15903
15903
|
return (command, args) => {
|
|
15904
15904
|
const dir = dirname2(p);
|
|
15905
15905
|
if (!existsSync11(dir))
|
|
15906
|
-
|
|
15906
|
+
mkdirSync7(dir, { recursive: true });
|
|
15907
15907
|
let existing = existsSync11(p) ? readFileSync22(p, "utf8") : "";
|
|
15908
15908
|
existing = existing.replace(/^ blitzstrike:\n(?: .*\n?)*/m, "");
|
|
15909
15909
|
if (!existing.trimEnd().endsWith(`
|
|
@@ -15925,80 +15925,80 @@ mcp_servers:
|
|
|
15925
15925
|
args: ${JSON.stringify(args)}
|
|
15926
15926
|
`;
|
|
15927
15927
|
}
|
|
15928
|
-
|
|
15928
|
+
writeFileSync8(p, existing);
|
|
15929
15929
|
};
|
|
15930
15930
|
}
|
|
15931
15931
|
function detectAgents() {
|
|
15932
|
-
const home =
|
|
15932
|
+
const home = homedir8();
|
|
15933
15933
|
const agents = [];
|
|
15934
|
-
const claudeJson =
|
|
15934
|
+
const claudeJson = join20(home, ".claude.json");
|
|
15935
15935
|
agents.push({
|
|
15936
15936
|
name: "Claude Code",
|
|
15937
15937
|
detectPath: claudeJson,
|
|
15938
15938
|
installed: () => existsSync11(claudeJson) || which("claude"),
|
|
15939
15939
|
write: jsonMcpServersWrite(claudeJson)
|
|
15940
15940
|
});
|
|
15941
|
-
const claudeDesktop =
|
|
15941
|
+
const claudeDesktop = join20(home, ".config", "Claude", "claude_desktop_config.json");
|
|
15942
15942
|
agents.push({
|
|
15943
15943
|
name: "Claude Desktop",
|
|
15944
15944
|
detectPath: claudeDesktop,
|
|
15945
15945
|
installed: () => existsSync11(claudeDesktop),
|
|
15946
15946
|
write: jsonMcpServersWrite(claudeDesktop)
|
|
15947
15947
|
});
|
|
15948
|
-
const cursor =
|
|
15948
|
+
const cursor = join20(home, ".cursor", "mcp.json");
|
|
15949
15949
|
agents.push({
|
|
15950
15950
|
name: "Cursor",
|
|
15951
15951
|
detectPath: cursor,
|
|
15952
|
-
installed: () => existsSync11(
|
|
15952
|
+
installed: () => existsSync11(join20(home, ".cursor")) || which("cursor"),
|
|
15953
15953
|
write: jsonMcpServersWrite(cursor)
|
|
15954
15954
|
});
|
|
15955
|
-
const opencode =
|
|
15955
|
+
const opencode = join20(home, ".config", "opencode", "opencode.jsonc");
|
|
15956
15956
|
agents.push({
|
|
15957
15957
|
name: "OpenCode",
|
|
15958
15958
|
detectPath: opencode,
|
|
15959
|
-
installed: () => existsSync11(
|
|
15959
|
+
installed: () => existsSync11(join20(home, ".config", "opencode")) || which("opencode"),
|
|
15960
15960
|
write: opencodeWrite(opencode)
|
|
15961
15961
|
});
|
|
15962
|
-
const codex =
|
|
15962
|
+
const codex = join20(home, ".codex", "config.toml");
|
|
15963
15963
|
agents.push({
|
|
15964
15964
|
name: "Codex",
|
|
15965
15965
|
detectPath: codex,
|
|
15966
|
-
installed: () => existsSync11(
|
|
15966
|
+
installed: () => existsSync11(join20(home, ".codex")) || which("codex"),
|
|
15967
15967
|
write: codexWrite(codex)
|
|
15968
15968
|
});
|
|
15969
|
-
const hermes =
|
|
15969
|
+
const hermes = join20(home, ".hermes", "config.yaml");
|
|
15970
15970
|
agents.push({
|
|
15971
15971
|
name: "Hermes",
|
|
15972
15972
|
detectPath: hermes,
|
|
15973
|
-
installed: () => existsSync11(
|
|
15973
|
+
installed: () => existsSync11(join20(home, ".hermes")) || which("hermes"),
|
|
15974
15974
|
write: hermesWrite(hermes)
|
|
15975
15975
|
});
|
|
15976
|
-
const gemini =
|
|
15976
|
+
const gemini = join20(home, ".gemini", "settings.json");
|
|
15977
15977
|
agents.push({
|
|
15978
15978
|
name: "Gemini CLI",
|
|
15979
15979
|
detectPath: gemini,
|
|
15980
|
-
installed: () => existsSync11(
|
|
15980
|
+
installed: () => existsSync11(join20(home, ".gemini")) || which("gemini"),
|
|
15981
15981
|
write: jsonMcpServersWrite(gemini)
|
|
15982
15982
|
});
|
|
15983
|
-
const windsurf =
|
|
15983
|
+
const windsurf = join20(home, ".codeium", "windsurf", "mcp_config.json");
|
|
15984
15984
|
agents.push({
|
|
15985
15985
|
name: "Windsurf",
|
|
15986
15986
|
detectPath: windsurf,
|
|
15987
|
-
installed: () => existsSync11(
|
|
15987
|
+
installed: () => existsSync11(join20(home, ".codeium")) || which("windsurf"),
|
|
15988
15988
|
write: jsonMcpServersWrite(windsurf)
|
|
15989
15989
|
});
|
|
15990
|
-
const copilot =
|
|
15990
|
+
const copilot = join20(home, ".copilot", "mcp.json");
|
|
15991
15991
|
agents.push({
|
|
15992
15992
|
name: "Copilot",
|
|
15993
15993
|
detectPath: copilot,
|
|
15994
|
-
installed: () => existsSync11(
|
|
15994
|
+
installed: () => existsSync11(join20(home, ".copilot")),
|
|
15995
15995
|
write: jsonMcpServersWrite(copilot)
|
|
15996
15996
|
});
|
|
15997
|
-
const cline =
|
|
15997
|
+
const cline = join20(home, ".cline", "mcp_settings.json");
|
|
15998
15998
|
agents.push({
|
|
15999
15999
|
name: "Cline",
|
|
16000
16000
|
detectPath: cline,
|
|
16001
|
-
installed: () => existsSync11(
|
|
16001
|
+
installed: () => existsSync11(join20(home, ".cline")),
|
|
16002
16002
|
write: jsonMcpServersWrite(cline)
|
|
16003
16003
|
});
|
|
16004
16004
|
return agents;
|
|
@@ -16116,7 +16116,7 @@ var init_cli = __esm(() => {
|
|
|
16116
16116
|
init_release();
|
|
16117
16117
|
init_dependency();
|
|
16118
16118
|
init_mcp_status();
|
|
16119
|
-
ROOT10 =
|
|
16119
|
+
ROOT10 = join20(fileURLToPath12(new URL(".", import.meta.url)), "..");
|
|
16120
16120
|
});
|
|
16121
16121
|
|
|
16122
16122
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -30838,7 +30838,7 @@ async function nvdLookup(cveId) {
|
|
|
30838
30838
|
// src/orchestrator.ts
|
|
30839
30839
|
init_scanner();
|
|
30840
30840
|
import { readFileSync as readFileSync8, existsSync as existsSync6, statSync as statSync2 } from "node:fs";
|
|
30841
|
-
import { join as
|
|
30841
|
+
import { join as join10 } from "node:path";
|
|
30842
30842
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
30843
30843
|
|
|
30844
30844
|
// src/memory.ts
|
|
@@ -33115,6 +33115,9 @@ function cvssAssess(input) {
|
|
|
33115
33115
|
}
|
|
33116
33116
|
|
|
33117
33117
|
// src/report.ts
|
|
33118
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync4 } from "node:fs";
|
|
33119
|
+
import { join as join9 } from "node:path";
|
|
33120
|
+
import { homedir as homedir6 } from "node:os";
|
|
33118
33121
|
var SEVERITY_METRICS = {
|
|
33119
33122
|
critical: { AV: "N", AC: "L", PR: "N", UI: "N", S: "U", C: "H", I: "H", A: "H" },
|
|
33120
33123
|
high: { AV: "N", AC: "L", PR: "L", UI: "N", S: "U", C: "H", I: "H", A: "N" },
|
|
@@ -33317,6 +33320,21 @@ function reportJson(findings, opts = {}) {
|
|
|
33317
33320
|
};
|
|
33318
33321
|
return JSON.stringify(payload, null, 2);
|
|
33319
33322
|
}
|
|
33323
|
+
var REPORT_DIR = process.env.BLITZSTRIKE_REPORT_DIR ?? join9(homedir6(), ".blitzstrike", "reports");
|
|
33324
|
+
function slugify2(s) {
|
|
33325
|
+
const slug = s.toLowerCase().replace(/^https?:\/\//, "").replace(/[^a-z0-9.-]+/g, "-").replace(/^-+|-+$/g, "").replace(/\./g, "_").slice(0, 60);
|
|
33326
|
+
return slug || "engagement";
|
|
33327
|
+
}
|
|
33328
|
+
function saveReport(content, opts = {}) {
|
|
33329
|
+
mkdirSync4(REPORT_DIR, { recursive: true });
|
|
33330
|
+
const slug = slugify2(opts.scope ?? opts.title ?? "engagement");
|
|
33331
|
+
const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
33332
|
+
const ext = opts.format === "json" ? "json" : "md";
|
|
33333
|
+
const filename = `${slug}-${ts}.${ext}`;
|
|
33334
|
+
const path = join9(REPORT_DIR, filename);
|
|
33335
|
+
writeFileSync2(path, content, "utf8");
|
|
33336
|
+
return { path, dir: REPORT_DIR, filename };
|
|
33337
|
+
}
|
|
33320
33338
|
|
|
33321
33339
|
// src/sarif.ts
|
|
33322
33340
|
init_version();
|
|
@@ -33910,8 +33928,8 @@ function loadChains() {
|
|
|
33910
33928
|
if (_chainsCache)
|
|
33911
33929
|
return _chainsCache;
|
|
33912
33930
|
try {
|
|
33913
|
-
const dir =
|
|
33914
|
-
const path =
|
|
33931
|
+
const dir = join10(fileURLToPath5(new URL(".", import.meta.url)), "..");
|
|
33932
|
+
const path = join10(dir, "chains.json");
|
|
33915
33933
|
const raw = JSON.parse(readFileSync8(path, "utf8"));
|
|
33916
33934
|
_chainsCache = raw.chains ?? [];
|
|
33917
33935
|
return _chainsCache;
|
|
@@ -34136,7 +34154,8 @@ function runEngagement(target, scope = "", mode = "bug-bounty", maxFiles = 2000,
|
|
|
34136
34154
|
summary: JSON.parse(reportJsonText).summary ?? null,
|
|
34137
34155
|
markdown: reportMarkdownText,
|
|
34138
34156
|
json: reportJsonText,
|
|
34139
|
-
sarif: sarifDoc
|
|
34157
|
+
sarif: sarifDoc,
|
|
34158
|
+
saved: saveReport(reportMarkdownText, { title: reportTitle, scope: target, version: VERSION, format: "markdown" }).path
|
|
34140
34159
|
};
|
|
34141
34160
|
report.status = "DETECTED";
|
|
34142
34161
|
report.note = "Detection complete — verification is the NEXT mandatory step (do not stop here). " + "Every finding is a HYPOTHESIS until verified: strike_verify (HTTP reflection, marker + negative control), " + "verify_file_read (CWE-22 / path traversal), or drive_devtools (DOM/JS precision). " + "Verify each finding NOW, then generate_report. Never deliver a report with unverified findings.";
|
|
@@ -34689,8 +34708,8 @@ var CHAIN_ID_TO_ESCALATION = {
|
|
|
34689
34708
|
};
|
|
34690
34709
|
function loadChainLinks() {
|
|
34691
34710
|
try {
|
|
34692
|
-
const dir =
|
|
34693
|
-
const data = JSON.parse(readFileSync8(
|
|
34711
|
+
const dir = join10(fileURLToPath5(new URL(".", import.meta.url)), "..");
|
|
34712
|
+
const data = JSON.parse(readFileSync8(join10(dir, "intelligence", "chain_links.json"), "utf8"));
|
|
34694
34713
|
return data.links ?? [];
|
|
34695
34714
|
} catch {
|
|
34696
34715
|
return [];
|
|
@@ -34846,14 +34865,14 @@ function compactState(phase, findings) {
|
|
|
34846
34865
|
}
|
|
34847
34866
|
|
|
34848
34867
|
// src/tasks.ts
|
|
34849
|
-
import { mkdirSync as
|
|
34850
|
-
import { join as
|
|
34868
|
+
import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync3 } from "node:fs";
|
|
34869
|
+
import { join as join11 } from "node:path";
|
|
34851
34870
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
34852
34871
|
function tasksDir() {
|
|
34853
|
-
return
|
|
34872
|
+
return join11(fileURLToPath6(new URL(".", import.meta.url)), "..", ".blitzstrike", "tasks");
|
|
34854
34873
|
}
|
|
34855
34874
|
function taskPath(id) {
|
|
34856
|
-
return
|
|
34875
|
+
return join11(tasksDir(), `${id}.json`);
|
|
34857
34876
|
}
|
|
34858
34877
|
function load(id) {
|
|
34859
34878
|
try {
|
|
@@ -34863,8 +34882,8 @@ function load(id) {
|
|
|
34863
34882
|
}
|
|
34864
34883
|
}
|
|
34865
34884
|
function save(t) {
|
|
34866
|
-
|
|
34867
|
-
|
|
34885
|
+
mkdirSync5(tasksDir(), { recursive: true });
|
|
34886
|
+
writeFileSync3(taskPath(t.task_id), JSON.stringify(t, null, 2));
|
|
34868
34887
|
}
|
|
34869
34888
|
function taskStart(id, objective, plan) {
|
|
34870
34889
|
const now = Date.now();
|
|
@@ -35161,8 +35180,8 @@ function engagementStatus() {
|
|
|
35161
35180
|
|
|
35162
35181
|
// src/incremental.ts
|
|
35163
35182
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
35164
|
-
import { writeFileSync as
|
|
35165
|
-
import { join as
|
|
35183
|
+
import { writeFileSync as writeFileSync4, mkdtempSync, rmSync } from "node:fs";
|
|
35184
|
+
import { join as join12 } from "node:path";
|
|
35166
35185
|
import { tmpdir } from "node:os";
|
|
35167
35186
|
|
|
35168
35187
|
// src/eagle2.ts
|
|
@@ -54677,9 +54696,9 @@ function analyzeChangedFiles(repo, base = "HEAD~1", head = "HEAD") {
|
|
|
54677
54696
|
continue;
|
|
54678
54697
|
const lang = detectLanguage(file)?.language;
|
|
54679
54698
|
if (lang === "php") {
|
|
54680
|
-
const dir = mkdtempSync(
|
|
54681
|
-
const tmp =
|
|
54682
|
-
|
|
54699
|
+
const dir = mkdtempSync(join12(tmpdir(), "blitz-incr-"));
|
|
54700
|
+
const tmp = join12(dir, "changed.php");
|
|
54701
|
+
writeFileSync4(tmp, code);
|
|
54683
54702
|
try {
|
|
54684
54703
|
const r = analyzeDataFlow2(tmp);
|
|
54685
54704
|
for (const f of r.findings)
|
|
@@ -55091,16 +55110,16 @@ function taintTree(root, maxFiles = 2000) {
|
|
|
55091
55110
|
}
|
|
55092
55111
|
|
|
55093
55112
|
// src/differential.ts
|
|
55094
|
-
import { writeFileSync as
|
|
55095
|
-
import { join as
|
|
55113
|
+
import { writeFileSync as writeFileSync5, rmSync as rmSync2, mkdtempSync as mkdtempSync2, readFileSync as readFileSync14 } from "node:fs";
|
|
55114
|
+
import { join as join13 } from "node:path";
|
|
55096
55115
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
55097
55116
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
55098
55117
|
init_scanner();
|
|
55099
55118
|
function runEngine(code, language, file) {
|
|
55100
55119
|
if (language === "php") {
|
|
55101
|
-
const dir = mkdtempSync2(
|
|
55102
|
-
const tmp =
|
|
55103
|
-
|
|
55120
|
+
const dir = mkdtempSync2(join13(tmpdir2(), "blitz-diff-"));
|
|
55121
|
+
const tmp = join13(dir, "old.php");
|
|
55122
|
+
writeFileSync5(tmp, code);
|
|
55104
55123
|
try {
|
|
55105
55124
|
const r = analyzeDataFlow2(tmp);
|
|
55106
55125
|
return r.findings.map((f) => ({ sink: f.sink, sink_line: f.sink_line, category: f.category, source: f.source, cwe: f.cwe }));
|
|
@@ -55285,15 +55304,15 @@ function analyzeGitDiff(repo, base = "HEAD~1", head = "HEAD") {
|
|
|
55285
55304
|
|
|
55286
55305
|
// src/frameworks.ts
|
|
55287
55306
|
import { readFileSync as readFileSync15, existsSync as existsSync7 } from "node:fs";
|
|
55288
|
-
import { join as
|
|
55307
|
+
import { join as join14 } from "node:path";
|
|
55289
55308
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
55290
|
-
var ROOT4 =
|
|
55291
|
-
var INTEL2 =
|
|
55309
|
+
var ROOT4 = join14(fileURLToPath7(new URL(".", import.meta.url)), "..");
|
|
55310
|
+
var INTEL2 = join14(ROOT4, "intelligence");
|
|
55292
55311
|
var cache = null;
|
|
55293
55312
|
function load2() {
|
|
55294
55313
|
if (cache)
|
|
55295
55314
|
return cache;
|
|
55296
|
-
const p =
|
|
55315
|
+
const p = join14(INTEL2, "frameworks.json");
|
|
55297
55316
|
if (!existsSync7(p))
|
|
55298
55317
|
return null;
|
|
55299
55318
|
try {
|
|
@@ -56050,12 +56069,12 @@ function nextSteps(ctx) {
|
|
|
56050
56069
|
}
|
|
56051
56070
|
|
|
56052
56071
|
// src/benchmark.ts
|
|
56053
|
-
import { readFileSync as readFileSync16, readdirSync as readdirSync5, writeFileSync as
|
|
56054
|
-
import { join as
|
|
56072
|
+
import { readFileSync as readFileSync16, readdirSync as readdirSync5, writeFileSync as writeFileSync6, rmSync as rmSync3 } from "node:fs";
|
|
56073
|
+
import { join as join15 } from "node:path";
|
|
56055
56074
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
56056
56075
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
56057
|
-
var ROOT5 =
|
|
56058
|
-
var CORPUS =
|
|
56076
|
+
var ROOT5 = join15(fileURLToPath8(new URL(".", import.meta.url)), "..");
|
|
56077
|
+
var CORPUS = join15(ROOT5, "bench", "corpus");
|
|
56059
56078
|
function parseCorpusFile(path) {
|
|
56060
56079
|
let text;
|
|
56061
56080
|
try {
|
|
@@ -56109,7 +56128,7 @@ function loadCorpus() {
|
|
|
56109
56128
|
for (const f of readdirSync5(CORPUS)) {
|
|
56110
56129
|
if (!f.endsWith(".md"))
|
|
56111
56130
|
continue;
|
|
56112
|
-
const e = parseCorpusFile(
|
|
56131
|
+
const e = parseCorpusFile(join15(CORPUS, f));
|
|
56113
56132
|
if (e)
|
|
56114
56133
|
entries.push(e);
|
|
56115
56134
|
}
|
|
@@ -56121,8 +56140,8 @@ function loadCorpus() {
|
|
|
56121
56140
|
function detect(entry) {
|
|
56122
56141
|
const lang = entry.language;
|
|
56123
56142
|
if (lang === "php") {
|
|
56124
|
-
const tmp =
|
|
56125
|
-
|
|
56143
|
+
const tmp = join15(tmpdir3(), `blitzstrike-bench-${entry.id}-${process.pid}.php`);
|
|
56144
|
+
writeFileSync6(tmp, entry.code);
|
|
56126
56145
|
const r = analyzeDataFlow2(tmp);
|
|
56127
56146
|
rmSync3(tmp, { force: true });
|
|
56128
56147
|
if (r.findings.length > 0)
|
|
@@ -56165,15 +56184,15 @@ function runBenchmark() {
|
|
|
56165
56184
|
|
|
56166
56185
|
// src/enterprise-benchmark.ts
|
|
56167
56186
|
import { existsSync as existsSync9, readFileSync as readFileSync17, readdirSync as readdirSync6, statSync as statSync3 } from "node:fs";
|
|
56168
|
-
import { join as
|
|
56187
|
+
import { join as join16, resolve } from "node:path";
|
|
56169
56188
|
var ROOT6 = resolve(process.cwd(), "bench", "enterprise");
|
|
56170
56189
|
var ENTERPRISE_FIXTURES = [
|
|
56171
|
-
{ id: "php-laravel", dir:
|
|
56172
|
-
{ id: "js-express", dir:
|
|
56173
|
-
{ id: "py-django", dir:
|
|
56174
|
-
{ id: "java-spring", dir:
|
|
56175
|
-
{ id: "wp-batch-route", dir:
|
|
56176
|
-
{ id: "php-complex", dir:
|
|
56190
|
+
{ id: "php-laravel", dir: join16(ROOT6, "php-laravel"), expected_vulns: 4 },
|
|
56191
|
+
{ id: "js-express", dir: join16(ROOT6, "js-express"), expected_vulns: 2 },
|
|
56192
|
+
{ id: "py-django", dir: join16(ROOT6, "py-django"), expected_vulns: 2 },
|
|
56193
|
+
{ id: "java-spring", dir: join16(ROOT6, "java-spring"), expected_vulns: 2 },
|
|
56194
|
+
{ id: "wp-batch-route", dir: join16(ROOT6, "wp-batch-route"), expected_vulns: 1 },
|
|
56195
|
+
{ id: "php-complex", dir: join16(ROOT6, "php-complex"), expected_vulns: 4 }
|
|
56177
56196
|
];
|
|
56178
56197
|
function sourceFiles(root) {
|
|
56179
56198
|
const out = [];
|
|
@@ -56185,7 +56204,7 @@ function sourceFiles(root) {
|
|
|
56185
56204
|
return;
|
|
56186
56205
|
}
|
|
56187
56206
|
for (const e of entries) {
|
|
56188
|
-
const p =
|
|
56207
|
+
const p = join16(dir, e);
|
|
56189
56208
|
let st;
|
|
56190
56209
|
try {
|
|
56191
56210
|
st = statSync3(p);
|
|
@@ -57788,9 +57807,13 @@ ${statusLine}` : statusLine },
|
|
|
57788
57807
|
} catch {
|
|
57789
57808
|
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid JSON" }) }] };
|
|
57790
57809
|
}
|
|
57810
|
+
const fmt = format ?? "markdown";
|
|
57791
57811
|
const opts = { title, scope, version: VERSION };
|
|
57792
|
-
const out =
|
|
57793
|
-
|
|
57812
|
+
const out = fmt === "json" ? reportJson(list, opts) : reportMarkdown(list, opts);
|
|
57813
|
+
const saved = saveReport(out, { title, scope, version: VERSION, format: fmt });
|
|
57814
|
+
return { content: [{ type: "text", text: `Report saved to: ${saved.path}
|
|
57815
|
+
|
|
57816
|
+
${out}` }] };
|
|
57794
57817
|
});
|
|
57795
57818
|
server.registerTool("run_benchmark", {
|
|
57796
57819
|
title: "Run the benchmark suite",
|
|
@@ -57832,12 +57855,12 @@ async function serve() {
|
|
|
57832
57855
|
// src/index.ts
|
|
57833
57856
|
init_cli();
|
|
57834
57857
|
import { readFileSync as readFileSync23, existsSync as existsSync12 } from "node:fs";
|
|
57835
|
-
import { join as
|
|
57858
|
+
import { join as join21 } from "node:path";
|
|
57836
57859
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
57837
|
-
var ROOT11 =
|
|
57860
|
+
var ROOT11 = join21(fileURLToPath13(new URL(".", import.meta.url)), "..");
|
|
57838
57861
|
function readVersion() {
|
|
57839
57862
|
try {
|
|
57840
|
-
const p =
|
|
57863
|
+
const p = join21(ROOT11, "package.json");
|
|
57841
57864
|
if (existsSync12(p))
|
|
57842
57865
|
return JSON.parse(readFileSync23(p, "utf8")).version ?? "1.0.0";
|
|
57843
57866
|
} catch {}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.22",
|
|
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": {
|