blitzstrike 2.4.177 → 2.4.179

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 CHANGED
@@ -5,6 +5,26 @@ All notable changes to Blitz Strike are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [2.4.179] — 2026-10-11
9
+
10
+ ### Added — WordPress P1-P6 vulnerability pattern taxonomy
11
+
12
+ - `intelligence/frameworks.json` (id=wordpress) now carries a `patterns` taxonomy:
13
+ P1 RCE, P2 arbitrary file upload, P3 unauthenticated account takeover, P4
14
+ unauthenticated password reset, P5 privilege escalation, P6 AJAX/REST
15
+ authorization failure — each with source signals, detect (what to trace),
16
+ fixed (the correct control), and anchor WPVDB record ids.
17
+ - `frameworkProfile()` exposes `patterns`; `framework_intel` returns them.
18
+
19
+ ## [2.4.178] — 2026-10-11
20
+
21
+ ### Added — goal decomposition (six-phase plan)
22
+
23
+ - New `decompose_goal` tool: decompose a high-level goal into the standard
24
+ six-phase sub-goal plan (ENUMERATION → SURFACE → DISCOVERY → VERIFICATION →
25
+ ESCALATION → REPORT), each with its own quantitative condition. `goal_tree`
26
+ shows the parent → sub-goal hierarchy and per-parent progress.
27
+
8
28
  ## [2.4.177] — 2026-10-11
9
29
 
10
30
  ### Added — surface coverage tracker (quantitative progress)
package/dist/index.js CHANGED
@@ -63938,15 +63938,36 @@ function nextId2() {
63938
63938
  counter2 += 1;
63939
63939
  return `G-${String(counter2).padStart(3, "0")}`;
63940
63940
  }
63941
+ var STANDARD_SUBGOALS = [
63942
+ { text: "ENUMERATION — discover every in-scope asset", condition: "every host/subdomain/endpoint enumerated (asset_discovery)" },
63943
+ { text: "SURFACE — map every endpoint, parameter, and action", condition: "coverage >= 100% (every surface item has a terminal verdict)" },
63944
+ { text: "DISCOVERY — find vulnerabilities across every class", condition: "each eligible class × shape carries a terminal verdict" },
63945
+ { text: "VERIFICATION — verify each hypothesis live", condition: "every hypothesis verified (strike_verify/OOB) or refuted" },
63946
+ { text: "ESCALATION — drive each finding to real impact", condition: "every foothold escalated to records/admin/PII or genuinely blocked" },
63947
+ { text: "REPORT — write findings", condition: "generate_report run; zero open obligations" }
63948
+ ];
63941
63949
  function setGoals(texts) {
63942
63950
  for (const t of texts) {
63943
63951
  const text = typeof t === "string" ? t : t.text;
63944
63952
  const condition = typeof t === "string" ? undefined : t.condition;
63953
+ const parent_id = typeof t === "string" ? undefined : t.parent_id;
63945
63954
  const now = new Date().toISOString();
63946
- goals.push({ id: nextId2(), text, condition, status: "pending", created: now, updated: now });
63955
+ goals.push({ id: nextId2(), text, condition, status: "pending", ...parent_id ? { parent_id } : {}, created: now, updated: now });
63947
63956
  }
63948
63957
  return [...goals];
63949
63958
  }
