blitzstrike 2.4.27 → 2.4.29
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 +28 -0
- package/dist/index.js +484 -189
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -15466,11 +15466,11 @@ var require_src = __commonJS(function(exports, module) {
|
|
|
15466
15466
|
});
|
|
15467
15467
|
|
|
15468
15468
|
// src/mcp-status.ts
|
|
15469
|
-
import { existsSync as
|
|
15469
|
+
import { existsSync as existsSync9 } from "node:fs";
|
|
15470
15470
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
15471
15471
|
async function checkMcpServers() {
|
|
15472
15472
|
const out = [];
|
|
15473
|
-
const bin = ["/usr/bin/chrome-devtools-mcp", "/usr/local/bin/chrome-devtools-mcp"].find((p) =>
|
|
15473
|
+
const bin = ["/usr/bin/chrome-devtools-mcp", "/usr/local/bin/chrome-devtools-mcp"].find((p) => existsSync9(p));
|
|
15474
15474
|
const npxOk = spawnSync3("npx", ["--version"], { timeout: 8000 }).error === undefined;
|
|
15475
15475
|
const devtoolsOk = Boolean(bin) || npxOk;
|
|
15476
15476
|
out.push({
|
|
@@ -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 mkdirSync8, writeFileSync as writeFileSync7, readFileSync as readFileSync19, readdirSync as readdirSync7, statSync as statSync4, rmSync as rmSync4 } from "node:fs";
|
|
15497
|
+
import { join as join18 } from "node:path";
|
|
15498
|
+
import { homedir as homedir9 } 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(join18(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
|
+
mkdirSync8(DATA_ROOT2, { recursive: true });
|
|
15528
|
+
const payloadsPath = join18(DATA_ROOT2, "payloads");
|
|
15529
|
+
const templatesPath = join18(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 = join18(ROOT7, "payloads");
|
|
15540
|
+
const localTemplates = join18(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 = join18(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(join18(tmp, "payloads"), payloadsPath);
|
|
15562
15562
|
payloadsSynced = true;
|
|
15563
15563
|
}
|
|
15564
15564
|
if (!dirExists(templatesPath) || countFiles(templatesPath) === 0) {
|
|
15565
|
-
copyDir(
|
|
15565
|
+
copyDir(join18(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
|
+
mkdirSync8(dst, { recursive: true });
|
|
15586
15586
|
for (const e of readdirSync7(src, { withFileTypes: true })) {
|
|
15587
|
-
const s =
|
|
15588
|
-
const d =
|
|
15587
|
+
const s = join18(src, e.name);
|
|
15588
|
+
const d = join18(dst, e.name);
|
|
15589
15589
|
if (e.isDirectory())
|
|
15590
15590
|
manualCopy(s, d);
|
|
15591
15591
|
else
|
|
15592
|
-
writeFileSync7(d,
|
|
15592
|
+
writeFileSync7(d, readFileSync19(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 = join18(fileURLToPath9(new URL(".", import.meta.url)), "..");
|
|
15598
|
+
DATA_ROOT2 = process.env.BLITZSTRIKE_DATA ?? join18(homedir9(), ".blitzstrike", "data");
|
|
15599
15599
|
});
|
|
15600
15600
|
|
|
15601
15601
|
// src/update.ts
|
|
@@ -15640,15 +15640,15 @@ var init_update = __esm(() => {
|
|
|
15640
15640
|
});
|
|
15641
15641
|
|
|
15642
15642
|
// src/release.ts
|
|
15643
|
-
import { readFileSync as
|
|
15644
|
-
import { join as
|
|
15643
|
+
import { readFileSync as readFileSync21, existsSync as existsSync11 } from "node:fs";
|
|
15644
|
+
import { join as join19 } 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 =
|
|
15651
|
+
const changelog = readFileSync21(join19(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
|
|
15683
|
+
return existsSync11(join19(ROOT8, "package-lock.json")) || existsSync11(join19(ROOT8, "bun.lock")) || existsSync11(join19(ROOT8, "bun.lockb"));
|
|
15684
15684
|
}
|
|
15685
15685
|
var ROOT8;
|
|
15686
15686
|
var init_release = __esm(() => {
|
|
15687
15687
|
init_version();
|
|
15688
|
-
ROOT8 =
|
|
15688
|
+
ROOT8 = join19(fileURLToPath10(new URL(".", import.meta.url)), "..");
|
|
15689
15689
|
});
|
|
15690
15690
|
|
|
15691
15691
|
// src/dependency.ts
|
|
15692
|
-
import { readFileSync as
|
|
15693
|
-
import { join as
|
|
15692
|
+
import { readFileSync as readFileSync22 } from "node:fs";
|
|
15693
|
+
import { join as join20 } 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(
|
|
15698
|
+
pkg = JSON.parse(readFileSync22(join20(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 = join20(fileURLToPath11(new URL(".", import.meta.url)), "..");
|
|
15722
15722
|
});
|
|
15723
15723
|
|
|
15724
15724
|
// src/cli.ts
|
|
15725
|
-
import { readFileSync as
|
|
15726
|
-
import { join as
|
|
15727
|
-
import { homedir as
|
|
15725
|
+
import { readFileSync as readFileSync23, existsSync as existsSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync9 } from "node:fs";
|
|
15726
|
+
import { join as join21, dirname as dirname2 } from "node:path";
|
|
15727
|
+
import { homedir as homedir10 } 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 =
|
|
15771
|
+
const dataOk = existsSync12(join21(ROOT10, "chains.json")) && existsSync12(join21(ROOT10, "tools-catalog.json"));
|
|
15772
15772
|
issues.push({
|
|
15773
15773
|
name: "Data layers (chains + tools-catalog)",
|
|
15774
15774
|
status: dataOk ? "ok" : "fail",
|
|
@@ -15819,21 +15819,21 @@ BlitzStrike — ${verdict}`);
|
|
|
15819
15819
|
function resolveCommand() {
|
|
15820
15820
|
if (which("blitzstrike"))
|
|
15821
15821
|
return { command: "blitzstrike", args: ["serve", "--mcp"] };
|
|
15822
|
-
const src =
|
|
15823
|
-
if (which("bun") &&
|
|
15822
|
+
const src = join21(ROOT10, "src", "index.ts");
|
|
15823
|
+
if (which("bun") && existsSync12(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 =
|
|
15830
|
-
if (
|
|
15829
|
+
const dist = join21(ROOT10, "dist", "index.js");
|
|
15830
|
+
if (existsSync12(dist))
|
|
15831
15831
|
return { command: "bun", args: [dist, "serve", "--mcp"] };
|
|
15832
15832
|
return { command: "npx", args: ["-y", "blitzstrike", "serve", "--mcp"] };
|
|
15833
15833
|
}
|
|
15834
15834
|
function readJson(p) {
|
|
15835
15835
|
try {
|
|
15836
|
-
return JSON.parse(
|
|
15836
|
+
return JSON.parse(readFileSync23(p, "utf8"));
|
|
15837
15837
|
} catch {
|
|
15838
15838
|
return null;
|
|
15839
15839
|
}
|
|
@@ -15841,8 +15841,8 @@ function readJson(p) {
|
|
|
15841
15841
|
function jsonMcpServersWrite(p) {
|
|
15842
15842
|
return (command, args) => {
|
|
15843
15843
|
const dir = dirname2(p);
|
|
15844
|
-
if (!
|
|
15845
|
-
|
|
15844
|
+
if (!existsSync12(dir))
|
|
15845
|
+
mkdirSync9(dir, { recursive: true });
|
|
15846
15846
|
const existing = readJson(p) ?? {};
|
|
15847
15847
|
existing.mcpServers = {
|
|
15848
15848
|
...existing.mcpServers ?? {},
|
|
@@ -15854,8 +15854,8 @@ function jsonMcpServersWrite(p) {
|
|
|
15854
15854
|
function opencodeWrite(p) {
|
|
15855
15855
|
return (command, args) => {
|
|
15856
15856
|
const dir = dirname2(p);
|
|
15857
|
-
if (!
|
|
15858
|
-
|
|
15857
|
+
if (!existsSync12(dir))
|
|
15858
|
+
mkdirSync9(dir, { recursive: true });
|
|
15859
15859
|
const existing = readJson(p) ?? {};
|
|
15860
15860
|
existing.mcp = {
|
|
15861
15861
|
...existing.mcp ?? {},
|
|
@@ -15866,26 +15866,26 @@ function opencodeWrite(p) {
|
|
|
15866
15866
|
};
|
|
15867
15867
|
}
|
|
15868
15868
|
function copyOpenCodeAgents() {
|
|
15869
|
-
const srcDir =
|
|
15870
|
-
const dstDir =
|
|
15871
|
-
if (!
|
|
15869
|
+
const srcDir = join21(ROOT10, "opencode-agents");
|
|
15870
|
+
const dstDir = join21(homedir10(), ".config", "opencode", "agents");
|
|
15871
|
+
if (!existsSync12(srcDir))
|
|
15872
15872
|
return;
|
|
15873
|
-
if (!
|
|
15874
|
-
|
|
15873
|
+
if (!existsSync12(dstDir))
|
|
15874
|
+
mkdirSync9(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 =
|
|
15878
|
-
if (
|
|
15879
|
-
writeFileSync8(dst,
|
|
15876
|
+
const src = join21(srcDir, f);
|
|
15877
|
+
const dst = join21(dstDir, f);
|
|
15878
|
+
if (existsSync12(src)) {
|
|
15879
|
+
writeFileSync8(dst, readFileSync23(src, "utf8"));
|
|
15880
15880
|
}
|
|
15881
15881
|
}
|
|
15882
15882
|
}
|
|
15883
15883
|
function codexWrite(p) {
|
|
15884
15884
|
return (command, args) => {
|
|
15885
15885
|
const dir = dirname2(p);
|
|
15886
|
-
if (!
|
|
15887
|
-
|
|
15888
|
-
let existing =
|
|
15886
|
+
if (!existsSync12(dir))
|
|
15887
|
+
mkdirSync9(dir, { recursive: true });
|
|
15888
|
+
let existing = existsSync12(p) ? readFileSync23(p, "utf8") : "";
|
|
15889
15889
|
if (!existing.trimEnd().endsWith(`
|
|
15890
15890
|
`))
|
|
15891
15891
|
existing += `
|
|
@@ -15902,9 +15902,9 @@ args = ${JSON.stringify(args)}
|
|
|
15902
15902
|
function hermesWrite(p) {
|
|
15903
15903
|
return (command, args) => {
|
|
15904
15904
|
const dir = dirname2(p);
|
|
15905
|
-
if (!
|
|
15906
|
-
|
|
15907
|
-
let existing =
|
|
15905
|
+
if (!existsSync12(dir))
|
|
15906
|
+
mkdirSync9(dir, { recursive: true });
|
|
15907
|
+
let existing = existsSync12(p) ? readFileSync23(p, "utf8") : "";
|
|
15908
15908
|
existing = existing.replace(/^ blitzstrike:\n(?: .*\n?)*/m, "");
|
|
15909
15909
|
if (!existing.trimEnd().endsWith(`
|
|
15910
15910
|
`))
|
|
@@ -15929,76 +15929,76 @@ mcp_servers:
|
|
|
15929
15929
|
};
|
|
15930
15930
|
}
|
|
15931
15931
|
function detectAgents() {
|
|
15932
|
-
const home =
|
|
15932
|
+
const home = homedir10();
|
|
15933
15933
|
const agents = [];
|
|
15934
|
-
const claudeJson =
|
|
15934
|
+
const claudeJson = join21(home, ".claude.json");
|
|
15935
15935
|
agents.push({
|
|
15936
15936
|
name: "Claude Code",
|
|
15937
15937
|
detectPath: claudeJson,
|
|
15938
|
-
installed: () =>
|
|
15938
|
+
installed: () => existsSync12(claudeJson) || which("claude"),
|
|
15939
15939
|
write: jsonMcpServersWrite(claudeJson)
|
|
15940
15940
|
});
|
|
15941
|
-
const claudeDesktop =
|
|
15941
|
+
const claudeDesktop = join21(home, ".config", "Claude", "claude_desktop_config.json");
|
|
15942
15942
|
agents.push({
|
|
15943
15943
|
name: "Claude Desktop",
|
|
15944
15944
|
detectPath: claudeDesktop,
|
|
15945
|
-
installed: () =>
|
|
15945
|
+
installed: () => existsSync12(claudeDesktop),
|
|
15946
15946
|
write: jsonMcpServersWrite(claudeDesktop)
|
|
15947
15947
|
});
|
|
15948
|
-
const cursor =
|
|
15948
|
+
const cursor = join21(home, ".cursor", "mcp.json");
|
|
15949
15949
|
agents.push({
|
|
15950
15950
|
name: "Cursor",
|
|
15951
15951
|
detectPath: cursor,
|
|
15952
|
-
installed: () =>
|
|
15952
|
+
installed: () => existsSync12(join21(home, ".cursor")) || which("cursor"),
|
|
15953
15953
|
write: jsonMcpServersWrite(cursor)
|
|
15954
15954
|
});
|
|
15955
|
-
const opencode =
|
|
15955
|
+
const opencode = join21(home, ".config", "opencode", "opencode.jsonc");
|
|
15956
15956
|
agents.push({
|
|
15957
15957
|
name: "OpenCode",
|
|
15958
15958
|
detectPath: opencode,
|
|
15959
|
-
installed: () =>
|
|
15959
|
+
installed: () => existsSync12(join21(home, ".config", "opencode")) || which("opencode"),
|
|
15960
15960
|
write: opencodeWrite(opencode)
|
|
15961
15961
|
});
|
|
15962
|
-
const codex =
|
|
15962
|
+
const codex = join21(home, ".codex", "config.toml");
|
|
15963
15963
|
agents.push({
|
|
15964
15964
|
name: "Codex",
|
|
15965
15965
|
detectPath: codex,
|
|
15966
|
-
installed: () =>
|
|
15966
|
+
installed: () => existsSync12(join21(home, ".codex")) || which("codex"),
|
|
15967
15967
|
write: codexWrite(codex)
|
|
15968
15968
|
});
|
|
15969
|
-
const hermes =
|
|
15969
|
+
const hermes = join21(home, ".hermes", "config.yaml");
|
|
15970
15970
|
agents.push({
|
|
15971
15971
|
name: "Hermes",
|
|
15972
15972
|
detectPath: hermes,
|
|
15973
|
-
installed: () =>
|
|
15973
|
+
installed: () => existsSync12(join21(home, ".hermes")) || which("hermes"),
|
|
15974
15974
|
write: hermesWrite(hermes)
|
|
15975
15975
|
});
|
|
15976
|
-
const gemini =
|
|
15976
|
+
const gemini = join21(home, ".gemini", "settings.json");
|
|
15977
15977
|
agents.push({
|
|
15978
15978
|
name: "Gemini CLI",
|
|
15979
15979
|
detectPath: gemini,
|
|
15980
|
-
installed: () =>
|
|
15980
|
+
installed: () => existsSync12(join21(home, ".gemini")) || which("gemini"),
|
|
15981
15981
|
write: jsonMcpServersWrite(gemini)
|
|
15982
15982
|
});
|
|
15983
|
-
const windsurf =
|
|
15983
|
+
const windsurf = join21(home, ".codeium", "windsurf", "mcp_config.json");
|
|
15984
15984
|
agents.push({
|
|
15985
15985
|
name: "Windsurf",
|
|
15986
15986
|
detectPath: windsurf,
|
|
15987
|
-
installed: () =>
|
|
15987
|
+
installed: () => existsSync12(join21(home, ".codeium")) || which("windsurf"),
|
|
15988
15988
|
write: jsonMcpServersWrite(windsurf)
|
|
15989
15989
|
});
|
|
15990
|
-
const copilot =
|
|
15990
|
+
const copilot = join21(home, ".copilot", "mcp.json");
|
|
15991
15991
|
agents.push({
|
|
15992
15992
|
name: "Copilot",
|
|
15993
15993
|
detectPath: copilot,
|
|
15994
|
-
installed: () =>
|
|
15994
|
+
installed: () => existsSync12(join21(home, ".copilot")),
|
|
15995
15995
|
write: jsonMcpServersWrite(copilot)
|
|
15996
15996
|
});
|
|
15997
|
-
const cline =
|
|
15997
|
+
const cline = join21(home, ".cline", "mcp_settings.json");
|
|
15998
15998
|
agents.push({
|
|
15999
15999
|
name: "Cline",
|
|
16000
16000
|
detectPath: cline,
|
|
16001
|
-
installed: () =>
|
|
16001
|
+
installed: () => existsSync12(join21(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 = join21(fileURLToPath12(new URL(".", import.meta.url)), "..");
|
|
16120
16120
|
});
|
|
16121
16121
|
|
|
16122
16122
|
// node_modules/zod/v3/helpers/util.js
|
|
@@ -30754,7 +30754,7 @@ class StdioServerTransport {
|
|
|
30754
30754
|
|
|
30755
30755
|
// src/server.ts
|
|
30756
30756
|
init_scanner();
|
|
30757
|
-
import { readFileSync as
|
|
30757
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
30758
30758
|
|
|
30759
30759
|
// src/recon.ts
|
|
30760
30760
|
var TIMEOUT_MS = 25000;
|
|
@@ -30837,8 +30837,8 @@ async function nvdLookup(cveId) {
|
|
|
30837
30837
|
|
|
30838
30838
|
// src/orchestrator.ts
|
|
30839
30839
|
init_scanner();
|
|
30840
|
-
import { readFileSync as
|
|
30841
|
-
import { join as
|
|
30840
|
+
import { readFileSync as readFileSync9, existsSync as existsSync7, statSync as statSync2 } from "node:fs";
|
|
30841
|
+
import { join as join11 } from "node:path";
|
|
30842
30842
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
30843
30843
|
|
|
30844
30844
|
// src/memory.ts
|
|
@@ -32291,19 +32291,166 @@ function uniqueFindings(findings) {
|
|
|
32291
32291
|
}
|
|
32292
32292
|
|
|
32293
32293
|
// src/intel.ts
|
|
32294
|
-
import { readFileSync as
|
|
32295
|
-
import { join as
|
|
32294
|
+
import { readFileSync as readFileSync8, existsSync as existsSync6 } from "node:fs";
|
|
32295
|
+
import { join as join9 } from "node:path";
|
|
32296
32296
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32297
|
-
|
|
32297
|
+
|
|
32298
|
+
// src/intelligence.ts
|
|
32299
|
+
import { readFileSync as readFileSync7, appendFileSync as appendFileSync3, mkdirSync as mkdirSync4, existsSync as existsSync5 } from "node:fs";
|
|
32300
|
+
import { join as join8 } from "node:path";
|
|
32301
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
32298
32302
|
import { homedir as homedir5 } from "node:os";
|
|
32299
|
-
var
|
|
32300
|
-
var
|
|
32303
|
+
var HOME_DIR3 = process.env.BLITZSTRIKE_HOME ?? join8(homedir5(), ".blitzstrike");
|
|
32304
|
+
var INTEL_PATH = join8(HOME_DIR3, "intelligence.jsonl");
|
|
32305
|
+
var SINK_TO_VECTOR = {
|
|
32306
|
+
sql_execution: "sql_injection",
|
|
32307
|
+
command_execution: "command_injection",
|
|
32308
|
+
html_render: "xss",
|
|
32309
|
+
code_execution: "code_execution",
|
|
32310
|
+
http_request: "ssrf",
|
|
32311
|
+
deserialization: "deserialization",
|
|
32312
|
+
file_operations: "path_traversal",
|
|
32313
|
+
file_inclusion: "path_traversal",
|
|
32314
|
+
template_injection: "ssti",
|
|
32315
|
+
xml_processing: "xxe",
|
|
32316
|
+
path_traversal: "path_traversal",
|
|
32317
|
+
redirect: "open_redirect",
|
|
32318
|
+
auth_bypass: "auth_bypass",
|
|
32319
|
+
cors_misconfiguration: "cors_misconfiguration"
|
|
32320
|
+
};
|
|
32321
|
+
function sinkToVector(sinkType) {
|
|
32322
|
+
return SINK_TO_VECTOR[sinkType.toLowerCase()] ?? sinkType.toLowerCase();
|
|
32323
|
+
}
|
|
32324
|
+
function ensureDir2() {
|
|
32325
|
+
if (!existsSync5(HOME_DIR3))
|
|
32326
|
+
mkdirSync4(HOME_DIR3, { recursive: true });
|
|
32327
|
+
}
|
|
32328
|
+
function dedupHash2(vector, tech, target, outcome) {
|
|
32329
|
+
return createHash4("sha256").update(`${vector}\x00${tech}\x00${target}\x00${outcome}`).digest("hex").slice(0, 16);
|
|
32330
|
+
}
|
|
32331
|
+
function loadIntel() {
|
|
32332
|
+
if (!existsSync5(INTEL_PATH))
|
|
32333
|
+
return [];
|
|
32334
|
+
try {
|
|
32335
|
+
const out = [];
|
|
32336
|
+
for (const line of readFileSync7(INTEL_PATH, "utf8").split(`
|
|
32337
|
+
`)) {
|
|
32338
|
+
const t = line.trim();
|
|
32339
|
+
if (!t)
|
|
32340
|
+
continue;
|
|
32341
|
+
try {
|
|
32342
|
+
out.push(JSON.parse(t));
|
|
32343
|
+
} catch {}
|
|
32344
|
+
}
|
|
32345
|
+
return out;
|
|
32346
|
+
} catch {
|
|
32347
|
+
return [];
|
|
32348
|
+
}
|
|
32349
|
+
}
|
|
32350
|
+
function append2(entry) {
|
|
32351
|
+
ensureDir2();
|
|
32352
|
+
appendFileSync3(INTEL_PATH, JSON.stringify(entry) + `
|
|
32353
|
+
`);
|
|
32354
|
+
}
|
|
32355
|
+
function recordVerdict(input) {
|
|
32356
|
+
const vector = input.vector.trim().toLowerCase();
|
|
32357
|
+
const tech = (input.tech ?? "unknown").trim().toLowerCase();
|
|
32358
|
+
const target = (input.target ?? "").trim();
|
|
32359
|
+
const hash = dedupHash2(vector, tech, target, input.outcome);
|
|
32360
|
+
const existing = loadIntel().find((e) => e.dedup_hash === hash);
|
|
32361
|
+
if (existing) {
|
|
32362
|
+
return { saved: false, duplicate: true, id: existing.id, vector, tech, outcome: input.outcome };
|
|
32363
|
+
}
|
|
32364
|
+
const entry = {
|
|
32365
|
+
id: `int-${hash.slice(0, 12)}`,
|
|
32366
|
+
vector,
|
|
32367
|
+
tech,
|
|
32368
|
+
framework: input.framework,
|
|
32369
|
+
severity: input.severity,
|
|
32370
|
+
outcome: input.outcome,
|
|
32371
|
+
target: target || undefined,
|
|
32372
|
+
cvss: input.cvss,
|
|
32373
|
+
ts: new Date().toISOString(),
|
|
32374
|
+
dedup_hash: hash
|
|
32375
|
+
};
|
|
32376
|
+
append2(entry);
|
|
32377
|
+
return { saved: true, duplicate: false, id: entry.id, vector, tech, outcome: input.outcome };
|
|
32378
|
+
}
|
|
32379
|
+
function hitRates(tech) {
|
|
32380
|
+
const entries = loadIntel();
|
|
32381
|
+
const filtered = tech ? entries.filter((e) => e.tech === tech.toLowerCase()) : entries;
|
|
32382
|
+
const agg = new Map;
|
|
32383
|
+
for (const e of filtered) {
|
|
32384
|
+
const key = `${e.vector}\x00${e.tech}`;
|
|
32385
|
+
const a = agg.get(key) ?? { vector: e.vector, tech: e.tech, tested: 0, confirmed: 0, false_positive: 0, hit_rate: 0 };
|
|
32386
|
+
a.tested += 1;
|
|
32387
|
+
if (e.outcome === "confirmed")
|
|
32388
|
+
a.confirmed += 1;
|
|
32389
|
+
else
|
|
32390
|
+
a.false_positive += 1;
|
|
32391
|
+
agg.set(key, a);
|
|
32392
|
+
}
|
|
32393
|
+
const list = [...agg.values()].map((a) => ({ ...a, hit_rate: Number((a.confirmed / a.tested).toFixed(3)) }));
|
|
32394
|
+
list.sort((x, y) => y.hit_rate - x.hit_rate || y.tested - x.tested);
|
|
32395
|
+
return { tech: tech ?? null, total_verdicts: filtered.length, entries: list };
|
|
32396
|
+
}
|
|
32397
|
+
function empiricalPrior(vector, tech, formulaPrior) {
|
|
32398
|
+
const v = vector.toLowerCase();
|
|
32399
|
+
const t = (tech || "unknown").toLowerCase();
|
|
32400
|
+
const all = loadIntel();
|
|
32401
|
+
const specific = all.filter((e) => e.vector === v && e.tech === t);
|
|
32402
|
+
const pool = specific.length > 0 ? specific : all.filter((e) => e.vector === v);
|
|
32403
|
+
if (pool.length === 0)
|
|
32404
|
+
return formulaPrior;
|
|
32405
|
+
const confirmed = pool.filter((e) => e.outcome === "confirmed").length;
|
|
32406
|
+
const tested = pool.length;
|
|
32407
|
+
const K = 5;
|
|
32408
|
+
const alpha = formulaPrior * K;
|
|
32409
|
+
const beta = (1 - formulaPrior) * K;
|
|
32410
|
+
const posterior = (confirmed + alpha) / (tested + alpha + beta);
|
|
32411
|
+
return Math.round(posterior * 100) / 100;
|
|
32412
|
+
}
|
|
32413
|
+
function topVectors(tech, limit = 10) {
|
|
32414
|
+
const rates = hitRates(tech);
|
|
32415
|
+
const entries = rates.entries.filter((e) => e.hit_rate > 0);
|
|
32416
|
+
return { tech, top: entries.slice(0, limit) };
|
|
32417
|
+
}
|
|
32418
|
+
function queryIntel(filter = {}) {
|
|
32419
|
+
let entries = loadIntel();
|
|
32420
|
+
if (filter.vector)
|
|
32421
|
+
entries = entries.filter((e) => e.vector === filter.vector.toLowerCase());
|
|
32422
|
+
if (filter.tech)
|
|
32423
|
+
entries = entries.filter((e) => e.tech === filter.tech.toLowerCase());
|
|
32424
|
+
if (filter.outcome)
|
|
32425
|
+
entries = entries.filter((e) => e.outcome === filter.outcome);
|
|
32426
|
+
entries.sort((a, b) => a.ts < b.ts ? 1 : -1);
|
|
32427
|
+
return {
|
|
32428
|
+
total: entries.length,
|
|
32429
|
+
entries: entries.slice(0, 50).map((e) => ({
|
|
32430
|
+
id: e.id,
|
|
32431
|
+
vector: e.vector,
|
|
32432
|
+
tech: e.tech,
|
|
32433
|
+
framework: e.framework,
|
|
32434
|
+
severity: e.severity,
|
|
32435
|
+
outcome: e.outcome,
|
|
32436
|
+
target: e.target,
|
|
32437
|
+
cvss: e.cvss,
|
|
32438
|
+
ts: e.ts
|
|
32439
|
+
}))
|
|
32440
|
+
};
|
|
32441
|
+
}
|
|
32442
|
+
|
|
32443
|
+
// src/intel.ts
|
|
32444
|
+
import { readdirSync as readdirSync4 } from "node:fs";
|
|
32445
|
+
import { homedir as homedir6 } from "node:os";
|
|
32446
|
+
var ROOT3 = join9(fileURLToPath4(new URL(".", import.meta.url)), "..");
|
|
32447
|
+
var INTEL = join9(ROOT3, "intelligence");
|
|
32301
32448
|
function loadJson(name) {
|
|
32302
|
-
const p =
|
|
32303
|
-
if (!
|
|
32449
|
+
const p = join9(INTEL, `${name}.json`);
|
|
32450
|
+
if (!existsSync6(p))
|
|
32304
32451
|
return null;
|
|
32305
32452
|
try {
|
|
32306
|
-
return JSON.parse(
|
|
32453
|
+
return JSON.parse(readFileSync8(p, "utf8"));
|
|
32307
32454
|
} catch {
|
|
32308
32455
|
return null;
|
|
32309
32456
|
}
|
|
@@ -32528,8 +32675,9 @@ var VECTOR_TIME = {
|
|
|
32528
32675
|
wp_plugin_audit: 600
|
|
32529
32676
|
};
|
|
32530
32677
|
var DEFAULT_VECTOR_TIME = 180;
|
|
32531
|
-
function successProbability(priority) {
|
|
32532
|
-
|
|
32678
|
+
function successProbability(priority, vector, tech) {
|
|
32679
|
+
const formula = Math.round(Math.min(0.85, Math.max(0.25, 0.85 - 0.15 * (priority - 1))) * 100) / 100;
|
|
32680
|
+
return empiricalPrior(vector, tech, formula);
|
|
32533
32681
|
}
|
|
32534
32682
|
function estimateTime(vector) {
|
|
32535
32683
|
return VECTOR_TIME[vector] ?? DEFAULT_VECTOR_TIME;
|
|
@@ -32564,6 +32712,7 @@ function attackPlan(target, tech = [], params = [], mode = "full") {
|
|
|
32564
32712
|
else if (mode === "stealth")
|
|
32565
32713
|
sorted = sorted.filter((p) => STEALTH_VECTORS.has(p.vector));
|
|
32566
32714
|
const totalTime = sorted.reduce((s, p) => s + estimateTime(p.vector), 0);
|
|
32715
|
+
const techKey = (tech[0] ?? "unknown").toLowerCase();
|
|
32567
32716
|
return {
|
|
32568
32717
|
target,
|
|
32569
32718
|
mode,
|
|
@@ -32572,7 +32721,7 @@ function attackPlan(target, tech = [], params = [], mode = "full") {
|
|
|
32572
32721
|
order: i + 1,
|
|
32573
32722
|
vector: p.vector,
|
|
32574
32723
|
priority: p.priority,
|
|
32575
|
-
success_probability: successProbability(p.priority),
|
|
32724
|
+
success_probability: successProbability(p.priority, p.vector, techKey),
|
|
32576
32725
|
estimated_time_sec: estimateTime(p.vector),
|
|
32577
32726
|
reason: p.reason,
|
|
32578
32727
|
tool: p.tool,
|
|
@@ -32581,18 +32730,18 @@ function attackPlan(target, tech = [], params = [], mode = "full") {
|
|
|
32581
32730
|
total_estimated_time_sec: totalTime
|
|
32582
32731
|
};
|
|
32583
32732
|
}
|
|
32584
|
-
var PACKAGE_PAYLOADS =
|
|
32585
|
-
var PACKAGE_TEMPLATES =
|
|
32586
|
-
var DATA_ROOT = process.env.BLITZSTRIKE_DATA ??
|
|
32733
|
+
var PACKAGE_PAYLOADS = join9(ROOT3, "payloads");
|
|
32734
|
+
var PACKAGE_TEMPLATES = join9(ROOT3, "templates");
|
|
32735
|
+
var DATA_ROOT = process.env.BLITZSTRIKE_DATA ?? join9(homedir6(), ".blitzstrike", "data");
|
|
32587
32736
|
function payloadsDir() {
|
|
32588
|
-
if (
|
|
32737
|
+
if (existsSync6(PACKAGE_PAYLOADS))
|
|
32589
32738
|
return PACKAGE_PAYLOADS;
|
|
32590
|
-
return
|
|
32739
|
+
return join9(DATA_ROOT, "payloads");
|
|
32591
32740
|
}
|
|
32592
32741
|
function templatesDir() {
|
|
32593
|
-
if (
|
|
32742
|
+
if (existsSync6(PACKAGE_TEMPLATES))
|
|
32594
32743
|
return PACKAGE_TEMPLATES;
|
|
32595
|
-
return
|
|
32744
|
+
return join9(DATA_ROOT, "templates");
|
|
32596
32745
|
}
|
|
32597
32746
|
var PAYLOADS = payloadsDir();
|
|
32598
32747
|
var TEMPLATES = templatesDir();
|
|
@@ -32628,7 +32777,7 @@ function payloadLookup(topic) {
|
|
|
32628
32777
|
const normalized = ALIASES[key] ?? key;
|
|
32629
32778
|
const exact = cats.find((c) => c.toLowerCase() === normalized);
|
|
32630
32779
|
if (exact) {
|
|
32631
|
-
return { found: true, category: exact, files: listFiles(
|
|
32780
|
+
return { found: true, category: exact, files: listFiles(join9(PAYLOADS, exact)) };
|
|
32632
32781
|
}
|
|
32633
32782
|
const keyTokens = normalized.split(/[^a-z0-9]+/).filter((t) => t.length >= 3);
|
|
32634
32783
|
const matches = cats.filter((c) => {
|
|
@@ -32638,7 +32787,7 @@ function payloadLookup(topic) {
|
|
|
32638
32787
|
return keyTokens.some((tok) => new RegExp(`(^|[^a-z0-9])${tok}`).test(cl));
|
|
32639
32788
|
});
|
|
32640
32789
|
if (matches.length > 0) {
|
|
32641
|
-
return { found: true, category: matches[0], files: listFiles(
|
|
32790
|
+
return { found: true, category: matches[0], files: listFiles(join9(PAYLOADS, matches[0])), alternatives: matches.slice(0, 10) };
|
|
32642
32791
|
}
|
|
32643
32792
|
return { found: false, topic, suggestions: cats.slice(0, 20) };
|
|
32644
32793
|
}
|
|
@@ -32647,19 +32796,19 @@ function readPayload(category, file) {
|
|
|
32647
32796
|
const exact = cats.find((c) => c.toLowerCase() === category.toLowerCase());
|
|
32648
32797
|
if (!exact)
|
|
32649
32798
|
return { found: false, category, suggestions: cats.slice(0, 20) };
|
|
32650
|
-
const dir =
|
|
32799
|
+
const dir = join9(PAYLOADS, exact);
|
|
32651
32800
|
const files = listFiles(dir);
|
|
32652
32801
|
if (!file) {
|
|
32653
32802
|
const readme = files.find((f) => f.toLowerCase() === "readme.md");
|
|
32654
32803
|
if (readme) {
|
|
32655
|
-
return { found: true, category: exact, file: readme, content:
|
|
32804
|
+
return { found: true, category: exact, file: readme, content: readFileSync8(join9(dir, readme), "utf8").slice(0, 20000) };
|
|
32656
32805
|
}
|
|
32657
32806
|
return { found: true, category: exact, files };
|
|
32658
32807
|
}
|
|
32659
32808
|
const f = files.find((x) => x.toLowerCase() === file.toLowerCase());
|
|
32660
32809
|
if (!f)
|
|
32661
32810
|
return { found: false, category: exact, file, suggestions: files };
|
|
32662
|
-
return { found: true, category: exact, file: f, content:
|
|
32811
|
+
return { found: true, category: exact, file: f, content: readFileSync8(join9(dir, f), "utf8").slice(0, 20000) };
|
|
32663
32812
|
}
|
|
32664
32813
|
function listFiles(dir) {
|
|
32665
32814
|
try {
|
|
@@ -32674,7 +32823,7 @@ function countTemplates() {
|
|
|
32674
32823
|
const walk = (dir) => {
|
|
32675
32824
|
for (const e of readdirSync4(dir, { withFileTypes: true })) {
|
|
32676
32825
|
if (e.isDirectory())
|
|
32677
|
-
walk(
|
|
32826
|
+
walk(join9(dir, e.name));
|
|
32678
32827
|
else if (e.name.endsWith(".yaml"))
|
|
32679
32828
|
n++;
|
|
32680
32829
|
}
|
|
@@ -32699,14 +32848,14 @@ function templateLookup(topic, limit = 10) {
|
|
|
32699
32848
|
}
|
|
32700
32849
|
for (const e of entries) {
|
|
32701
32850
|
if (e.isDirectory())
|
|
32702
|
-
walk(
|
|
32851
|
+
walk(join9(dir, e.name), depth + 1);
|
|
32703
32852
|
else if (e.name.endsWith(".yaml")) {
|
|
32704
32853
|
const name = e.name.toLowerCase();
|
|
32705
32854
|
if (name.includes(key)) {
|
|
32706
|
-
const full =
|
|
32855
|
+
const full = join9(dir, e.name);
|
|
32707
32856
|
let id = "";
|
|
32708
32857
|
try {
|
|
32709
|
-
const content =
|
|
32858
|
+
const content = readFileSync8(full, "utf8");
|
|
32710
32859
|
const m = content.match(/^\s*id:\s*(.+)$/m);
|
|
32711
32860
|
if (m)
|
|
32712
32861
|
id = m[1].trim();
|
|
@@ -33171,10 +33320,83 @@ function cvssAssess(input) {
|
|
|
33171
33320
|
return { score, vector: cvssVector(input), severity: cvssSeverity(score) };
|
|
33172
33321
|
}
|
|
33173
33322
|
|
|
33323
|
+
// src/compliance.ts
|
|
33324
|
+
var CWE_COMPLIANCE = {
|
|
33325
|
+
"79": { name: "Cross-site Scripting (XSS)", owasp_top10: "A03:2021 Injection", asvs: ["V5.3.3"], pci: ["6.5.7"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33326
|
+
"89": { name: "SQL Injection", owasp_top10: "A03:2021 Injection", asvs: ["V5.3.4"], pci: ["6.5.1"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33327
|
+
"78": { name: "OS Command Injection", owasp_top10: "A03:2021 Injection", asvs: ["V5.3.8"], pci: ["6.5.1"], iso: ["A.8.9"], nist: ["SI-10"] },
|
|
33328
|
+
"94": { name: "Code Injection", owasp_top10: "A03:2021 Injection", asvs: ["V5.2.4"], pci: ["6.5.1"], iso: ["A.8.9"], nist: ["SI-10"] },
|
|
33329
|
+
"918": { name: "Server-Side Request Forgery (SSRF)", owasp_top10: "A10:2021 SSRF", asvs: ["V5.2.6"], pci: ["6.5.6"], iso: ["A.8.20"], nist: ["SC-7"] },
|
|
33330
|
+
"611": { name: "XXE", owasp_top10: "A05:2021 Security Misconfiguration", asvs: ["V5.5.2"], pci: ["6.5.3"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33331
|
+
"502": { name: "Insecure Deserialization", owasp_top10: "A08:2021 Software and Data Integrity Failures", asvs: ["V5.5.1"], pci: ["6.5.2"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33332
|
+
"22": { name: "Path Traversal", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V12.3.1"], pci: ["6.5.8"], iso: ["A.8.12"], nist: ["AC-3"] },
|
|
33333
|
+
"601": { name: "Open Redirect", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V5.1.5"], pci: ["6.5.9"], iso: ["A.8.20"], nist: ["AC-3"] },
|
|
33334
|
+
"434": { name: "Unrestricted File Upload", owasp_top10: "A03:2021 Injection", asvs: ["V12.3.2"], pci: ["6.5.5"], iso: ["A.8.12"], nist: ["SI-10"] },
|
|
33335
|
+
"942": { name: "Permissive Cross-Origin Policy (CORS)", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V4.2.2"], pci: ["6.5.9"], iso: ["A.8.20"], nist: ["AC-4"] },
|
|
33336
|
+
"287": { name: "Improper Authentication", owasp_top10: "A07:2021 Identification and Authentication Failures", asvs: ["V2.1.1"], pci: ["7.1.1", "8.1.1"], iso: ["A.8.5"], nist: ["IA-2"] },
|
|
33337
|
+
"1336": { name: "Server-Side Template Injection (SSTI)", owasp_top10: "A03:2021 Injection", asvs: ["V5.3.12"], pci: ["6.5.1"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33338
|
+
"915": { name: "Mass Assignment", owasp_top10: "A04:2021 Insecure Design", asvs: ["V5.1.2"], pci: ["6.5.4"], iso: ["A.8.2"], nist: ["AC-3"] },
|
|
33339
|
+
"1321": { name: "Prototype Pollution", owasp_top10: "A03:2021 Injection", asvs: ["V5.3.12"], pci: ["6.5.2"], iso: ["A.8.26"], nist: ["SI-10"] },
|
|
33340
|
+
"352": { name: "Cross-Site Request Forgery (CSRF)", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V4.2.2"], pci: ["6.5.9"], iso: ["A.8.5"], nist: ["AC-3"] },
|
|
33341
|
+
"319": { name: "Cleartext Transmission of Sensitive Information", owasp_top10: "A02:2021 Cryptographic Failures", asvs: ["V9.1.1"], pci: ["4.1.1"], iso: ["A.8.24"], nist: ["SC-8"] },
|
|
33342
|
+
"693": { name: "Protection Mechanism Failure", owasp_top10: "A05:2021 Security Misconfiguration", asvs: ["V14.2.1"], pci: ["6.5.x"], iso: ["A.8.8"], nist: ["SI-2"] },
|
|
33343
|
+
"200": { name: "Exposure of Sensitive Information", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V7.4.1"], pci: ["6.5.x"], iso: ["A.8.11"], nist: ["AC-4"] },
|
|
33344
|
+
"862": { name: "Missing Authorization", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V4.1.1"], pci: ["7.1.1"], iso: ["A.8.2"], nist: ["AC-3"] },
|
|
33345
|
+
"639": { name: "Insecure Direct Object Reference (IDOR)", owasp_top10: "A01:2021 Broken Access Control", asvs: ["V4.1.2"], pci: ["7.1.1"], iso: ["A.8.2"], nist: ["AC-3"] },
|
|
33346
|
+
"640": { name: "Weak Password Recovery", owasp_top10: "A07:2021 Identification and Authentication Failures", asvs: ["V2.5.2"], pci: ["8.3.6"], iso: ["A.8.5"], nist: ["IA-5"] },
|
|
33347
|
+
"798": { name: "Hard-coded Credentials", owasp_top10: "A07:2021 Identification and Authentication Failures", asvs: ["V2.10.4"], pci: ["8.3.8"], iso: ["A.8.5"], nist: ["IA-5"] },
|
|
33348
|
+
"327": { name: "Weak Cryptography", owasp_top10: "A02:2021 Cryptographic Failures", asvs: ["V6.2.1"], pci: ["3.5.1"], iso: ["A.8.24"], nist: ["SC-13"] },
|
|
33349
|
+
"306": { name: "Missing Authentication for Critical Function", owasp_top10: "A07:2021 Identification and Authentication Failures", asvs: ["V1.2.1"], pci: ["8.1.1"], iso: ["A.8.5"], nist: ["IA-2"] }
|
|
33350
|
+
};
|
|
33351
|
+
function complianceMap(cwe) {
|
|
33352
|
+
const id = (cwe ?? "").toUpperCase().replace(/^CWE-?/, "");
|
|
33353
|
+
const m = CWE_COMPLIANCE[id];
|
|
33354
|
+
if (!m)
|
|
33355
|
+
return null;
|
|
33356
|
+
return { cwe: `CWE-${id}`, ...m };
|
|
33357
|
+
}
|
|
33358
|
+
function complianceSummary(cwes) {
|
|
33359
|
+
const by_owasp = {};
|
|
33360
|
+
const by_asvs = {};
|
|
33361
|
+
const by_pci = {};
|
|
33362
|
+
const by_iso = {};
|
|
33363
|
+
const by_nist = {};
|
|
33364
|
+
const mappings = [];
|
|
33365
|
+
let mapped = 0;
|
|
33366
|
+
let unmapped = 0;
|
|
33367
|
+
for (const cwe of cwes) {
|
|
33368
|
+
if (!cwe) {
|
|
33369
|
+
unmapped += 1;
|
|
33370
|
+
continue;
|
|
33371
|
+
}
|
|
33372
|
+
const m = complianceMap(cwe);
|
|
33373
|
+
if (!m) {
|
|
33374
|
+
unmapped += 1;
|
|
33375
|
+
continue;
|
|
33376
|
+
}
|
|
33377
|
+
mapped += 1;
|
|
33378
|
+
if (m.owasp_top10)
|
|
33379
|
+
by_owasp[m.owasp_top10] = (by_owasp[m.owasp_top10] ?? 0) + 1;
|
|
33380
|
+
for (const a of m.asvs ?? [])
|
|
33381
|
+
by_asvs[a] = (by_asvs[a] ?? 0) + 1;
|
|
33382
|
+
for (const p of m.pci ?? [])
|
|
33383
|
+
by_pci[p] = (by_pci[p] ?? 0) + 1;
|
|
33384
|
+
for (const i of m.iso ?? [])
|
|
33385
|
+
by_iso[i] = (by_iso[i] ?? 0) + 1;
|
|
33386
|
+
for (const n of m.nist ?? [])
|
|
33387
|
+
by_nist[n] = (by_nist[n] ?? 0) + 1;
|
|
33388
|
+
if (!mappings.some((x) => x.cwe === m.cwe)) {
|
|
33389
|
+
mappings.push({ cwe: m.cwe, name: m.name, owasp_top10: m.owasp_top10 ?? null, asvs: m.asvs ?? [], pci: m.pci ?? [], iso: m.iso ?? [], nist: m.nist ?? [] });
|
|
33390
|
+
}
|
|
33391
|
+
}
|
|
33392
|
+
mappings.sort((a, b) => a.cwe.localeCompare(b.cwe));
|
|
33393
|
+
return { total_mapped: mapped, total_unmapped: unmapped, by_owasp, by_asvs, by_pci, by_iso, by_nist, mappings };
|
|
33394
|
+
}
|
|
33395
|
+
|
|
33174
33396
|
// src/report.ts
|
|
33175
|
-
import { writeFileSync as writeFileSync2, mkdirSync as
|
|
33176
|
-
import { join as
|
|
33177
|
-
import { homedir as
|
|
33397
|
+
import { writeFileSync as writeFileSync2, mkdirSync as mkdirSync5 } from "node:fs";
|
|
33398
|
+
import { join as join10 } from "node:path";
|
|
33399
|
+
import { homedir as homedir7 } from "node:os";
|
|
33178
33400
|
var SEVERITY_METRICS = {
|
|
33179
33401
|
critical: { AV: "N", AC: "L", PR: "N", UI: "N", S: "U", C: "H", I: "H", A: "H" },
|
|
33180
33402
|
high: { AV: "N", AC: "L", PR: "L", UI: "N", S: "U", C: "H", I: "H", A: "N" },
|
|
@@ -33333,7 +33555,34 @@ function reportMarkdown(findings, opts = {}) {
|
|
|
33333
33555
|
lines.push("");
|
|
33334
33556
|
});
|
|
33335
33557
|
}
|
|
33336
|
-
lines.push("## 6.
|
|
33558
|
+
lines.push("## 6. Compliance Mapping");
|
|
33559
|
+
lines.push("");
|
|
33560
|
+
const comp = complianceSummary(findings.map((f) => f.classification?.cwe ?? null));
|
|
33561
|
+
if (comp.total_mapped === 0) {
|
|
33562
|
+
lines.push("No CWE-tagged findings to map.");
|
|
33563
|
+
} else {
|
|
33564
|
+
lines.push("Maps each finding's CWE to OWASP Top 10 (2021), OWASP ASVS v4.0, PCI DSS v4.0, ISO 27001:2022 (Annex A), and NIST SP 800-53.");
|
|
33565
|
+
lines.push("");
|
|
33566
|
+
for (const m of comp.mappings) {
|
|
33567
|
+
lines.push(`- **${m.cwe}** ${m.name}`);
|
|
33568
|
+
if (m.owasp_top10)
|
|
33569
|
+
lines.push(` - OWASP Top 10: \`${m.owasp_top10}\``);
|
|
33570
|
+
if (m.asvs.length)
|
|
33571
|
+
lines.push(` - ASVS v4.0: \`${m.asvs.join(", ")}\``);
|
|
33572
|
+
if (m.pci.length)
|
|
33573
|
+
lines.push(` - PCI DSS v4.0: \`${m.pci.join(", ")}\``);
|
|
33574
|
+
if (m.iso.length)
|
|
33575
|
+
lines.push(` - ISO 27001:2022: \`${m.iso.join(", ")}\``);
|
|
33576
|
+
if (m.nist.length)
|
|
33577
|
+
lines.push(` - NIST 800-53: \`${m.nist.join(", ")}\``);
|
|
33578
|
+
}
|
|
33579
|
+
if (comp.total_unmapped > 0) {
|
|
33580
|
+
lines.push("");
|
|
33581
|
+
lines.push(`_${comp.total_unmapped} finding(s) had no CWE and were not mapped._`);
|
|
33582
|
+
}
|
|
33583
|
+
}
|
|
33584
|
+
lines.push("");
|
|
33585
|
+
lines.push("## 7. Recommendations");
|
|
33337
33586
|
lines.push("");
|
|
33338
33587
|
if (findings.length === 0) {
|
|
33339
33588
|
lines.push("No findings — no remediation required.");
|
|
@@ -33344,7 +33593,7 @@ function reportMarkdown(findings, opts = {}) {
|
|
|
33344
33593
|
});
|
|
33345
33594
|
}
|
|
33346
33595
|
lines.push("");
|
|
33347
|
-
lines.push("##
|
|
33596
|
+
lines.push("## 8. Appendix");
|
|
33348
33597
|
lines.push("");
|
|
33349
33598
|
if (hypotheses.length) {
|
|
33350
33599
|
lines.push("### Unverified hypotheses (kept for follow-up)");
|
|
@@ -33377,18 +33626,18 @@ function reportJson(findings, opts = {}) {
|
|
|
33377
33626
|
};
|
|
33378
33627
|
return JSON.stringify(payload, null, 2);
|
|
33379
33628
|
}
|
|
33380
|
-
var REPORT_DIR = process.env.BLITZSTRIKE_REPORT_DIR ??
|
|
33629
|
+
var REPORT_DIR = process.env.BLITZSTRIKE_REPORT_DIR ?? join10(homedir7(), ".blitzstrike", "reports");
|
|
33381
33630
|
function slugify2(s) {
|
|
33382
33631
|
const slug = s.toLowerCase().replace(/^https?:\/\//, "").replace(/[^a-z0-9.-]+/g, "-").replace(/^-+|-+$/g, "").replace(/\./g, "_").slice(0, 60);
|
|
33383
33632
|
return slug || "engagement";
|
|
33384
33633
|
}
|
|
33385
33634
|
function saveReport(content, opts = {}) {
|
|
33386
|
-
|
|
33635
|
+
mkdirSync5(REPORT_DIR, { recursive: true });
|
|
33387
33636
|
const slug = slugify2(opts.scope ?? opts.title ?? "engagement");
|
|
33388
33637
|
const ts = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19);
|
|
33389
33638
|
const ext = opts.format === "json" ? "json" : "md";
|
|
33390
33639
|
const filename = `${slug}-${ts}.${ext}`;
|
|
33391
|
-
const path =
|
|
33640
|
+
const path = join10(REPORT_DIR, filename);
|
|
33392
33641
|
writeFileSync2(path, content, "utf8");
|
|
33393
33642
|
return { path, dir: REPORT_DIR, filename };
|
|
33394
33643
|
}
|
|
@@ -33969,7 +34218,7 @@ function classifyTarget(target) {
|
|
|
33969
34218
|
if (/^https?:\/\//i.test(target))
|
|
33970
34219
|
return { kind: "live", target };
|
|
33971
34220
|
try {
|
|
33972
|
-
if (
|
|
34221
|
+
if (existsSync7(target) && (statSync2(target).isDirectory() || statSync2(target).isFile())) {
|
|
33973
34222
|
return { kind: "source", target };
|
|
33974
34223
|
}
|
|
33975
34224
|
} catch {}
|
|
@@ -33985,9 +34234,9 @@ function loadChains() {
|
|
|
33985
34234
|
if (_chainsCache)
|
|
33986
34235
|
return _chainsCache;
|
|
33987
34236
|
try {
|
|
33988
|
-
const dir =
|
|
33989
|
-
const path =
|
|
33990
|
-
const raw = JSON.parse(
|
|
34237
|
+
const dir = join11(fileURLToPath5(new URL(".", import.meta.url)), "..");
|
|
34238
|
+
const path = join11(dir, "chains.json");
|
|
34239
|
+
const raw = JSON.parse(readFileSync9(path, "utf8"));
|
|
33991
34240
|
_chainsCache = raw.chains ?? [];
|
|
33992
34241
|
return _chainsCache;
|
|
33993
34242
|
} catch {
|
|
@@ -34110,7 +34359,7 @@ function runEngagement(target, scope = "", mode = "bug-bounty", maxFiles = 2000,
|
|
|
34110
34359
|
};
|
|
34111
34360
|
const isPath = (() => {
|
|
34112
34361
|
try {
|
|
34113
|
-
return
|
|
34362
|
+
return existsSync7(target) && (statSync2(target).isDirectory() || statSync2(target).isFile());
|
|
34114
34363
|
} catch {
|
|
34115
34364
|
return false;
|
|
34116
34365
|
}
|
|
@@ -34765,8 +35014,8 @@ var CHAIN_ID_TO_ESCALATION = {
|
|
|
34765
35014
|
};
|
|
34766
35015
|
function loadChainLinks() {
|
|
34767
35016
|
try {
|
|
34768
|
-
const dir =
|
|
34769
|
-
const data = JSON.parse(
|
|
35017
|
+
const dir = join11(fileURLToPath5(new URL(".", import.meta.url)), "..");
|
|
35018
|
+
const data = JSON.parse(readFileSync9(join11(dir, "intelligence", "chain_links.json"), "utf8"));
|
|
34770
35019
|
return data.links ?? [];
|
|
34771
35020
|
} catch {
|
|
34772
35021
|
return [];
|
|
@@ -34922,24 +35171,24 @@ function compactState(phase, findings) {
|
|
|
34922
35171
|
}
|
|
34923
35172
|
|
|
34924
35173
|
// src/tasks.ts
|
|
34925
|
-
import { mkdirSync as
|
|
34926
|
-
import { join as
|
|
35174
|
+
import { mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "node:fs";
|
|
35175
|
+
import { join as join12 } from "node:path";
|
|
34927
35176
|
import { fileURLToPath as fileURLToPath6 } from "node:url";
|
|
34928
35177
|
function tasksDir() {
|
|
34929
|
-
return
|
|
35178
|
+
return join12(fileURLToPath6(new URL(".", import.meta.url)), "..", ".blitzstrike", "tasks");
|
|
34930
35179
|
}
|
|
34931
35180
|
function taskPath(id) {
|
|
34932
|
-
return
|
|
35181
|
+
return join12(tasksDir(), `${id}.json`);
|
|
34933
35182
|
}
|
|
34934
35183
|
function load(id) {
|
|
34935
35184
|
try {
|
|
34936
|
-
return JSON.parse(
|
|
35185
|
+
return JSON.parse(readFileSync10(taskPath(id), "utf8"));
|
|
34937
35186
|
} catch {
|
|
34938
35187
|
return null;
|
|
34939
35188
|
}
|
|
34940
35189
|
}
|
|
34941
35190
|
function save(t) {
|
|
34942
|
-
|
|
35191
|
+
mkdirSync6(tasksDir(), { recursive: true });
|
|
34943
35192
|
writeFileSync3(taskPath(t.task_id), JSON.stringify(t, null, 2));
|
|
34944
35193
|
}
|
|
34945
35194
|
function taskStart(id, objective, plan) {
|
|
@@ -35238,16 +35487,16 @@ function engagementStatus() {
|
|
|
35238
35487
|
// src/incremental.ts
|
|
35239
35488
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
35240
35489
|
import { writeFileSync as writeFileSync4, mkdtempSync, rmSync } from "node:fs";
|
|
35241
|
-
import { join as
|
|
35490
|
+
import { join as join13 } from "node:path";
|
|
35242
35491
|
import { tmpdir } from "node:os";
|
|
35243
35492
|
|
|
35244
35493
|
// src/eagle2.ts
|
|
35245
35494
|
var import_php_parser2 = __toESM(require_src(), 1);
|
|
35246
|
-
import { readFileSync as
|
|
35495
|
+
import { readFileSync as readFileSync13 } from "node:fs";
|
|
35247
35496
|
|
|
35248
35497
|
// src/dataflow.ts
|
|
35249
35498
|
init_scanner();
|
|
35250
|
-
import { readFileSync as
|
|
35499
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
35251
35500
|
var SOURCES = {
|
|
35252
35501
|
$_GET: { id: "http_get", label: "HTTP GET parameter", attacker_controlled: true },
|
|
35253
35502
|
$_POST: { id: "http_post", label: "HTTP POST body", attacker_controlled: true },
|
|
@@ -35332,7 +35581,7 @@ function traceDataFlow(path) {
|
|
|
35332
35581
|
return result;
|
|
35333
35582
|
let text;
|
|
35334
35583
|
try {
|
|
35335
|
-
text =
|
|
35584
|
+
text = readFileSync11(path, "utf8");
|
|
35336
35585
|
} catch {
|
|
35337
35586
|
return result;
|
|
35338
35587
|
}
|
|
@@ -35413,7 +35662,7 @@ init_scanner();
|
|
|
35413
35662
|
|
|
35414
35663
|
// src/callgraph.ts
|
|
35415
35664
|
var import_php_parser = __toESM(require_src(), 1);
|
|
35416
|
-
import { readFileSync as
|
|
35665
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
35417
35666
|
var parser = new import_php_parser.Engine({
|
|
35418
35667
|
parser: { extractDoc: false, php7: true },
|
|
35419
35668
|
ast: { withPositions: true, withSource: false }
|
|
@@ -35474,7 +35723,7 @@ function buildCallGraph(path) {
|
|
|
35474
35723
|
const g = { nodes: new Map, edges: [] };
|
|
35475
35724
|
let code;
|
|
35476
35725
|
try {
|
|
35477
|
-
code =
|
|
35726
|
+
code = readFileSync12(path, "utf8");
|
|
35478
35727
|
} catch {
|
|
35479
35728
|
return g;
|
|
35480
35729
|
}
|
|
@@ -35617,12 +35866,12 @@ function entryPoints(g) {
|
|
|
35617
35866
|
|
|
35618
35867
|
// src/cache.ts
|
|
35619
35868
|
init_version();
|
|
35620
|
-
import { createHash as
|
|
35869
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
35621
35870
|
var mem = new Map;
|
|
35622
35871
|
var hits = 0;
|
|
35623
35872
|
var misses = 0;
|
|
35624
35873
|
function cacheKey(kind, source) {
|
|
35625
|
-
const h =
|
|
35874
|
+
const h = createHash5("sha256").update(source).digest("hex").slice(0, 20);
|
|
35626
35875
|
return `${kind}:${VERSION}:${h}`;
|
|
35627
35876
|
}
|
|
35628
35877
|
function getCache(kind, source) {
|
|
@@ -36136,7 +36385,7 @@ function resolveFuncId(name, summaries) {
|
|
|
36136
36385
|
function analyzeDataFlow2(path) {
|
|
36137
36386
|
let cacheCode = "";
|
|
36138
36387
|
try {
|
|
36139
|
-
cacheCode =
|
|
36388
|
+
cacheCode = readFileSync13(path, "utf8");
|
|
36140
36389
|
} catch {}
|
|
36141
36390
|
if (cacheCode) {
|
|
36142
36391
|
const cached = getCache("eagle2", cacheCode);
|
|
@@ -36158,7 +36407,7 @@ function analyzeDataFlow2(path) {
|
|
|
36158
36407
|
};
|
|
36159
36408
|
let code;
|
|
36160
36409
|
try {
|
|
36161
|
-
code = cacheCode ||
|
|
36410
|
+
code = cacheCode || readFileSync13(path, "utf8");
|
|
36162
36411
|
} catch {
|
|
36163
36412
|
return result;
|
|
36164
36413
|
}
|
|
@@ -54753,8 +55002,8 @@ function analyzeChangedFiles(repo, base = "HEAD~1", head = "HEAD") {
|
|
|
54753
55002
|
continue;
|
|
54754
55003
|
const lang = detectLanguage(file)?.language;
|
|
54755
55004
|
if (lang === "php") {
|
|
54756
|
-
const dir = mkdtempSync(
|
|
54757
|
-
const tmp =
|
|
55005
|
+
const dir = mkdtempSync(join13(tmpdir(), "blitz-incr-"));
|
|
55006
|
+
const tmp = join13(dir, "changed.php");
|
|
54758
55007
|
writeFileSync4(tmp, code);
|
|
54759
55008
|
try {
|
|
54760
55009
|
const r = analyzeDataFlow2(tmp);
|
|
@@ -54775,7 +55024,7 @@ function analyzeChangedFiles(repo, base = "HEAD~1", head = "HEAD") {
|
|
|
54775
55024
|
// src/taint.ts
|
|
54776
55025
|
init_scanner();
|
|
54777
55026
|
var import_php_parser4 = __toESM(require_src(), 1);
|
|
54778
|
-
import { readFileSync as
|
|
55027
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
54779
55028
|
var parser4 = new import_php_parser4.Engine({
|
|
54780
55029
|
parser: { extractDoc: false, php7: true },
|
|
54781
55030
|
ast: { withPositions: true, withSource: false }
|
|
@@ -55073,7 +55322,7 @@ function analyzeTaint(path) {
|
|
|
55073
55322
|
const result = { file: path, findings: [], suppressed: 0 };
|
|
55074
55323
|
let code;
|
|
55075
55324
|
try {
|
|
55076
|
-
code =
|
|
55325
|
+
code = readFileSync14(path, "utf8");
|
|
55077
55326
|
} catch {
|
|
55078
55327
|
return result;
|
|
55079
55328
|
}
|
|
@@ -55167,15 +55416,15 @@ function taintTree(root, maxFiles = 2000) {
|
|
|
55167
55416
|
}
|
|
55168
55417
|
|
|
55169
55418
|
// src/differential.ts
|
|
55170
|
-
import { writeFileSync as writeFileSync5, rmSync as rmSync2, mkdtempSync as mkdtempSync2, readFileSync as
|
|
55171
|
-
import { join as
|
|
55419
|
+
import { writeFileSync as writeFileSync5, rmSync as rmSync2, mkdtempSync as mkdtempSync2, readFileSync as readFileSync15 } from "node:fs";
|
|
55420
|
+
import { join as join14 } from "node:path";
|
|
55172
55421
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
55173
55422
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
55174
55423
|
init_scanner();
|
|
55175
55424
|
function runEngine(code, language, file) {
|
|
55176
55425
|
if (language === "php") {
|
|
55177
|
-
const dir = mkdtempSync2(
|
|
55178
|
-
const tmp =
|
|
55426
|
+
const dir = mkdtempSync2(join14(tmpdir2(), "blitz-diff-"));
|
|
55427
|
+
const tmp = join14(dir, "old.php");
|
|
55179
55428
|
writeFileSync5(tmp, code);
|
|
55180
55429
|
try {
|
|
55181
55430
|
const r = analyzeDataFlow2(tmp);
|
|
@@ -55329,8 +55578,8 @@ function languageOf(file) {
|
|
|
55329
55578
|
return adapter?.language ?? "php";
|
|
55330
55579
|
}
|
|
55331
55580
|
function analyzeDifferentialFiles(oldPath, newPath, language) {
|
|
55332
|
-
const oldCode =
|
|
55333
|
-
const newCode =
|
|
55581
|
+
const oldCode = readFileSync15(oldPath, "utf8");
|
|
55582
|
+
const newCode = readFileSync15(newPath, "utf8");
|
|
55334
55583
|
const lang = language ?? languageOf(newPath);
|
|
55335
55584
|
return analyzeDifferential(oldCode, newCode, lang, newPath);
|
|
55336
55585
|
}
|
|
@@ -55360,20 +55609,20 @@ function analyzeGitDiff(repo, base = "HEAD~1", head = "HEAD") {
|
|
|
55360
55609
|
}
|
|
55361
55610
|
|
|
55362
55611
|
// src/frameworks.ts
|
|
55363
|
-
import { readFileSync as
|
|
55364
|
-
import { join as
|
|
55612
|
+
import { readFileSync as readFileSync16, existsSync as existsSync8 } from "node:fs";
|
|
55613
|
+
import { join as join15 } from "node:path";
|
|
55365
55614
|
import { fileURLToPath as fileURLToPath7 } from "node:url";
|
|
55366
|
-
var ROOT4 =
|
|
55367
|
-
var INTEL2 =
|
|
55615
|
+
var ROOT4 = join15(fileURLToPath7(new URL(".", import.meta.url)), "..");
|
|
55616
|
+
var INTEL2 = join15(ROOT4, "intelligence");
|
|
55368
55617
|
var cache = null;
|
|
55369
55618
|
function load2() {
|
|
55370
55619
|
if (cache)
|
|
55371
55620
|
return cache;
|
|
55372
|
-
const p =
|
|
55373
|
-
if (!
|
|
55621
|
+
const p = join15(INTEL2, "frameworks.json");
|
|
55622
|
+
if (!existsSync8(p))
|
|
55374
55623
|
return null;
|
|
55375
55624
|
try {
|
|
55376
|
-
cache = JSON.parse(
|
|
55625
|
+
cache = JSON.parse(readFileSync16(p, "utf8"));
|
|
55377
55626
|
return cache;
|
|
55378
55627
|
} catch {
|
|
55379
55628
|
return null;
|
|
@@ -56150,17 +56399,17 @@ function nextSteps(ctx) {
|
|
|
56150
56399
|
}
|
|
56151
56400
|
|
|
56152
56401
|
// src/benchmark.ts
|
|
56153
|
-
import { readFileSync as
|
|
56154
|
-
import { join as
|
|
56402
|
+
import { readFileSync as readFileSync17, readdirSync as readdirSync5, writeFileSync as writeFileSync6, rmSync as rmSync3, mkdirSync as mkdirSync7 } from "node:fs";
|
|
56403
|
+
import { join as join16 } from "node:path";
|
|
56155
56404
|
import { fileURLToPath as fileURLToPath8 } from "node:url";
|
|
56156
|
-
import { tmpdir as tmpdir3, homedir as
|
|
56157
|
-
var ROOT5 =
|
|
56158
|
-
var CORPUS =
|
|
56159
|
-
var CAPTURED_CORPUS_DIR = process.env.BLITZSTRIKE_CORPUS_DIR ??
|
|
56405
|
+
import { tmpdir as tmpdir3, homedir as homedir8 } from "node:os";
|
|
56406
|
+
var ROOT5 = join16(fileURLToPath8(new URL(".", import.meta.url)), "..");
|
|
56407
|
+
var CORPUS = join16(ROOT5, "bench", "corpus");
|
|
56408
|
+
var CAPTURED_CORPUS_DIR = process.env.BLITZSTRIKE_CORPUS_DIR ?? join16(homedir8(), ".blitzstrike", "corpus");
|
|
56160
56409
|
function parseCorpusFile(path) {
|
|
56161
56410
|
let text;
|
|
56162
56411
|
try {
|
|
56163
|
-
text =
|
|
56412
|
+
text = readFileSync17(path, "utf8");
|
|
56164
56413
|
} catch {
|
|
56165
56414
|
return null;
|
|
56166
56415
|
}
|
|
@@ -56216,7 +56465,7 @@ function loadDir(dir) {
|
|
|
56216
56465
|
for (const f of readdirSync5(dir)) {
|
|
56217
56466
|
if (!f.endsWith(".md"))
|
|
56218
56467
|
continue;
|
|
56219
|
-
const e = parseCorpusFile(
|
|
56468
|
+
const e = parseCorpusFile(join16(dir, f));
|
|
56220
56469
|
if (e)
|
|
56221
56470
|
entries.push(e);
|
|
56222
56471
|
}
|
|
@@ -56227,7 +56476,7 @@ function loadCorpus() {
|
|
|
56227
56476
|
return [...loadDir(CORPUS), ...loadDir(CAPTURED_CORPUS_DIR)];
|
|
56228
56477
|
}
|
|
56229
56478
|
function captureFalsePositive(input) {
|
|
56230
|
-
|
|
56479
|
+
mkdirSync7(CAPTURED_CORPUS_DIR, { recursive: true });
|
|
56231
56480
|
const slug = (input.note ?? "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "captured";
|
|
56232
56481
|
const id = `fp-${slug}-${Date.now().toString(36)}`;
|
|
56233
56482
|
const ext = { php: "php", javascript: "js", typescript: "ts", python: "py", java: "java", js: "js" }[input.language.toLowerCase()] ?? input.language;
|
|
@@ -56243,7 +56492,7 @@ function captureFalsePositive(input) {
|
|
|
56243
56492
|
input.code,
|
|
56244
56493
|
"```"
|
|
56245
56494
|
].filter((l) => l !== null);
|
|
56246
|
-
const path =
|
|
56495
|
+
const path = join16(CAPTURED_CORPUS_DIR, `${id}.md`);
|
|
56247
56496
|
writeFileSync6(path, lines.join(`
|
|
56248
56497
|
`) + `
|
|
56249
56498
|
`, "utf8");
|
|
@@ -56265,7 +56514,7 @@ function detect(entry) {
|
|
|
56265
56514
|
}
|
|
56266
56515
|
const lang = entry.language;
|
|
56267
56516
|
if (lang === "php") {
|
|
56268
|
-
const tmp =
|
|
56517
|
+
const tmp = join16(tmpdir3(), `blitzstrike-bench-${entry.id}-${process.pid}.php`);
|
|
56269
56518
|
writeFileSync6(tmp, entry.code);
|
|
56270
56519
|
const r = analyzeDataFlow2(tmp);
|
|
56271
56520
|
rmSync3(tmp, { force: true });
|
|
@@ -56330,16 +56579,16 @@ function runBenchmark() {
|
|
|
56330
56579
|
}
|
|
56331
56580
|
|
|
56332
56581
|
// src/enterprise-benchmark.ts
|
|
56333
|
-
import { existsSync as
|
|
56334
|
-
import { join as
|
|
56582
|
+
import { existsSync as existsSync10, readFileSync as readFileSync18, readdirSync as readdirSync6, statSync as statSync3 } from "node:fs";
|
|
56583
|
+
import { join as join17, resolve } from "node:path";
|
|
56335
56584
|
var ROOT6 = resolve(process.cwd(), "bench", "enterprise");
|
|
56336
56585
|
var ENTERPRISE_FIXTURES = [
|
|
56337
|
-
{ id: "php-laravel", dir:
|
|
56338
|
-
{ id: "js-express", dir:
|
|
56339
|
-
{ id: "py-django", dir:
|
|
56340
|
-
{ id: "java-spring", dir:
|
|
56341
|
-
{ id: "wp-batch-route", dir:
|
|
56342
|
-
{ id: "php-complex", dir:
|
|
56586
|
+
{ id: "php-laravel", dir: join17(ROOT6, "php-laravel"), expected_vulns: 4 },
|
|
56587
|
+
{ id: "js-express", dir: join17(ROOT6, "js-express"), expected_vulns: 2 },
|
|
56588
|
+
{ id: "py-django", dir: join17(ROOT6, "py-django"), expected_vulns: 2 },
|
|
56589
|
+
{ id: "java-spring", dir: join17(ROOT6, "java-spring"), expected_vulns: 2 },
|
|
56590
|
+
{ id: "wp-batch-route", dir: join17(ROOT6, "wp-batch-route"), expected_vulns: 1 },
|
|
56591
|
+
{ id: "php-complex", dir: join17(ROOT6, "php-complex"), expected_vulns: 4 }
|
|
56343
56592
|
];
|
|
56344
56593
|
function sourceFiles(root) {
|
|
56345
56594
|
const out = [];
|
|
@@ -56351,7 +56600,7 @@ function sourceFiles(root) {
|
|
|
56351
56600
|
return;
|
|
56352
56601
|
}
|
|
56353
56602
|
for (const e of entries) {
|
|
56354
|
-
const p =
|
|
56603
|
+
const p = join17(dir, e);
|
|
56355
56604
|
let st;
|
|
56356
56605
|
try {
|
|
56357
56606
|
st = statSync3(p);
|
|
@@ -56372,7 +56621,7 @@ function detectFixture(dir) {
|
|
|
56372
56621
|
for (const f of sourceFiles(dir)) {
|
|
56373
56622
|
let code;
|
|
56374
56623
|
try {
|
|
56375
|
-
code =
|
|
56624
|
+
code = readFileSync18(f, "utf8");
|
|
56376
56625
|
} catch {
|
|
56377
56626
|
continue;
|
|
56378
56627
|
}
|
|
@@ -56390,7 +56639,7 @@ function detectFixture(dir) {
|
|
|
56390
56639
|
function runEnterpriseBenchmark() {
|
|
56391
56640
|
const fixtures = [];
|
|
56392
56641
|
for (const fx of ENTERPRISE_FIXTURES) {
|
|
56393
|
-
if (!
|
|
56642
|
+
if (!existsSync10(fx.dir)) {
|
|
56394
56643
|
fixtures.push({ id: fx.id, available: false, detected: 0, expected: fx.expected_vulns, recall: 0 });
|
|
56395
56644
|
continue;
|
|
56396
56645
|
}
|
|
@@ -56568,7 +56817,7 @@ function createServer() {
|
|
|
56568
56817
|
` + `- Keep trying every lead AND every chain step until each is verified/executed or blocked, THEN generate_report. Never deliver a bare surface map, and never stop at 'found X' when X enables more.
|
|
56569
56818
|
|
|
56570
56819
|
` + "TWO PATHS:\\n" + "- Source path on disk -> blitz_scan / taint_file / eagle_eye2 (static).\\n" + "- Live URL -> live_recon / active_scan / strike_verify (web-hunting).\\n\\n" + `DEEPEN A FINDING: attack_plan(target, tech, params) to get the prioritized vector plan (decide what to test next with data); list_chains (escalation), chain_links (compose), technique_lookup(cls), payload_lookup, bypass_lookup (blocked). Phase doctrine: read_skill(bs-orchestrate-engagement | bs-web-hunting | bs-source-audit | bs-verify-finding). Campaign plan: read_playbook(target-type). On any failure call retry_guidance(signal) / model_fallback(signal) before giving up.
|
|
56571
|
-
` + `KNOWLEDGE BASE (discover, don't guess): skillLookup(topic) / listSkills for the 40 attack-path + hunting skills (ap-*, hp-*, bs-*); list_attack_vectors / attack_vectors(cat) for the 34-category vector taxonomy; taxonomy(kind) for OWASP/CWE/ASVS/API-top-10; read_playbook(type) for the 17 campaign playbooks; list_manuals / read_tool_manual for 317 tool references; list_tools / run_catalog_tool for the 141-tool catalog. Every tool, skill, and data layer is reachable from these.
|
|
56820
|
+
` + `KNOWLEDGE BASE (discover, don't guess): skillLookup(topic) / listSkills for the 40 attack-path + hunting skills (ap-*, hp-*, bs-*); list_attack_vectors / attack_vectors(cat) for the 34-category vector taxonomy; taxonomy(kind) for OWASP/CWE/ASVS/API-top-10; read_playbook(type) for the 17 campaign playbooks; list_manuals / read_tool_manual for 317 tool references; list_tools / run_catalog_tool for the 141-tool catalog. Every tool, skill, and data layer is reachable from these. CROSS-TARGET INTELLIGENCE: strike_resolve auto-records confirmed/false_positive verdicts into the empirical ledger; query it with intelligence(action=hit_rates/top_vectors) so a new target on a known tech inherits historical hit-rates (attack_plan already blends them into success_probability).
|
|
56572
56821
|
` + `PRECISION ANALYSIS — chrome-devtools MCP is MANDATORY, not optional:
|
|
56573
56822
|
` + `- When a lead needs DOM/JS precision — DOM-XSS sink execution, AJAX endpoint + payload interception, JS runtime errors, redirect chains, SSO/token flow, or anything a static HTML glance cannot prove — call drive_devtools(target). It spawns chrome-devtools-mcp and drives a REAL headless browser (navigate -> list_network_requests -> list_console_messages -> evaluate_script), giving reproducible evidence instead of a guess.
|
|
56574
56823
|
` + `- Before calling it, check_mcp() to confirm the browser MCP is available; if not, blitzstrike install-tools or npm i -g chrome-devtools-mcp. Never substitute eyeballing minified JS or a static sink guess when a live browser can PROVE it. This is the precision + consistency layer.
|
|
@@ -56753,6 +57002,16 @@ function createServer() {
|
|
|
56753
57002
|
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid verdict JSON" }) }] };
|
|
56754
57003
|
}
|
|
56755
57004
|
const updated = resolveFinding(f, v);
|
|
57005
|
+
const outcome = v.status === "confirmed" ? "confirmed" : v.status === "false_positive" ? "false_positive" : null;
|
|
57006
|
+
if (outcome) {
|
|
57007
|
+
recordVerdict({
|
|
57008
|
+
vector: sinkToVector(f.sink?.type ?? ""),
|
|
57009
|
+
outcome,
|
|
57010
|
+
severity: f.classification?.severity,
|
|
57011
|
+
target: f.target?.host ?? f.target?.endpoint,
|
|
57012
|
+
cvss: f.classification?.cvss_score
|
|
57013
|
+
});
|
|
57014
|
+
}
|
|
56756
57015
|
return { content: [{ type: "text", text: JSON.stringify(updated) }] };
|
|
56757
57016
|
});
|
|
56758
57017
|
server.registerTool("scan_leaked_source", {
|
|
@@ -57211,6 +57470,42 @@ ${statusLine}` : statusLine },
|
|
|
57211
57470
|
}, async ({ target, tech, params, mode }) => {
|
|
57212
57471
|
return { content: [{ type: "text", text: JSON.stringify(attackPlan(target, tech ?? [], params ?? [], mode ?? "full")) }] };
|
|
57213
57472
|
});
|
|
57473
|
+
server.registerTool("intelligence", {
|
|
57474
|
+
title: "Query the empirical intelligence ledger",
|
|
57475
|
+
description: "INTELLIGENCE: query the cross-engagement empirical ledger — hit-rates per (vector, tech), top vectors for a tech, or raw query. Verdicts are recorded AUTOMATICALLY by strike_resolve (confirmed/false_positive). Use this to learn what historically worked on a tech BEFORE planning, so a new Laravel target inherits the hit-rates of past Laravel engagements.",
|
|
57476
|
+
inputSchema: {
|
|
57477
|
+
action: _enum(["hit_rates", "top_vectors", "query"]).describe("hit_rates (aggregate) / top_vectors (ranked for a tech) / query (raw filter)"),
|
|
57478
|
+
tech: string2().optional().describe("Tech/framework filter (e.g. flask, laravel, wordpress)"),
|
|
57479
|
+
vector: string2().optional().describe("Vector filter (e.g. sql_injection)"),
|
|
57480
|
+
outcome: string2().optional().describe("Outcome filter (confirmed/false_positive)")
|
|
57481
|
+
}
|
|
57482
|
+
}, async ({ action, tech, vector, outcome }) => {
|
|
57483
|
+
const out = action === "hit_rates" ? hitRates(tech) : action === "top_vectors" ? topVectors(tech ?? "unknown", 10) : queryIntel({ vector, tech, outcome });
|
|
57484
|
+
return { content: [{ type: "text", text: JSON.stringify(out) }] };
|
|
57485
|
+
});
|
|
57486
|
+
server.registerTool("compliance", {
|
|
57487
|
+
title: "Map CWE(s) to compliance frameworks",
|
|
57488
|
+
description: "COMPLIANCE: map a CWE (or a JSON array of CWEs from findings) to OWASP Top 10 (2021), OWASP ASVS v4.0, PCI DSS v4.0, ISO 27001:2022 Annex A, and NIST SP 800-53. Pass a single `cwe` for one mapping, or `cwes` (JSON array) for an aggregate summary. Tells a CISO/auditor which controls a finding violates.",
|
|
57489
|
+
inputSchema: {
|
|
57490
|
+
cwe: string2().optional().describe("A single CWE id (e.g. CWE-89 or 89)"),
|
|
57491
|
+
cwes: string2().optional().describe("JSON array of CWE ids for an aggregate summary")
|
|
57492
|
+
}
|
|
57493
|
+
}, async ({ cwe, cwes }) => {
|
|
57494
|
+
if (cwes) {
|
|
57495
|
+
let arr;
|
|
57496
|
+
try {
|
|
57497
|
+
arr = JSON.parse(cwes);
|
|
57498
|
+
} catch {
|
|
57499
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "invalid cwes JSON" }) }] };
|
|
57500
|
+
}
|
|
57501
|
+
return { content: [{ type: "text", text: JSON.stringify(complianceSummary(arr)) }] };
|
|
57502
|
+
}
|
|
57503
|
+
const m = complianceMap(cwe ?? "");
|
|
57504
|
+
if (!m) {
|
|
57505
|
+
return { content: [{ type: "text", text: JSON.stringify({ error: "CWE not in the compliance table", cwe, hint: "supported ids: 79, 89, 78, 94, 918, 611, 502, 22, 601, 434, 942, 287, 1336, 915, 1321, 352, 319, 693, 200, 862, 639, 640, 798, 327, 306" }) }] };
|
|
57506
|
+
}
|
|
57507
|
+
return { content: [{ type: "text", text: JSON.stringify(m) }] };
|
|
57508
|
+
});
|
|
57214
57509
|
server.registerTool("payload_lookup", {
|
|
57215
57510
|
title: "Look up exploit payloads",
|
|
57216
57511
|
description: "INTEL: find a payload collection (66 categories from PayloadsAllTheThings).",
|
|
@@ -57719,7 +58014,7 @@ ${statusLine}` : statusLine },
|
|
|
57719
58014
|
description: "Route confusion (separate class from source→sink taint): detect attacker-controlled dispatch (call_user_func/forward/dispatch), dynamic method calls ($obj->$m()), dynamic include (LFI), batch/proxy forwarding without per-route auth re-check, and route matching without path normalization.",
|
|
57720
58015
|
inputSchema: { path: string2().describe("Source file path (PHP)") }
|
|
57721
58016
|
}, async ({ path }) => {
|
|
57722
|
-
const code =
|
|
58017
|
+
const code = readFileSync20(path, "utf8");
|
|
57723
58018
|
const findings = detectRouteConfusion(code, path);
|
|
57724
58019
|
return {
|
|
57725
58020
|
content: [{
|
|
@@ -57733,7 +58028,7 @@ ${statusLine}` : statusLine },
|
|
|
57733
58028
|
description: "Complex-bug detection beyond taint: deserialization→POP gadget chain (unserialize + magic method), type juggling (loose ==/!= vs hash/secret), mass assignment (extract/parse_str without a safe flag), prototype pollution (unsafe merge of request data), CRLF/header injection (user input into a header), path confusion (user input into a file path without canonicalization), SSRF (user-controlled URL with no host allowlist), XXE (user XML parsed without disabling entities), and SSTI (user input into a template render with no sandbox).",
|
|
57734
58029
|
inputSchema: { path: string2().describe("Source file path") }
|
|
57735
58030
|
}, async ({ path }) => {
|
|
57736
|
-
const code =
|
|
58031
|
+
const code = readFileSync20(path, "utf8");
|
|
57737
58032
|
const findings = detectComplexBugs(code, path);
|
|
57738
58033
|
return {
|
|
57739
58034
|
content: [{
|
|
@@ -57800,7 +58095,7 @@ ${statusLine}` : statusLine },
|
|
|
57800
58095
|
let lang = language;
|
|
57801
58096
|
if (path && !code) {
|
|
57802
58097
|
try {
|
|
57803
|
-
src =
|
|
58098
|
+
src = readFileSync20(path, "utf8");
|
|
57804
58099
|
} catch {
|
|
57805
58100
|
return { content: [{ type: "text", text: JSON.stringify({ error: `cannot read ${path}` }) }] };
|
|
57806
58101
|
}
|
|
@@ -58036,15 +58331,15 @@ async function serve() {
|
|
|
58036
58331
|
|
|
58037
58332
|
// src/index.ts
|
|
58038
58333
|
init_cli();
|
|
58039
|
-
import { readFileSync as
|
|
58040
|
-
import { join as
|
|
58334
|
+
import { readFileSync as readFileSync24, existsSync as existsSync13 } from "node:fs";
|
|
58335
|
+
import { join as join22 } from "node:path";
|
|
58041
58336
|
import { fileURLToPath as fileURLToPath13 } from "node:url";
|
|
58042
|
-
var ROOT11 =
|
|
58337
|
+
var ROOT11 = join22(fileURLToPath13(new URL(".", import.meta.url)), "..");
|
|
58043
58338
|
function readVersion() {
|
|
58044
58339
|
try {
|
|
58045
|
-
const p =
|
|
58046
|
-
if (
|
|
58047
|
-
return JSON.parse(
|
|
58340
|
+
const p = join22(ROOT11, "package.json");
|
|
58341
|
+
if (existsSync13(p))
|
|
58342
|
+
return JSON.parse(readFileSync24(p, "utf8")).version ?? "1.0.0";
|
|
58048
58343
|
} catch {}
|
|
58049
58344
|
return "1.0.0";
|
|
58050
58345
|
}
|