blitzstrike 2.4.86 → 2.4.88
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 +19 -0
- package/dist/index.js +32 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,25 @@ 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.88] — 2026-09-17
|
|
9
|
+
|
|
10
|
+
### Changed — XSS detector precision (local taint flow)
|
|
11
|
+
|
|
12
|
+
- `xss` no longer flags a DOM sink merely because a source exists somewhere in the
|
|
13
|
+
same file. It now builds a tainted-variable set via assignment flow (transitive,
|
|
14
|
+
≤3 hops) and flags a sink only when its argument references a tainted variable or
|
|
15
|
+
is a direct source expression. Removes the "source + sink co-occurrence" false
|
|
16
|
+
positives (4 FPs on the 30-lab benchmark) with zero recall loss.
|
|
17
|
+
|
|
18
|
+
## [2.4.87] — 2026-09-17
|
|
19
|
+
|
|
20
|
+
### Fixed — web3 class naming consistency + jwt grounding
|
|
21
|
+
|
|
22
|
+
- Renamed the web3 class `encodePacked_collision` → `encode_packed_collision`
|
|
23
|
+
(snake_case, matching the other classes; fixes resolution through canonical id).
|
|
24
|
+
- Added the `jwt` → `jwt_alg_confusion` synonym so the `jwt` attack-vector resolves
|
|
25
|
+
to its pattern grounding + payout (previously returned no bounty signal).
|
|
26
|
+
|
|
8
27
|
## [2.4.86] — 2026-09-17
|
|
9
28
|
|
|
10
29
|
### Added — Web3 audit extended to 13 bug classes
|
package/dist/index.js
CHANGED
|
@@ -16937,11 +16937,34 @@ function detectCorsMisconfig(code, file, out) {
|
|
|
16937
16937
|
function detectXss(code, file, out) {
|
|
16938
16938
|
const clean = stripCommentsOnly(code);
|
|
16939
16939
|
const ls = lines2(code);
|
|
16940
|
-
const
|
|
16941
|
-
|
|
16940
|
+
const isSourceExpr = (expr) => /\b(?:req\.(?:query|params|body|cookies|headers)|request\.(?:get|args|form|json|values|headers|params)|location\.(?:hash|search|href)|window\.location|document\.(?:URL|referrer)|URLSearchParams|searchParams\.get|getElementById\([^)]*\)\.value|routeParams|queryParams|this\.props)\b/i.test(expr);
|
|
16941
|
+
const tainted = new Set;
|
|
16942
|
+
const assignments = [];
|
|
16943
|
+
const assignRe = /\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)|(?<![\w$.])([A-Za-z_$][\w$]*)\s*=\s*([^;\n]+)/g;
|
|
16944
|
+
let m;
|
|
16945
|
+
while ((m = assignRe.exec(clean)) !== null) {
|
|
16946
|
+
const lhs = m[1] ?? m[3];
|
|
16947
|
+
const rhs = (m[2] ?? m[4] ?? "").trim();
|
|
16948
|
+
if (lhs)
|
|
16949
|
+
assignments.push({ lhs, rhs });
|
|
16950
|
+
}
|
|
16951
|
+
for (let hop = 0;hop < 3; hop++) {
|
|
16952
|
+
let changed = false;
|
|
16953
|
+
for (const a of assignments) {
|
|
16954
|
+
if (tainted.has(a.lhs))
|
|
16955
|
+
continue;
|
|
16956
|
+
const refsTainted = [...tainted].some((t) => new RegExp(`\\b${t}\\b`).test(a.rhs));
|
|
16957
|
+
if (isSourceExpr(a.rhs) || refsTainted) {
|
|
16958
|
+
tainted.add(a.lhs);
|
|
16959
|
+
changed = true;
|
|
16960
|
+
}
|
|
16961
|
+
}
|
|
16962
|
+
if (!changed)
|
|
16963
|
+
break;
|
|
16964
|
+
}
|
|
16965
|
+
if (tainted.size === 0)
|
|
16942
16966
|
return;
|
|
16943
16967
|
const sinkRe = /dangerouslySetInnerHTML|\.innerHTML\s*=|\.outerHTML\s*=|document\.write\s*\(|insertAdjacentHTML\s*\(|\.html\s*\(|eval\s*\(/g;
|
|
16944
|
-
let m;
|
|
16945
16968
|
const seen = new Set;
|
|
16946
16969
|
while ((m = sinkRe.exec(clean)) !== null) {
|
|
16947
16970
|
const ln = lineNo2(code, m.index);
|
|
@@ -16951,9 +16974,8 @@ function detectXss(code, file, out) {
|
|
|
16951
16974
|
const rest = line.slice(line.indexOf(m[0]) + m[0].length);
|
|
16952
16975
|
if (/^\s*["'`]/.test(rest))
|
|
16953
16976
|
continue;
|
|
16954
|
-
|
|
16955
|
-
|
|
16956
|
-
if (m[0] === "dangerouslySetInnerHTML" && !/__html\s*:\s*[^'"`]/.test(line))
|
|
16977
|
+
const refsTainted = [...tainted].some((t) => new RegExp(`\\b${t}\\b`).test(rest));
|
|
16978
|
+
if (!refsTainted && !isSourceExpr(rest))
|
|
16957
16979
|
continue;
|
|
16958
16980
|
seen.add(ln);
|
|
16959
16981
|
out.push({
|
|
@@ -34491,6 +34513,7 @@ var ALIASES = {
|
|
|
34491
34513
|
"rust format string": "rust_format_string",
|
|
34492
34514
|
"format string": "rust_format_string",
|
|
34493
34515
|
"format string injection": "rust_format_string",
|
|
34516
|
+
jwt: "jwt_alg_confusion",
|
|
34494
34517
|
"jwt algorithm confusion": "jwt_alg_confusion",
|
|
34495
34518
|
"jwt alg confusion": "jwt_alg_confusion",
|
|
34496
34519
|
"alg confusion": "jwt_alg_confusion",
|
|
@@ -60489,7 +60512,7 @@ var SEVERITY = {
|
|
|
60489
60512
|
timestamp_dependence: { severity: "medium", cwe: "CWE-1164", category: "block.timestamp / block.number dependence" },
|
|
60490
60513
|
oracle_manipulation: { severity: "high", cwe: "CWE-1235", category: "Spot-price oracle (DEX pair) manipulation" },
|
|
60491
60514
|
unbounded_loop: { severity: "medium", cwe: "CWE-834", category: "Unbounded loop over user-controlled length" },
|
|
60492
|
-
|
|
60515
|
+
encode_packed_collision: { severity: "high", cwe: "CWE-701", category: "abi.encodePacked hash collision (dynamic types)" },
|
|
60493
60516
|
address_zero_check: { severity: "low", cwe: "CWE-20", category: "Missing address(0) validation on privileged assignment" }
|
|
60494
60517
|
};
|
|
60495
60518
|
function lines3(code) {
|
|
@@ -60649,7 +60672,7 @@ function web3Audit(code, file) {
|
|
|
60649
60672
|
}
|
|
60650
60673
|
const packedRe = /keccak256\s*\(\s*abi\.encodePacked\s*\(/g;
|
|
60651
60674
|
while ((m = packedRe.exec(clean)) !== null) {
|
|
60652
|
-
push(out, file, code, m.index, "
|
|
60675
|
+
push(out, file, code, m.index, "encode_packed_collision", (ls[lineNo4(code, m.index) - 1] ?? "").trim(), "`keccak256(abi.encodePacked(...))` over dynamic types (string/bytes/array) is ambiguous — ['a','bc'] and ['ab','c'] pack identically, enabling hash collisions and signature forgery (CWE-701). Use `abi.encode` (which pads + length-prefixes each argument) for any hash or signature digest.");
|
|
60653
60676
|
}
|
|
60654
60677
|
const zeroCheckRe = /\b(constructor|initialize|setOwner|transferOwnership|setAdmin|setFeeRecipient|setPendingOwner)\s*\(/g;
|
|
60655
60678
|
const cleanLines = lines3(clean);
|
|
@@ -60790,7 +60813,7 @@ contract Evil {
|
|
|
60790
60813
|
vm.expectRevert(); // or assert gas consumption
|
|
60791
60814
|
target.processAll();
|
|
60792
60815
|
}`,
|
|
60793
|
-
|
|
60816
|
+
encode_packed_collision: ` function testEncodePackedCollision() public {
|
|
60794
60817
|
// two distinct inputs pack to the same hash
|
|
60795
60818
|
bytes32 a = target.hashFor("a", "bc");
|
|
60796
60819
|
bytes32 b = target.hashFor("ab", "c");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.88",
|
|
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": {
|