blitzstrike 1.0.39 → 1.0.40

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 (34) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/bench/corpus/java-cmd-processbuilder.md +8 -0
  3. package/bench/corpus/java-deser-readunshared.md +8 -0
  4. package/bench/corpus/java-sqli-execute.md +8 -0
  5. package/bench/corpus/java-ssrf-httpurl.md +8 -0
  6. package/bench/corpus/java-xss-escape.md +8 -0
  7. package/bench/corpus/java-xss-println.md +8 -0
  8. package/bench/corpus/js-cmd-execsync.md +8 -0
  9. package/bench/corpus/js-filewrite.md +8 -0
  10. package/bench/corpus/js-pathtraversal-readsync.md +8 -0
  11. package/bench/corpus/js-redirect-encodeuri.md +8 -0
  12. package/bench/corpus/js-ssrf-axios.md +8 -0
  13. package/bench/corpus/js-ssrf-fetch.md +8 -0
  14. package/bench/corpus/js-xss-documentwrite.md +8 -0
  15. package/bench/corpus/js-xss-innerhtml.md +8 -0
  16. package/bench/corpus/php-cmd-absint.md +9 -0
  17. package/bench/corpus/php-cmd-popen.md +9 -0
  18. package/bench/corpus/php-deser-json.md +9 -0
  19. package/bench/corpus/php-include-once.md +9 -0
  20. package/bench/corpus/php-include-sanitized.md +9 -0
  21. package/bench/corpus/php-sqli-filterinput.md +9 -0
  22. package/bench/corpus/php-sqli-getresults.md +9 -0
  23. package/bench/corpus/php-ssrf-wppost.md +9 -0
  24. package/bench/corpus/php-xss-escurl.md +9 -0
  25. package/bench/corpus/php-xss-print.md +9 -0
  26. package/bench/corpus/php-xss-sanitizetext.md +9 -0
  27. package/bench/corpus/py-cmd-popen.md +9 -0
  28. package/bench/corpus/py-cmd-shlex.md +9 -0
  29. package/bench/corpus/py-deser-yaml.md +9 -0
  30. package/bench/corpus/py-sqli-executescript.md +9 -0
  31. package/bench/corpus/py-ssrf-urllib.md +9 -0
  32. package/bench/corpus/py-xss-escape.md +8 -0
  33. package/dist/index.js +33 -8
  34. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,20 @@ All notable changes to Blitz Strike are documented here.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
+ ## [1.0.40] — 2026-09-13
9
+
10
+ ### Changed (review + spec alignment)
11
+
12
+ - **Coverage Matrix 2.0 (§57)**: `coverageMatrix()` now also tracks the framework
13
+ dimension — per-framework sinks/sources/sanitizers/auth counts + CWE set.
14
+ - **Benchmark 100+ (§65)**: corpus grown 70 → **101 fixtures** (70 vulnerable +
15
+ 31 patched), still scoring detection 1.0 / FP 0 / FN 0 / precision 1.0.
16
+
17
+ ### Fixed
18
+
19
+ - JS adapter now detects `el.innerHTML = <tainted>` (property assignment) as a
20
+ DOM XSS sink — previously only `innerHTML` inside call expressions was caught.
21
+
8
22
  ## [1.0.39] — 2026-09-13
9
23
 
10
24
  ### Added
