blitzstrike 2.4.19 → 2.4.20

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,18 @@ 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.20] — 2026-09-14
9
+
10
+ ### Security — command-injection fixes (self-audit)
11
+
12
+ - CRITICAL: `run_catalog_tool` built a shell string (`args.join(" ")` + `shell: true`)
13
+ from the target — an attacker-controlled target with shell metacharacters
14
+ (`evil.com; rm -rf /`) executed arbitrary commands. Now runs the tool directly
15
+ (`spawnSync(args[0], args.slice(1))`, no shell) — the target is a literal argv.
16
+ - MEDIUM: `diff_analyze` / `incremental_scan` / `worktree` interpolated
17
+ user-controlled git refs + branch/path into `execSync` (shell). Now use
18
+ `execFileSync("git", [...])` — no shell interpretation.
19
+
8
20
  ## [2.4.19] — 2026-09-14
9
21
 
10
22
  ### Added — unit tests for 5 deep modules + off-by-one fix
package/dist/index.js CHANGED
@@ -7635,7 +7635,7 @@ function runCatalogTool(hint, target, extraFlags = []) {
7635
7635
  };
7636
7636
  }
7637
7637
  const args = buildCatalogCommand(t, target, extraFlags);
7638
- const r = spawnSync(args.join(" "), { shell: true, timeout: 90000, maxBuffer: 1024 * 1024 });
7638
+ const r = spawnSync(args[0], args.slice(1), { timeout: 90000, maxBuffer: 1024 * 1024 });
7639
7639
  const out = (r.stdout?.toString() ?? "") || (r.stderr?.toString() ?? "");
7640
7640
  return {
7641
7641
  found: true,
@@ -15643,7 +15643,7 @@ var init_update = __esm(() => {
15643
15643
  import { readFileSync as readFileSync20, existsSync as existsSync10 } from "node:fs";
15644
15644
  import { join as join17 } from "node:path";
15645
15645
  import { fileURLToPath as fileURLToPath10 } from "node:url";
15646
- import { execSync as execSync4 } from "node:child_process";
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 });
@@ -15660,13 +15660,13 @@ function validateRelease() {
15660
15660
  checks.push({ name: "CHANGELOG version", ok: false, detail: "CHANGELOG.md not found" });
15661
15661
  }
15662
15662
  try {
15663
- const tag = execSync4("git describe --tags --abbrev=0", { cwd: ROOT8, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
15663
+ const tag = execSync2("git describe --tags --abbrev=0", { cwd: ROOT8, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
15664
15664
  checks.push({ name: "Git tag", ok: tag === `v${VERSION}`, detail: tag, soft: true });
15665
15665
  } catch {
15666
15666
  checks.push({ name: "Git tag", ok: true, detail: "unavailable (no git/tags)", soft: true });
15667
15667
  }
15668
15668
  try {
15669
- const published = execSync4("npm view blitzstrike version", { encoding: "utf8", timeout: 8000, stdio: ["ignore", "pipe", "ignore"] }).trim();
15669
+ const published = execSync2("npm view blitzstrike version", { encoding: "utf8", timeout: 8000, stdio: ["ignore", "pipe", "ignore"] }).trim();
15670
15670
  checks.push({ name: "npm registry version", ok: published === VERSION, detail: published, soft: true });
15671
15671
  } catch {
15672
15672
  checks.push({ name: "npm registry version", ok: true, detail: "unavailable (offline)", soft: true });
@@ -34761,7 +34761,7 @@ async function runAutonomous(target, scope = "", mode = "bug-bounty", maxPasses
34761
34761
  }
34762
34762
 
34763
34763
  // src/ops.ts
34764
- import { execSync } from "node:child_process";
34764
+ import { execSync, execFileSync } from "node:child_process";
34765
34765
  function decomposeBatches(tasks) {
34766
34766
  const remaining = [...tasks];
34767
34767
  const done = new Set;
@@ -34806,13 +34806,13 @@ function worktree(action, path, branch) {
34806
34806
  if (!path)
34807
34807
  return { action, ok: false, error: "path is required for worktree add" };
34808
34808
  const b = branch ?? `blitz-${Date.now().toString(36)}`;
34809
- const out = execSync(`git worktree add -b ${b} "${path}"`, { encoding: "utf8" }).trim();
34809
+ const out = execFileSync("git", ["worktree", "add", "-b", b, path], { encoding: "utf8" }).trim();
34810
34810
  return { action, ok: true, branch: b, path, out };
34811
34811
  }
34812
34812
  if (action === "remove") {
34813
34813
  if (!path)
34814
34814
  return { action, ok: false, error: "path is required for worktree remove" };
34815
- execSync(`git worktree remove "${path}" --force`, { encoding: "utf8" });
34815
+ execFileSync("git", ["worktree", "remove", path, "--force"], { encoding: "utf8" });
34816
34816
  return { action, ok: true, path };
34817
34817
  }
34818
34818
  return { action, ok: false, error: "unknown action (use add | list | remove)" };
@@ -35160,7 +35160,7 @@ function engagementStatus() {
35160
35160
  }
35161
35161
 
35162
35162
  // src/incremental.ts
35163
- import { execSync as execSync2 } from "node:child_process";
35163
+ import { execFileSync as execFileSync2 } from "node:child_process";
35164
35164
  import { writeFileSync as writeFileSync3, mkdtempSync, rmSync } from "node:fs";
35165
35165
  import { join as join11 } from "node:path";
35166
35166
  import { tmpdir } from "node:os";
@@ -54662,7 +54662,7 @@ registerLanguage(javaAdapter);
54662
54662
  var SOURCE_EXTS = [".php", ".phtml", ".js", ".mjs", ".ts", ".tsx", ".py", ".pyw", ".java"];
54663
54663
  function git(repo, args) {
54664
54664
  try {
54665
- return execSync2(`git ${args}`, { cwd: repo, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 }).trim();
54665
+ return execFileSync2("git", args.split(/\s+/).filter(Boolean), { cwd: repo, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 }).trim();
54666
54666
  } catch {
54667
54667
  return "";
54668
54668
  }
@@ -55094,7 +55094,7 @@ function taintTree(root, maxFiles = 2000) {
55094
55094
  import { writeFileSync as writeFileSync4, rmSync as rmSync2, mkdtempSync as mkdtempSync2, readFileSync as readFileSync14 } from "node:fs";
55095
55095
  import { join as join12 } from "node:path";
55096
55096
  import { tmpdir as tmpdir2 } from "node:os";
55097
- import { execSync as execSync3 } from "node:child_process";
55097
+ import { execFileSync as execFileSync3 } from "node:child_process";
55098
55098
  init_scanner();
55099
55099
  function runEngine(code, language, file) {
55100
55100
  if (language === "php") {
@@ -55262,7 +55262,7 @@ var SOURCE_EXTS2 = [".php", ".phtml", ".php5", ".js", ".mjs", ".ts", ".tsx", ".p
55262
55262
  function analyzeGitDiff(repo, base = "HEAD~1", head = "HEAD") {
55263
55263
  const git = (args) => {
55264
55264
  try {
55265
- return execSync3(`git ${args}`, { cwd: repo, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 }).trim();
55265
+ return execFileSync3("git", args.split(/\s+/).filter(Boolean), { cwd: repo, encoding: "utf8", maxBuffer: 50 * 1024 * 1024 }).trim();
55266
55266
  } catch {
55267
55267
  return "";
55268
55268
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blitzstrike",
3
- "version": "2.4.19",
3
+ "version": "2.4.20",
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": {