blitzstrike 2.4.47 → 2.4.48
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 +18 -0
- package/dist/index.js +16 -12
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ 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.48] — 2026-09-14
|
|
9
|
+
|
|
10
|
+
### Changed — Precision + consistency (traced to WP core dispatch)
|
|
11
|
+
|
|
12
|
+
- Grounded the authz/nonce rules in the WordPress core dispatch: `wp_ajax_*` and
|
|
13
|
+
`admin_post_*` fire ONLY when `is_user_logged_in()`, while `*_nopriv_*` fire
|
|
14
|
+
unauthenticated. `missing_authz` is now scoped to nopriv handlers that perform
|
|
15
|
+
a state-changing/privileged operation.
|
|
16
|
+
- Added a DANGEROUS_OP_RE gate: `missing_nonce`/`missing_authz` only fire when
|
|
17
|
+
the handler actually performs a WRITE (option/meta/user/post/comment writes,
|
|
18
|
+
file upload/write, `$wpdb->query/insert/update/delete`, `wp_mail`, `wp_redirect`).
|
|
19
|
+
Read-only handlers (list/search/get) are no longer flagged — removes the CSRF/
|
|
20
|
+
authz false-positive storm (forminator 90→16, elementor 11→4, wp-fastest-cache
|
|
21
|
+
15→1).
|
|
22
|
+
- Removed `is_admin()` / `wp_doing_ajax()` from the auth surface — they are
|
|
23
|
+
request-context checks, not authorization (treating them as auth caused false
|
|
24
|
+
negatives).
|
|
25
|
+
|
|
8
26
|
## [2.4.47] — 2026-09-14
|
|
9
27
|
|
|
10
28
|
### Changed — WordPress integration coverage is now COMPLETE (class-method + direct handlers)
|
package/dist/index.js
CHANGED
|
@@ -56478,8 +56478,9 @@ function handlerName(expr) {
|
|
|
56478
56478
|
return null;
|
|
56479
56479
|
}
|
|
56480
56480
|
var INDIRECT_AUTH = /\b[a-zA-Z0-9_]*(auth|permission|cap|nonce|can_|check|verify|allow)[a-zA-Z0-9_]*\s*\(/;
|
|
56481
|
-
var AUTH_RE = /current_user_can|is_user_logged_in|
|
|
56481
|
+
var AUTH_RE = /current_user_can|is_user_logged_in|is_super_admin|current_user_can_edit_post|authorize/;
|
|
56482
56482
|
var NONCE_RE = /wp_verify_nonce|check_ajax_referer|check_admin_referer|verify_nonce/;
|
|
56483
|
+
var DANGEROUS_OP_RE = /\b(update_option|add_option|delete_option|update_site_option|delete_site_option|update_post_meta|add_post_meta|delete_post_meta|update_user_meta|add_user_meta|delete_user_meta|update_metadata|add_metadata|delete_metadata|set_transient|delete_transient|wp_insert_post|wp_update_post|wp_delete_post|wp_trash_post|wp_untrash_post|wp_insert_comment|wp_update_comment|wp_delete_comment|wp_insert_user|wp_update_user|wp_delete_user|wp_create_user|wp_set_current_user|set_user_role|wp_set_auth_cookie|wp_mail|wp_new_user_notification|wp_handle_upload|move_uploaded_file|wp_upload_bits|wp_set_object_terms|wp_set_post_terms|wp_schedule_event|wp_clear_scheduled_hook|wp_redirect|file_put_contents|unlink|rename|wpdb->query|wpdb->insert|wpdb->update|wpdb->delete|wpdb->replace)\s*\(/;
|
|
56483
56484
|
function detectWpAuthz(code, file, out) {
|
|
56484
56485
|
const ajaxRe = /add_action\s*\(\s*['"](wp_ajax(?:_nopriv)?_\w+)['"]\s*,\s*(.+?)\s*\)/g;
|
|
56485
56486
|
let m;
|
|
@@ -56494,12 +56495,13 @@ function detectWpAuthz(code, file, out) {
|
|
|
56494
56495
|
continue;
|
|
56495
56496
|
const hasCap = AUTH_RE.test(body) || INDIRECT_AUTH.test(body);
|
|
56496
56497
|
const hasNonce = NONCE_RE.test(body);
|
|
56498
|
+
const dangerous = DANGEROUS_OP_RE.test(body);
|
|
56497
56499
|
const line = lineNoOf(code, m.index);
|
|
56498
|
-
if (nopriv && !hasCap) {
|
|
56499
|
-
out.push({ file, line, type: "missing_authz", category: "Missing capability check (unauthenticated AJAX handler)", severity: "high", evidence: `add_action('${hook}', ...)`, detail: `Unauthenticated AJAX handler '${handler}()' performs no current_user_can()/authorization check —
|
|
56500
|
+
if (nopriv && !hasCap && dangerous) {
|
|
56501
|
+
out.push({ file, line, type: "missing_authz", category: "Missing capability check (unauthenticated AJAX handler)", severity: "high", evidence: `add_action('${hook}', ...)`, detail: `Unauthenticated AJAX handler '${handler}()' performs a privileged/state-changing operation with no current_user_can()/authorization check — auth bypass / privilege escalation.` });
|
|
56500
56502
|
}
|
|
56501
|
-
if (!hasNonce) {
|
|
56502
|
-
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `AJAX handler '${handler}()'
|
|
56503
|
+
if (!hasNonce && dangerous) {
|
|
56504
|
+
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `AJAX handler '${handler}()' performs a state-changing operation without nonce verification (wp_verify_nonce / check_ajax_referer) — CSRF.` });
|
|
56503
56505
|
}
|
|
56504
56506
|
}
|
|
56505
56507
|
const adminRe = /add_action\s*\(\s*['"](admin_post(?:_nopriv)?_\w+)['"]\s*,\s*(.+?)\s*\)/g;
|
|
@@ -56514,12 +56516,13 @@ function detectWpAuthz(code, file, out) {
|
|
|
56514
56516
|
continue;
|
|
56515
56517
|
const hasCap = AUTH_RE.test(body) || INDIRECT_AUTH.test(body);
|
|
56516
56518
|
const hasNonce = NONCE_RE.test(body);
|
|
56519
|
+
const dangerous = DANGEROUS_OP_RE.test(body);
|
|
56517
56520
|
const line = lineNoOf(code, m.index);
|
|
56518
|
-
if (nopriv && !hasCap) {
|
|
56519
|
-
out.push({ file, line, type: "missing_authz", category: "Missing capability check (unauthenticated admin-post handler)", severity: "high", evidence: `add_action('${hook}', ...)`, detail: `Unauthenticated admin-post handler '${handler}()'
|
|
56521
|
+
if (nopriv && !hasCap && dangerous) {
|
|
56522
|
+
out.push({ file, line, type: "missing_authz", category: "Missing capability check (unauthenticated admin-post handler)", severity: "high", evidence: `add_action('${hook}', ...)`, detail: `Unauthenticated admin-post handler '${handler}()' performs a privileged/state-changing operation with no authorization check — auth bypass / privilege escalation.` });
|
|
56520
56523
|
}
|
|
56521
|
-
if (!hasNonce) {
|
|
56522
|
-
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `admin-post handler '${handler}()'
|
|
56524
|
+
if (!hasNonce && dangerous) {
|
|
56525
|
+
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `admin-post handler '${handler}()' performs a state-changing operation without nonce verification — CSRF.` });
|
|
56523
56526
|
}
|
|
56524
56527
|
}
|
|
56525
56528
|
const restRe = /register_rest_route\s*\(\s*['"]([^'"]+)['"]\s*,\s*['"]([^'"]+)['"]/g;
|
|
@@ -56543,11 +56546,12 @@ function detectWpAuthz(code, file, out) {
|
|
|
56543
56546
|
continue;
|
|
56544
56547
|
const hasCap = AUTH_RE.test(body) || INDIRECT_AUTH.test(body);
|
|
56545
56548
|
const hasNonce = NONCE_RE.test(body);
|
|
56549
|
+
const dangerous = DANGEROUS_OP_RE.test(body);
|
|
56546
56550
|
const line = lineNoOf(code, m.index);
|
|
56547
|
-
if (!hasNonce) {
|
|
56548
|
-
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification (direct request handler)", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `Request handler '${handler}()' (on '${hook}')
|
|
56551
|
+
if (!hasNonce && dangerous) {
|
|
56552
|
+
out.push({ file, line, type: "missing_nonce", category: "Missing nonce verification (direct request handler)", severity: "medium", evidence: `add_action('${hook}', ...)`, detail: `Request handler '${handler}()' (on '${hook}') performs a state-changing operation without nonce verification — CSRF.` });
|
|
56549
56553
|
}
|
|
56550
|
-
if (!hasCap &&
|
|
56554
|
+
if (!hasCap && dangerous) {
|
|
56551
56555
|
out.push({ file, line, type: "missing_authz", category: "Missing capability check (direct request handler)", severity: "high", evidence: `add_action('${hook}', ...)`, detail: `Request handler '${handler}()' (on '${hook}') performs a privileged/state-changing operation with no capability check — auth bypass / privilege escalation.` });
|
|
56552
56556
|
}
|
|
56553
56557
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blitzstrike",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.48",
|
|
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": {
|