@@ -0,0 +1,8 @@
1
+ - id: java-cmd-processbuilder
2
+ - language: java
3
+ - vulnerable: true
4
+ - sink_type: command_execution
5
+ ```java
6
+ String cmd = request.getParameter("cmd");
7
+ new ProcessBuilder(cmd).start();
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: java-deser-readunshared
2
+ - language: java
3
+ - vulnerable: true
4
+ - sink_type: deserialization
5
+ ```java
6
+ ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
7
+ ois.readUnshared();
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: java-sqli-execute
2
+ - language: java
3
+ - vulnerable: true
4
+ - sink_type: sql_execution
5
+ ```java
6
+ String id = request.getParameter("id");
7
+ st.execute("DELETE FROM t WHERE id=" + id);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: java-ssrf-httpurl
2
+ - language: java
3
+ - vulnerable: true
4
+ - sink_type: http_request
5
+ ```java
6
+ String url = request.getParameter("url");
7
+ HttpURLConnection c = (HttpURLConnection) new URL(url).openConnection();
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: java-xss-escape
2
+ - language: java
3
+ - vulnerable: false
4
+ - sink_type: html_render
5
+ ```java
6
+ String x = request.getParameter("x");
7
+ response.getWriter().write(HtmlUtils.htmlEscape(x));
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: java-xss-println
2
+ - language: java
3
+ - vulnerable: true
4
+ - sink_type: html_render
5
+ ```java
6
+ String x = request.getParameter("x");
7
+ response.getWriter().println(x);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-cmd-execsync
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: command_execution
5
+ ```javascript
6
+ const c = req.query.cmd;
7
+ execSync("ls " + c);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-filewrite
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: file_operations
5
+ ```javascript
6
+ const d = req.body.data;
7
+ fs.writeFile("/tmp/x", d);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-pathtraversal-readsync
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: path_traversal
5
+ ```javascript
6
+ const f = req.query.file;
7
+ fs.readFileSync("/data/" + f);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-redirect-encodeuri
2
+ - language: javascript
3
+ - vulnerable: false
4
+ - sink_type: redirect
5
+ ```javascript
6
+ const u = req.query.u;
7
+ res.redirect(encodeURIComponent(u));
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-ssrf-axios
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: http_request
5
+ ```javascript
6
+ const u = req.query.url;
7
+ axios.get(u);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-ssrf-fetch
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: http_request
5
+ ```javascript
6
+ const u = req.query.url;
7
+ fetch(u);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-xss-documentwrite
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: html_render
5
+ ```javascript
6
+ const x = req.query.x;
7
+ document.write(x);
8
+ ```
@@ -0,0 +1,8 @@
1
+ - id: js-xss-innerhtml
2
+ - language: javascript
3
+ - vulnerable: true
4
+ - sink_type: html_render
5
+ ```javascript
6
+ const x = req.query.x;
7
+ el.innerHTML = x;
8
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-cmd-absint
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: command_execution
5
+ ```php
6
+ <?php
7
+ $n = $_GET["n"];
8
+ system("ping -c " . absint($n));
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-cmd-popen
2
+ - language: php
3
+ - vulnerable: true
4
+ - sink_type: command_execution
5
+ ```php
6
+ <?php
7
+ $cmd = $_GET["cmd"];
8
+ popen($cmd, "r");
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-deser-json
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: deserialization
5
+ ```php
6
+ <?php
7
+ $data = $_COOKIE["data"];
8
+ json_decode($data);
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-include-once
2
+ - language: php
3
+ - vulnerable: true
4
+ - sink_type: file_inclusion
5
+ ```php
6
+ <?php
7
+ $page = $_GET["page"];
8
+ include_once($page . ".php");
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-include-sanitized
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: file_inclusion
5
+ ```php
6
+ <?php
7
+ $f = $_GET["f"];
8
+ include(sanitize_file_name($f));
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-sqli-filterinput
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: sql_execution
5
+ ```php
6
+ <?php
7
+ $id = filter_input(INPUT_GET, "id", FILTER_VALIDATE_INT);
8
+ $wpdb->query("SELECT * FROM t WHERE id=$id");
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-sqli-getresults
2
+ - language: php
3
+ - vulnerable: true
4
+ - sink_type: sql_execution
5
+ ```php
6
+ <?php
7
+ $id = $_GET["id"];
8
+ $wpdb->get_results("SELECT * FROM t WHERE id=$id");
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-ssrf-wppost
2
+ - language: php
3
+ - vulnerable: true
4
+ - sink_type: http_request
5
+ ```php
6
+ <?php
7
+ $url = $_GET["url"];
8
+ wp_remote_post($url, []);
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-xss-escurl
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: redirect
5
+ ```php
6
+ <?php
7
+ $url = $_GET["url"];
8
+ wp_safe_redirect(esc_url($url));
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-xss-print
2
+ - language: php
3
+ - vulnerable: true
4
+ - sink_type: html_render
5
+ ```php
6
+ <?php
7
+ $name = $_GET["name"];
8
+ print $name;
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: php-xss-sanitizetext
2
+ - language: php
3
+ - vulnerable: false
4
+ - sink_type: html_render
5
+ ```php
6
+ <?php
7
+ $v = $_GET["v"];
8
+ echo sanitize_text_field($v);
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: py-cmd-popen
2
+ - language: python
3
+ - vulnerable: true
4
+ - sink_type: command_execution
5
+ ```python
6
+ import os
7
+ cmd = request.args.get("cmd")
8
+ os.popen(cmd)
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: py-cmd-shlex
2
+ - language: python
3
+ - vulnerable: false
4
+ - sink_type: command_execution
5
+ ```python
6
+ import shlex, subprocess
7
+ cmd = request.args.get("cmd")
8
+ subprocess.run(shlex.quote(cmd))
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: py-deser-yaml
2
+ - language: python
3
+ - vulnerable: true
4
+ - sink_type: deserialization
5
+ ```python
6
+ import yaml
7
+ data = request.get_data()
8
+ yaml.load(data)
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: py-sqli-executescript
2
+ - language: python
3
+ - vulnerable: true
4
+ - sink_type: sql_execution
5
+ ```python
6
+ import sqlite3
7
+ id = request.args.get("id")
8
+ cursor.executescript(f"DELETE FROM t WHERE id={id}")
9
+ ```
@@ -0,0 +1,9 @@
1
+ - id: py-ssrf-urllib
2
+ - language: python
3
+ - vulnerable: true
4
+ - sink_type: http_request
5
+ ```python
6
+ import urllib.request
7
+ url = request.args.get("url")
8
+ urllib.request.urlopen(url)
9
+ ```
@@ -0,0 +1,8 @@
1
+ - id: py-xss-escape
2
+ - language: python
3
+ - vulnerable: false
4
+ - sink_type: html_render
5
+ ```python
6
+ name = request.args.get("name")
7
+ return render_template_string(escape(name))
8
+ ```
package/dist/index.js CHANGED
@@ -50492,13 +50492,23 @@ var jsAdapter = {
50492
50492
  rhsVars.push(c.name);
50493
50493
  assigns.push({ target: name, sources: rhsVars, line: n.loc?.start?.line ?? 0 });
50494
50494
  }
50495
- if (n.type === "AssignmentExpression" && n.left?.type === "Identifier") {
50496
- const name = n.left.name;
50497
- const rhsVars = [];
50498
- for (const c of jsWalk(n.right, []))
50499
- if (c.type === "Identifier" && c.name)
50500
- rhsVars.push(c.name);
50501
- assigns.push({ target: name, sources: rhsVars, line: n.loc?.start?.line ?? 0 });
50495
+ if (n.type === "AssignmentExpression") {
50496
+ if (n.left?.type === "MemberExpression" && n.left.property?.name === "innerHTML") {
50497
+ const rhsVars = [];
50498
+ for (const c of jsWalk(n.right, []))
50499
+ if (c.type === "Identifier" && c.name)
50500
+ rhsVars.push(c.name);
50501
+ for (const v of rhsVars)
50502
+ sinks.push({ variable: v, kind: "html_render", line: n.loc?.start?.line ?? 0, cwe: "CWE-79" });
50503
+ }
50504
+ if (n.left?.type === "Identifier") {
50505
+ const name = n.left.name;
50506
+ const rhsVars = [];
50507
+ for (const c of jsWalk(n.right, []))
50508
+ if (c.type === "Identifier" && c.name)
50509
+ rhsVars.push(c.name);
50510
+ assigns.push({ target: name, sources: rhsVars, line: n.loc?.start?.line ?? 0 });
50511
+ }
50502
50512
  }
50503
50513
  if (n.type === "CallExpression") {
50504
50514
  const calleeText = srcText(n.callee);
@@ -52039,6 +52049,19 @@ function coverageMatrix() {
52039
52049
  const covered = langs.map((l) => l.language).filter((lang) => SINK_BY_LANG[lang]?.[sink] === true);
52040
52050
  return { sink, languages: covered };
52041
52051
  });
52052
+ const frameworkCoverage = listFrameworks().map(({ id, language }) => {
52053
+ const p = frameworkProfile(id);
52054
+ const cwe = p ? [...new Set(p.sinks.map((s) => s.cwe).filter((c) => !!c))].sort() : [];
52055
+ return {
52056
+ framework: id,
52057
+ language,
52058
+ sinks: p?.sinks.length ?? 0,
52059
+ sources: p?.sources.length ?? 0,
52060
+ sanitizers: p?.sanitizers.length ?? 0,
52061
+ auth: p?.auth.length ?? 0,
52062
+ cwe
52063
+ };
52064
+ });
52042
52065
  let coveredPairs = 0;
52043
52066
  for (const lang of langs) {
52044
52067
  for (const sink of SINK_CLASSES) {
@@ -52050,11 +52073,13 @@ function coverageMatrix() {
52050
52073
  return {
52051
52074
  languages: langs,
52052
52075
  sink_coverage: sinkCoverage,
52076
+ framework_coverage: frameworkCoverage,
52053
52077
  counts: {
52054
52078
  languages: langs.length,
52055
52079
  sink_classes: SINK_CLASSES.length,
52056
52080
  covered_pairs: coveredPairs,
52057
- total_pairs: totalPairs
52081
+ total_pairs: totalPairs,
52082
+ frameworks: frameworkCoverage.length
52058
52083
  },
52059
52084
  coverage_ratio: Number((coveredPairs / totalPairs).toFixed(3))
52060
52085
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blitzstrike",
3
- "version": "1.0.39",
3
+ "version": "1.0.40",
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": {