63959
+ function decomposeGoal(text) {
63960
+ const now = new Date().toISOString();
63961
+ const parent = { id: nextId2(), text, status: "pending", created: now, updated: now };
63962
+ goals.push(parent);
63963
+ const sub_goals = [];
63964
+ for (const sg of STANDARD_SUBGOALS) {
63965
+ const g = { id: nextId2(), text: sg.text, condition: sg.condition, status: "pending", parent_id: parent.id, created: now, updated: now };
63966
+ goals.push(g);
63967
+ sub_goals.push(g);
63968
+ }
63969
+ return { parent, sub_goals };
63970
+ }
63950
63971
  function proveGoal(id, evidence, reason) {
63951
63972
  const g = goals.find((x) => x.id === id);
63952
63973
  if (!g)
@@ -63961,6 +63982,13 @@ function goalStatus() {
63961
63982
  const met = goals.filter((g) => g.status === "met").length;
63962
63983
  return { goals: [...goals], all_met: goals.length > 0 && met === goals.length, met, total: goals.length };
63963
63984
  }
63985
+ function goalTree() {
63986
+ const parents = goals.filter((g) => !g.parent_id);
63987
+ return parents.map((p) => {
63988
+ const children = goals.filter((g) => g.parent_id === p.id);
63989
+ return { parent: p, children, children_met: children.filter((c) => c.status === "met").length };
63990
+ });
63991
+ }
63964
63992
 
63965
63993
  // src/facts.ts
63966
63994
  var facts = [];
@@ -66024,6 +66052,23 @@ ${statusLine}` : statusLine },
66024
66052
  }, async () => {
66025
66053
  return { content: [{ type: "text", text: JSON.stringify(goalStatus()) }] };
66026
66054
  });
66055
+ server.registerTool("decompose_goal", {
66056
+ title: "Decompose a high-level goal into the six-phase plan",
66057
+ description: "GOALS: decompose a high-level goal (e.g. 'audit app.example.com') into the standard six-phase sub-goal plan — ENUMERATION → SURFACE → DISCOVERY → VERIFICATION → ESCALATION → REPORT — each registered in the ledger with its own condition (pending). Returns the parent + sub-goals. Then prove each sub-goal with prove_goal as it completes; the task is done only when all are met.",
66058
+ inputSchema: {
66059
+ goal: string2().describe("The high-level goal to decompose")
66060
+ }
66061
+ }, async ({ goal }) => {
66062
+ const r = decomposeGoal(goal);
66063
+ return { content: [{ type: "text", text: JSON.stringify({ ...r, ...goalStatus() }) }] };
66064
+ });
66065
+ server.registerTool("goal_tree", {
66066
+ title: "View the goal hierarchy (parents + sub-goals)",
66067
+ description: "GOALS: return the goal tree — each top-level goal with its sub-goals and how many of each are met. Use to see progress through a decomposed plan.",
66068
+ inputSchema: {}
66069
+ }, async () => {
66070
+ return { content: [{ type: "text", text: JSON.stringify(goalTree()) }] };
66071
+ });
66027
66072
  server.registerTool("record_fact", {
66028
66073
  title: "Record an exploration observation (fact)",
66029
66074
  description: "FACTS: record an observation/conclusion that is NOT a vuln (finding_create) and NOT an asset (asset_discovery) — e.g. 'admin panel is behind SSO', 'upload strips .php', 'param id is reflected'. Pass text, confidence (observed = you triggered it; inferred = deduced from a fingerprint/diff — never report inferred as confirmed), optional target, and optional parent_ids (facts this derives from). Use this so negative/neutral observations are written down instead of lost.",
@@ -67154,7 +67199,7 @@ ${statusLine}` : statusLine },
67154
67199
  });
