blitzstrike 1.0.18 → 1.0.19

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.
Files changed (2) hide show
  1. package/dist/index.js +337 -1
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -49762,13 +49762,336 @@ function nextSteps(ctx) {
49762
49762
  return steps;
49763
49763
  }
49764
49764
 
49765
+ // src/live-recon.ts
49766
+ import { connect } from "node:net";
49767
+ var HTTP_TIMEOUT_MS = 20000;
49768
+ async function httpGet(url) {
49769
+ const controller = new AbortController;
49770
+ const t = setTimeout(() => controller.abort(), HTTP_TIMEOUT_MS);
49771
+ try {
49772
+ const res = await fetch(url, { signal: controller.signal, redirect: "follow" });
49773
+ const body = await res.text();
49774
+ const headers = {};
49775
+ res.headers.forEach((v, k) => {
49776
+ headers[k] = v;
49777
+ });
49778
+ return { status: res.status, headers, body: body.slice(0, 50000), ok: res.ok };
49779
+ } catch (e) {
49780
+ return { status: 0, headers: {}, body: String(e), ok: false };
49781
+ } finally {
49782
+ clearTimeout(t);
49783
+ }
49784
+ }
49785
+ function normalizeTarget2(target) {
49786
+ let t = target.trim();
49787
+ if (!/^https?:\/\//i.test(t))
49788
+ t = `https://${t}`;
49789
+ return t.replace(/\/+$/, "");
49790
+ }
49791
+ function crawlLinks(base, body) {
49792
+ const links = [];
49793
+ const scripts = [];
49794
+ const hrefRe = /<a[^>]+href=["']([^"'#]+)["']/gi;
49795
+ const scriptRe = /<script[^>]+src=["']([^"'#]+)["']/gi;
49796
+ let m;
49797
+ while ((m = hrefRe.exec(body)) !== null) {
49798
+ let u = m[1];
49799
+ if (u.startsWith("/"))
49800
+ u = base + u;
49801
+ else if (!/^https?:\/\//i.test(u))
49802
+ u = base + "/" + u;
49803
+ links.push(u);
49804
+ }
49805
+ while ((m = scriptRe.exec(body)) !== null) {
49806
+ let u = m[1];
49807
+ if (u.startsWith("/"))
49808
+ u = base + u;
49809
+ else if (!/^https?:\/\//i.test(u))
49810
+ u = base + "/" + u;
49811
+ scripts.push(u);
49812
+ }
49813
+ return { links, scripts };
49814
+ }
49815
+ async function fetchRobotsAndSitemap(base) {
49816
+ const robots = [];
49817
+ const sitemap = [];
49818
+ const rob = await httpGet(`${base}/robots.txt`);
49819
+ if (rob.status === 200) {
49820
+ for (const line of rob.body.split(`
49821
+ `)) {
49822
+ const sm = line.match(/^Sitemap:\s*(.+)$/i);
49823
+ if (sm)
49824
+ sitemap.push(sm[1].trim());
49825
+ const allow = line.match(/^(?:Allow|Disallow):\s*(.+)$/i);
49826
+ if (allow && !allow[1].includes("*"))
49827
+ robots.push(base + allow[1].trim());
49828
+ }
49829
+ }
49830
+ const sm = await httpGet(`${base}/sitemap.xml`);
49831
+ if (sm.status === 200 && sm.body.includes("<loc>")) {
49832
+ const locRe = /<loc>([^<]+)<\/loc>/gi;
49833
+ let m;
49834
+ while ((m = locRe.exec(sm.body)) !== null)
49835
+ sitemap.push(m[1].trim());
49836
+ }
49837
+ return { robots, sitemap };
49838
+ }
49839
+ function extractParams(urls) {
49840
+ const params = new Set;
49841
+ for (const u of urls) {
49842
+ try {
49843
+ const q = new URL(u).searchParams;
49844
+ for (const k of q.keys())
49845
+ params.add(k);
49846
+ } catch {}
49847
+ }
49848
+ return [...params];
49849
+ }
49850
+ async function subdomainEnum(domain) {
49851
+ const out = new Set;
49852
+ try {
49853
+ const url = `https://crt.sh/?q=%25.${encodeURIComponent(domain)}&output=json`;
49854
+ const r = await httpGet(url);
49855
+ if (r.status === 200 && r.body.startsWith("[")) {
49856
+ const data = JSON.parse(r.body);
49857
+ for (const entry of data) {
49858
+ for (const field of (entry.name_value ?? "").split(`
49859
+ `)) {
49860
+ const name = field.trim().toLowerCase();
49861
+ if (name && name.endsWith(domain.toLowerCase()) && !name.includes("*"))
49862
+ out.add(name);
49863
+ }
49864
+ }
49865
+ }
49866
+ } catch {}
49867
+ return { subdomains: [...out].sort(), source: "crt.sh (certificate transparency)" };
49868
+ }
49869
+ var COMMON_PORTS = [
49870
+ [21, "ftp"],
49871
+ [22, "ssh"],
49872
+ [25, "smtp"],
49873
+ [53, "dns"],
49874
+ [80, "http"],
49875
+ [110, "pop3"],
49876
+ [135, "msrpc"],
49877
+ [139, "netbios"],
49878
+ [143, "imap"],
49879
+ [443, "https"],
49880
+ [445, "smb"],
49881
+ [993, "imaps"],
49882
+ [995, "pop3s"],
49883
+ [1433, "mssql"],
49884
+ [1521, "oracle"],
49885
+ [3306, "mysql"],
49886
+ [3389, "rdp"],
49887
+ [5432, "postgres"],
49888
+ [6379, "redis"],
49889
+ [8080, "http-alt"],
49890
+ [8443, "https-alt"],
49891
+ [9000, "app"],
49892
+ [9090, "app"],
49893
+ [9200, "elasticsearch"],
49894
+ [11211, "memcached"],
49895
+ [27017, "mongodb"]
49896
+ ];
49897
+ function tcpProbe(host, port, timeout = 2000) {
49898
+ return new Promise((resolve) => {
49899
+ const socket = connect({ host, port, timeout });
49900
+ socket.once("connect", () => {
49901
+ socket.destroy();
49902
+ resolve(true);
49903
+ });
49904
+ socket.once("timeout", () => {
49905
+ socket.destroy();
49906
+ resolve(false);
49907
+ });
49908
+ socket.once("error", () => {
49909
+ socket.destroy();
49910
+ resolve(false);
49911
+ });
49912
+ });
49913
+ }
49914
+ async function scanPorts(host) {
49915
+ const results = [];
49916
+ for (const [port, service] of COMMON_PORTS) {
49917
+ const open = await tcpProbe(host, port);
49918
+ if (open) {
49919
+ const corr = portCorrelation(port);
49920
+ results.push({ port, service, open: true, correlation: corr });
49921
+ }
49922
+ }
49923
+ return results;
49924
+ }
49925
+ var API_PATHS = [
49926
+ "/swagger.json",
49927
+ "/swagger-ui.html",
49928
+ "/openapi.json",
49929
+ "/api-docs",
49930
+ "/v2/api-docs",
49931
+ "/v3/api-docs",
49932
+ "/graphql",
49933
+ "/graphiql",
49934
+ "/actuator",
49935
+ "/actuator/health",
49936
+ "/actuator/env",
49937
+ "/api/swagger.json",
49938
+ "/docs",
49939
+ "/redoc"
49940
+ ];
49941
+ async function discoverApi(base) {
49942
+ const out = [];
49943
+ for (const p of API_PATHS) {
49944
+ const r = await httpGet(`${base}${p}`);
49945
+ if (r.status >= 200 && r.status < 400) {
49946
+ out.push({ path: p, status: r.status, body_size: r.body.length });
49947
+ }
49948
+ }
49949
+ return out;
49950
+ }
49951
+ function extractVersion(headers, body) {
49952
+ const out = [];
49953
+ const server = headers["server"] ?? headers["x-powered-by"] ?? "";
49954
+ const serverVer = /^(nginx|apache|microsoft-iis|openresty|liteSpeed|caddy)\/?([0-9][0-9.\-]*)?/i.exec(server);
49955
+ if (serverVer) {
49956
+ out.push({ product: serverVer[1].toLowerCase(), version: serverVer[2] ?? "unknown", evidence: server });
49957
+ }
49958
+ const phpVer = /php\/([0-9][0-9.\-]*)/i.exec(server);
49959
+ if (phpVer)
49960
+ out.push({ product: "php", version: phpVer[1], evidence: server });
49961
+ const wpVer = /content="WordPress\s+([0-9][0-9.]*)/i.exec(body);
49962
+ if (wpVer)
49963
+ out.push({ product: "wordpress", version: wpVer[1], evidence: `meta generator: WordPress ${wpVer[1]}` });
49964
+ const joomlaVer = /Joomla!?\s*([0-9][0-9.]*)/i.exec(body);
49965
+ if (joomlaVer)
49966
+ out.push({ product: "joomla", version: joomlaVer[1], evidence: `body: Joomla ${joomlaVer[1]}` });
49967
+ const drupalVer = /Drupal\s+([0-9][0-9.]*)/i.exec(body);
49968
+ if (drupalVer)
49969
+ out.push({ product: "drupal", version: drupalVer[1], evidence: `body: Drupal ${drupalVer[1]}` });
49970
+ const powered = headers["x-powered-by"] ?? "";
49971
+ if (powered && !out.some((o) => powered.includes(o.product))) {
49972
+ out.push({ product: powered.split("/")[0].toLowerCase(), version: powered.split("/")[1] ?? "unknown", evidence: powered });
49973
+ }
49974
+ return out;
49975
+ }
49976
+ function correlateIntel(techs, versionList, portList) {
49977
+ const tech = techs.map((t) => ({ tech: t, ...techCorrelation(t) }));
49978
+ const versions = versionList.map((v) => ({
49979
+ product: v.product,
49980
+ version: v.version,
49981
+ correlation: techCorrelation(v.product),
49982
+ payload_lookup: payloadLookup(v.product),
49983
+ template_lookup: templateLookup(v.product, 5)
49984
+ }));
49985
+ const ports = portList.map((p) => ({ port: p.port, service: p.service, ...portCorrelation(p.port) }));
49986
+ return { tech, versions, ports };
49987
+ }
49988
+ async function liveRecon(target, includeActive = false) {
49989
+ const base = normalizeTarget2(target);
49990
+ const host = (() => {
49991
+ try {
49992
+ return new URL(base).hostname;
49993
+ } catch {
49994
+ return target;
49995
+ }
49996
+ })();
49997
+ const root = await httpGet(base);
49998
+ const interestingHeaders = {};
49999
+ for (const k of ["server", "x-powered-by", "x-aspnet-version", "x-drupal-cache", "x-generator", "via", "x-cache", "cf-ray"]) {
50000
+ if (root.headers[k])
50001
+ interestingHeaders[k] = root.headers[k];
50002
+ }
50003
+ const fingerprint = {
50004
+ status: root.status,
50005
+ title: (root.body.match(/<title[^>]*>([^<]+)<\/title>/i) ?? [])[1]?.trim().slice(0, 200) ?? "",
50006
+ server: root.headers["server"] ?? root.headers["x-powered-by"] ?? "",
50007
+ headers: interestingHeaders,
50008
+ body_size: root.body.length
50009
+ };
50010
+ const waf = detectWaf(root.headers, root.body);
50011
+ const techSig = [
50012
+ [/wp-content|wp-includes|wp-json/i, "wordpress"],
50013
+ [/wp-login\.php|wp-admin/i, "wordpress"],
50014
+ [/powered by joomla|com_content/i, "joomla"],
50015
+ [/laravel|_token|csrf-token/i, "laravel"],
50016
+ [/react|__NEXT_DATA__|next\/static/i, "nextjs"],
50017
+ [/angular|ng-version/i, "angular"],
50018
+ [/vue|__vue__|v-data/i, "vue"],
50019
+ [/django|csrftoken|__debug__/i, "django"],
50020
+ [/ruby on rails|rails/i, "rails"],
50021
+ [/asp\.net|__VIEWSTATE|__EVENTVALIDATION/i, "aspnet"],
50022
+ [/phpBB|phpbb/i, "phpbb"],
50023
+ [/mybb|mybb/i, "mybb"],
50024
+ [/drupal|Drupal\.settings/i, "drupal"],
50025
+ [/magento|Mage\./i, "magento"],
50026
+ [/shopify|cdn\.shopify/i, "shopify"],
50027
+ [/grafana|kibana|elastic/i, "grafana-kibana"],
50028
+ [/node\.js|express/i, "nodejs"],
50029
+ [/flask|werkzeug/i, "flask"],
50030
+ [/spring|actuator/i, "spring"]
50031
+ ];
50032
+ const techs = [...new Set(techSig.filter(([re]) => re.test(root.body)).map(([, t]) => t))];
50033
+ const versions = extractVersion(root.headers, root.body);
50034
+ const { links, scripts } = crawlLinks(base, root.body);
50035
+ const { robots, sitemap } = await fetchRobotsAndSitemap(base);
50036
+ const allUrls = [...links, ...scripts, ...robots, ...sitemap];
50037
+ const crawl = { links, scripts, endpoints: [...new Set(allUrls)], robots, sitemap, count: allUrls.length };
50038
+ const params = extractParams(allUrls);
50039
+ const { subdomains } = await subdomainEnum(host);
50040
+ const apiEndpoints = (await discoverApi(base)).map(({ path, status }) => ({ path, status }));
50041
+ let openPorts = [];
50042
+ if (includeActive && root.status > 0) {
50043
+ const scan = await scanPorts(host);
50044
+ openPorts = scan.map(({ port, service }) => ({ port, service }));
50045
+ }
50046
+ const intel = correlateIntel(techs, versions, openPorts);
50047
+ const nextSteps = [];
50048
+ if (waf.detected)
50049
+ nextSteps.push(`WAF detected (${waf.wafs?.map((w) => w.waf).join(", ")}) — consult detect_waf + WAF bypass playbook before exploitation.`);
50050
+ for (const t of techs) {
50051
+ const c = techCorrelation(t);
50052
+ if (c.found)
50053
+ nextSteps.push(`Tech '${t}' maps to known vuln classes — read tech_correlation('${t}') and fetch nuclei templates with template_lookup('${t}').`);
50054
+ }
50055
+ for (const v of versions) {
50056
+ nextSteps.push(`Version ${v.product}/${v.version} detected — check cve_correlation + nvd_lookup for known CVEs affecting ${v.product} ${v.version}.`);
50057
+ }
50058
+ if (crawl.endpoints.length > 0)
50059
+ nextSteps.push(`Found ${crawl.endpoints.length} endpoints — feed them to taint_file/blitz_scan for source analysis, or strike_verify for live validation.`);
50060
+ if (params.length > 0)
50061
+ nextSteps.push(`Discovered input params: ${params.join(", ")} — these are attack-surface entry points; fuzz them with payload_lookup after scope confirms.`);
50062
+ if (subdomains.length > 0)
50063
+ nextSteps.push(`Found ${subdomains.length} subdomains — each is a separate scope surface; enumerate further with fofa_search.`);
50064
+ if (openPorts.length > 0)
50065
+ nextSteps.push(`Open ports: ${openPorts.map((p) => `${p.port}/${p.service}`).join(", ")} — map services via port_correlation and probe each with the relevant tool manual.`);
50066
+ if (apiEndpoints.length > 0)
50067
+ nextSteps.push(`API endpoints exposed (${apiEndpoints.map((e) => e.path).join(", ")}) — audit them with api-security playbook; check for BOLA/IDOR/auth gaps.`);
50068
+ if (nextSteps.length === 0)
50069
+ nextSteps.push("Nothing exposed on the surface — try subdomain enumeration, port scan (active), or request source access for EAGLE-EYE analysis.");
50070
+ nextSteps.push("Every confirmed finding: record with finding_create, attach confidence_score, redact secrets. A hit is a hypothesis until verified.");
50071
+ return {
50072
+ target: base,
50073
+ host,
50074
+ fingerprint,
50075
+ waf,
50076
+ tech: { detected: techs, server: fingerprint.server },
50077
+ versions,
50078
+ crawl,
50079
+ params,
50080
+ subdomains,
50081
+ api_endpoints: apiEndpoints,
50082
+ open_ports: openPorts,
50083
+ intel,
50084
+ next_steps: nextSteps
50085
+ };
50086
+ }
50087
+
49765
50088
  // src/server.ts
49766
50089
  function createServer() {
49767
50090
  const server = new McpServer({
49768
50091
  name: "blitzstrike",
49769
50092
  version: "1.0.0"
49770
50093
  }, {
49771
- instructions: "Blitz Strike is a universal penetration-testing toolbelt with three tiers — " + "BLITZ (reconnaissance / attack-surface mapping), EAGLE-EYE (source-to-sink " + "analysis), STRIKE (live validation) — plus a canonical evidence-first finding " + "engine and a multi-language taint engine.\\n\\n" + "CORE MENTAL MODEL:\\n" + "- A scanner hit is a HYPOTHESIS, not a finding. Live verification (or data-flow " + " proof) is the verdict. Never report an unverified hit as a vulnerability.\\n" + "- Distinguish REACHABLE from mere PRESENT: a sink is only a finding when tainted " + " input reaches it AND it is not neutralized by a sanitizer and not guarded by an " + " auth gate.\\n\\n" + "HOW TO RUN AN AUDIT (start here):\\n" + "1. SCOPE FIRST. Call scope_check(target, scope, mode) before ANY active testing. " + " Passive analysis (reading source, fingerprinting public pages) needs no gate; " + " active probing (exploitation, fuzzing, path brute-force) is blocked until scope " + " authorizes it.\\n" + "2. MAP THE SURFACE (BLITZ). For a source tree use blitz_scan (tree) or blitz_file " + " (single file) then enrich_scan to match sinks to escalation chains. For a live " + " URL use active_scan (it re-checks scope internally): it fingerprints the stack, " + " detects WAF, identifies tech, and probes common endpoints.\\n" + "3. TRACE REACHABILITY (EAGLE-EYE). For every sink, determine whether attacker " + " input actually reaches it:\\n" + " - PHP/JS/TS/Python/Java source: taint_file (auto-detects language) or " + " taint_scan/taint_tree (PHP AST). list_languages shows what's supported.\\n" + " - Any language: trace_data_flow (window heuristic) and eagle_eye/eagle_grep " + " (function-scoped view of sinks + auth gates).\\n" + " A sink counts only if tainted input reaches it unsanitized and unguarded.\\n" + "4. VALIDATE (STRIKE). Confirm live with strike_verify using a MARKER plus a " + " NEGATIVE CONTROL; the finding is confirmed only when your marker reflects AND " + " the negative control stays inert. Use read_tool_manual for the exploit tool's " + " manual, payload_lookup for payloads, detect_waf/tech_correlation for context.\\n" + "5. RECORD + REPORT. Create a canonical finding with finding_create, advance it " + " through the lifecycle with finding_transition, attach confidence_score, and " + " redact any secrets before persisting. Only report findings that survived " + " verification.\\n\\n" + "SUPPORTING LAYERS:\\n" + "- run_engagement: full one-call audit (scope gate -> triage -> chain enrichment " + " -> findings with tool manuals attached).\\n" + "- list_languages / taint_file: multi-language taint (PHP, JS/TS, Python, Java).\\n" + "- list_chains: 57 escalation chains (source -> sink -> impact).\\n" + "- tool_lookup / ensure_tool / list_tools: 130-tool catalog, auto-install.\\n" + "- skill_lookup / read_skill / list_skills: 85 playbooks (WP/PHP 0-day, AD, " + " malware, mobile, cloud, etc.).\\n" + "- read_playbook / read_tool_manual / list_manuals: 270 tool manuals + engagement " + " playbooks.\\n" + "- detect_waf / tech_correlation / cve_correlation / port_correlation: signature " + " + correlation intelligence.\\n" + "- nvd_lookup / fofa_search: CVE + asset reconnaissance (FOFA needs env creds).\\n" + "- remember / memory_lookup / memory_list: persist + recall verified knowledge.\\n\\n" + "IRON RULES:\\n" + "- Scope first; authorized targets only. Refuse out-of-scope or destructive/DoS work.\\n" + "- A hit is a hypothesis; a verified exploit (or proven data-flow) is the finding.\\n" + "- Prefer the one-call run_engagement path; fall back to granular tools when you " + " need finer control."
50094
+ instructions: "Blitz Strike is a universal penetration-testing toolbelt with three tiers — " + "BLITZ (reconnaissance / attack-surface mapping), EAGLE-EYE (source-to-sink " + "analysis), STRIKE (live validation) — plus a canonical evidence-first finding " + "engine and a multi-language taint engine.\\n\\n" + "CORE MENTAL MODEL:\\n" + "- A scanner hit is a HYPOTHESIS, not a finding. Live verification (or data-flow " + " proof) is the verdict. Never report an unverified hit as a vulnerability.\\n" + "- Distinguish REACHABLE from mere PRESENT: a sink is only a finding when tainted " + " input reaches it AND it is not neutralized by a sanitizer and not guarded by an " + " auth gate.\\n\\n" + "HOW TO RUN AN AUDIT (start here):\\n" + "1. SCOPE FIRST. Call scope_check(target, scope, mode) before ANY active testing. " + " Passive analysis (reading source, fingerprinting public pages) needs no gate; " + " active probing (exploitation, fuzzing, path brute-force) is blocked until scope " + " authorizes it.\\n" + "2. MAP THE SURFACE (BLITZ). For a source tree use blitz_scan (tree) or blitz_file " + " (single file) then enrich_scan to match sinks to escalation chains. For a live " + " URL use live_recon for a full pass (fingerprint/WAF/tech/version/crawler/params/" + " subdomains/API endpoints/intel correlation) it returns next_steps. active_scan " + " is the lighter gated alternative. Both re-check scope internally.\\n" + "3. TRACE REACHABILITY (EAGLE-EYE). For every sink, determine whether attacker " + " input actually reaches it:\\n" + " - PHP/JS/TS/Python/Java source: taint_file (auto-detects language) or " + " taint_scan/taint_tree (PHP AST). list_languages shows what's supported.\\n" + " - Any language: trace_data_flow (window heuristic) and eagle_eye/eagle_grep " + " (function-scoped view of sinks + auth gates).\\n" + " A sink counts only if tainted input reaches it unsanitized and unguarded.\\n" + "4. VALIDATE (STRIKE). Confirm live with strike_verify using a MARKER plus a " + " NEGATIVE CONTROL; the finding is confirmed only when your marker reflects AND " + " the negative control stays inert. Use read_tool_manual for the exploit tool's " + " manual, payload_lookup for payloads, detect_waf/tech_correlation for context.\\n" + "5. RECORD + REPORT. Create a canonical finding with finding_create, advance it " + " through the lifecycle with finding_transition, attach confidence_score, and " + " redact any secrets before persisting. Only report findings that survived " + " verification.\\n\\n" + "SUPPORTING LAYERS:\\n" + "- run_engagement: full one-call audit (scope gate -> triage -> chain enrichment " + " -> findings with tool manuals attached).\\n" + "- list_languages / taint_file: multi-language taint (PHP, JS/TS, Python, Java).\\n" + "- list_chains: 57 escalation chains (source -> sink -> impact).\\n" + "- tool_lookup / ensure_tool / list_tools: 130-tool catalog, auto-install.\\n" + "- skill_lookup / read_skill / list_skills: 85 playbooks (WP/PHP 0-day, AD, " + " malware, mobile, cloud, etc.).\\n" + "- read_playbook / read_tool_manual / list_manuals: 270 tool manuals + engagement " + " playbooks.\\n" + "- detect_waf / tech_correlation / cve_correlation / port_correlation: signature " + " + correlation intelligence.\\n" + "- nvd_lookup / fofa_search: CVE + asset reconnaissance (FOFA needs env creds).\\n" + "- remember / memory_lookup / memory_list: persist + recall verified knowledge.\\n\\n" + "IRON RULES:\\n" + "- Scope first; authorized targets only. Refuse out-of-scope or destructive/DoS work.\\n" + "- A hit is a hypothesis; a verified exploit (or proven data-flow) is the finding.\\n" + "- Prefer the one-call run_engagement path; fall back to granular tools when you " + " need finer control."
49772
50095
  });
49773
50096
  server.registerTool("blitz_scan", {
49774
50097
  title: "BLITZ scan",
@@ -49930,6 +50253,19 @@ function createServer() {
49930
50253
  content: [{ type: "text", text: JSON.stringify({ scope_gate: gate, ...result }) }]
49931
50254
  };
49932
50255
  });
50256
+ server.registerTool("live_recon", {
50257
+ title: "Full live reconnaissance (multi-phase)",
50258
+ description: "STRIKE: comprehensive live recon — fingerprint, WAF, tech+version detection, crawler (links/scripts/robots/sitemap), parameter discovery, subdomain enumeration (crt.sh), API endpoint discovery, and intel correlation (tech/CVE/port/payloads/templates). " + "Returns next_steps so you know exactly what to do after each result. " + "ACTIVE port scanning only runs when authorize=true (scope gate). " + "USE WHEN: you have a live URL and need to map its full attack surface before source analysis or exploitation.",
50259
+ inputSchema: {
50260
+ target: string2().describe("Target URL/host"),
50261
+ authorize: boolean2().optional().describe("Explicit authorization to run ACTIVE phases (TCP port scan)")
50262
+ }
50263
+ }, async ({ target, authorize }) => {
50264
+ const result = await liveRecon(target, authorize === true);
50265
+ return {
50266
+ content: [{ type: "text", text: JSON.stringify(result) }]
50267
+ };
50268
+ });
49933
50269
  server.registerTool("run_engagement", {
49934
50270
  title: "STRIKE full engagement",
49935
50271
  description: "STRIKE: run a full 3-tier audit server-side (scope gate -> triage -> chain enrichment -> findings). One call.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blitzstrike",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
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": {