67155
67200
  server.registerTool("framework_intel", {
67156
67201
  title: "Framework security knowledge",
67157
- description: "PHASE 5: return a framework's security knowledge (sources, sinks, sanitizers, auth gates, routing, ORM, middleware) and optionally scan code with those patterns.",
67202
+ description: "PHASE 5: return a framework's security knowledge (sources, sinks, sanitizers, auth gates, routing, ORM, middleware, and — for WordPress — the P1-P6 vulnerability pattern taxonomy: RCE / upload / ATO / reset / priv-esc / AJAX-REST-authz, each with signals, detect, fixed, and anchor WPVDB ids) and optionally scan code with those patterns.",
67158
67203
  inputSchema: {
67159
67204
  framework: string2().describe("Framework id (see list_frameworks)"),
67160
67205
  code: string2().optional().describe("Optional source code to scan with the framework's patterns")
@@ -576,6 +576,135 @@
576
576
  "pattern": "plugins_loaded",
577
577
  "label": "plugin lifecycle"
578
578
  }
579
+ ],
580
+ "patterns": [
581
+ {
582
+ "id": "P1",
583
+ "name": "Remote code execution",
584
+ "signals": [
585
+ "dynamic callbacks/templates",
586
+ "generated PHP",
587
+ "command/process functions",
588
+ "executable writes"
589
+ ],
590
+ "detect": [
591
+ "eval",
592
+ "assert",
593
+ "variable functions",
594
+ "call_user_func*",
595
+ "shell/process APIs",
596
+ "include paths",
597
+ "generated PHP",
598
+ "executable writes"
599
+ ],
600
+ "fixed": "closed allow-list, least-privilege gate, no request input in generated/evaluated PHP",
601
+ "anchors": [
602
+ "69f9dcd8-ab3c-46ed-ac6b-2f1db35f8d1f",
603
+ "df32569a-e4fe-430b-8310-df7be80d7249",
604
+ "9bb1a4ca-976c-461d-82de-8a3b04a56fbc"
605
+ ]
606
+ },
607
+ {
608
+ "id": "P2",
609
+ "name": "Arbitrary file upload",
610
+ "signals": [
611
+ "$_FILES",
612
+ "remote import",
613
+ "base64 file content",
614
+ "move_uploaded_file",
615
+ "wp_handle_upload",
616
+ "custom directories"
617
+ ],
618
+ "detect": [
619
+ "local filesystem upload",
620
+ "WordPress media upload",
621
+ "remote-fetch/local-copy",
622
+ "third-party storage (confused-deputy)"
623
+ ],
624
+ "fixed": "auth/capability + nonce (CSRF only) + server-derived dest + normalized name + extension+MIME+content allow-list + executable denial",
625
+ "anchors": [
626
+ "e424157e-b79f-4000-8dcc-51413581fdec",
627
+ "043f449f-fc65-4218-83d2-7742e62f2af3",
628
+ "110db433-01ec-47ea-b74f-c3faa1757a3c"
629
+ ]
630
+ },
631
+ {
632
+ "id": "P3",
633
+ "name": "Unauthenticated account takeover",
634
+ "signals": [
635
+ "weak SSO/payment callbacks",
636
+ "QR/OTP login",
637
+ "auto-login helpers",
638
+ "selected user IDs/emails",
639
+ "bad signatures",
640
+ "wp_set_auth_cookie"
641
+ ],
642
+ "detect": [
643
+ "all paths to session establishment",
644
+ "identity lookup"
645
+ ],
646
+ "fixed": "verify canonical provider signatures, bind state/code to one account+flow, short expiry/one-time/attempts+rate limits",
647
+ "anchors": [
648
+ "6576dcd1-aea6-47c0-9157-4ca56f426612",
649
+ "d9f1b40f-526a-44ed-a3ec-a3c1ce0f1ece",
650
+ "56fdcba6-c7b1-443d-9f9d-b738ecaadabc"
651
+ ]
652
+ },
653
+ {
654
+ "id": "P4",
655
+ "name": "Unauthenticated password reset",
656
+ "signals": [
657
+ "public reset routes",
658
+ "request-selected account/key/password/email-body data"
659
+ ],
660
+ "detect": [
661
+ "core/custom reset APIs",
662
+ "mail-body filters"
663
+ ],
664
+ "fixed": "expiring one-time server key bound to account + core validation + trusted reset URL/body",
665
+ "anchors": [
666
+ "79fa8b91-f88e-4249-9f17-9e98e879f6fa",
667
+ "6c2d4489-de82-472d-a5f7-dc01b305fdd0"
668
+ ]
669
+ },
670
+ {
671
+ "id": "P5",
672
+ "name": "Privilege escalation",
673
+ "signals": [
674
+ "client-controlled role/capabilities/custom meta/options",
675
+ "user insertion/update",
676
+ "restore auto-login"
677
+ ],
678
+ "detect": [
679
+ "requests into user/role/cap/meta/option/import/restore mutations"
680
+ ],
681
+ "fixed": "server-side field allow-list, discard public role/capability metadata, operation-specific capability, prohibit arbitrary option names",
682
+ "anchors": [
683
+ "04d64797-751a-4cdd-a37d-70afbad5d784",
684
+ "929f243b-2f1c-4eca-88bc-03b1a86270ed",
685
+ "be3d5432-8f8c-4d45-b6e7-de24352378a8"
686
+ ]
687
+ },
688
+ {
689
+ "id": "P6",
690
+ "name": "AJAX/REST authorization failure",
691
+ "signals": [
692
+ "wp_ajax_nopriv_*",
693
+ "both auth states",
694
+ "public REST permissions",
695
+ "public/shared nonce",
696
+ "role check without ownership"
697
+ ],
698
+ "detect": [
699
+ "every AJAX/REST/admin-post registration -> callback, permissions, request-selected IDs, sink"
700
+ ],
701
+ "fixed": "nonce (CSRF) + authentication (identity) + current_user_can (authority) + object policy (ownership)",
702
+ "anchors": [
703
+ "030939ee-9aa9-4082-934e-c9a07fc3dfc3",
704
+ "c81aa489-0663-40b7-b2ce-f4c8f2edd4b6",
705
+ "e31c9bf0-7340-4bd7-ad6e-6ad01737654a"
706
+ ]
707
+ }
579
708
  ]
580
709
  },
581
710
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blitzstrike",
3
- "version": "2.4.177",
3
+ "version": "2.4.179",
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": {