Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
013529e
Mod. Settings. Moving Vulnerability Check settings to React
AntonV1211 Jul 21, 2026
dd468f4
Mod. Settings. Moving Admin Bar settings to React
AntonV1211 Jul 21, 2026
96adca6
Fix jest config, add test for settings
AntonV1211 Jul 23, 2026
f3fbe87
Jest test for firewall and scanner
AntonV1211 Jul 23, 2026
17c1ee7
Mod. Settings. Moving Miscellaneous settings to React
AntonV1211 Jul 23, 2026
f7ef648
fix php, js test errors
AntonV1211 Jul 24, 2026
ec7fb54
fix php, js test errors
AntonV1211 Jul 24, 2026
7664fd4
New. UserPassCheck. Debugging functionality using the cron task launc…
AntonV1211 Jul 28, 2026
92a845b
Mod. UserPassCheck. Rendering the status of the check and its results
AntonV1211 Jul 30, 2026
170d7b3
Fix js eslint errors, upd common libs
AntonV1211 Jul 30, 2026
c1db3b5
Fix. FW. Improve logs.
svfcode Jul 30, 2026
fa9fc2a
Mod. PSCTab. Caching data for fast content display
AntonV1211 Aug 1, 2026
4569316
Upd. Settings. Add BFP option. (#694)
svfcode Aug 3, 2026
3d4ee02
Upd. Firewall. Improve BFP module to protect woo login. (#693)
svfcode Aug 3, 2026
7e08dd0
Security Firewall UI update
alexander-b-clean Aug 3, 2026
5da43da
Merge branch 'master' of https://github.com/CleanTalk/security-malwar…
AntonV1211 Aug 3, 2026
1709a84
Upd version 2.185.99-dev
AntonV1211 Aug 3, 2026
00988e7
Merge branch 'master' of https://github.com/CleanTalk/security-malwar…
AntonV1211 Aug 3, 2026
944ebac
Upd version 2.185.99-fix
AntonV1211 Aug 3, 2026
0bec033
Merge dev
AntonV1211 Aug 3, 2026
550a486
Merge pull request #697 from CleanTalk/debug_us_pas_chk_av
AntonV1211 Aug 3, 2026
42c0c54
Merge branch 'dev' of https://github.com/CleanTalk/security-malware-f…
AntonV1211 Aug 4, 2026
318ad40
merge dev
AntonV1211 Aug 5, 2026
70ea537
UI update. Renamed the account creation button and description. Add n…
alexander-b-clean Aug 6, 2026
b972a89
Fix. Scan. Improve surface iterator to filter not available dirs. (#705)
svfcode Aug 7, 2026
5c75ded
Upd. Scan. Update skip policy. (#704)
svfcode Aug 7, 2026
15a97ea
Mod. PSCTab. Filtering by installed plug-ins, PC search, active PSC f…
AntonV1211 Aug 7, 2026
55a8977
Fix. PSCTab. Editing the caching logic and general output in accordan…
AntonV1211 Aug 7, 2026
2134cf6
Fix. Integrations. Update upload checker verify from ACF.
svfcode Aug 10, 2026
92ccb31
Fix. PSCTab. Edits for the formation of values ​​for the total number…
AntonV1211 Aug 10, 2026
6e4eeb2
Fix. Scan. Show unknown accordion. (#709)
svfcode Aug 10, 2026
d6d2cd8
File synchronization
alexander-b-clean Aug 10, 2026
70ac16c
Merge dev
AntonV1211 Aug 10, 2026
5cb1cec
Merge pull request #706 from CleanTalk/cache_sec_mod_tab_av
AntonV1211 Aug 10, 2026
1105fac
Fix. Remote Calls. Wrong response fixed. (#707)
Glomberg Aug 10, 2026
d1775fe
Mod. Settings. Transferring settings to React
AntonV1211 Aug 10, 2026
b9871cf
Merge branch 'dev' of https://github.com/CleanTalk/security-malware-f…
AntonV1211 Aug 10, 2026
b693343
Fix. FW. Improve statement on WAF module to prevent false positive. (…
svfcode Aug 11, 2026
9024aa1
Fix errors
AntonV1211 Aug 11, 2026
11e4131
Jest test
AntonV1211 Aug 11, 2026
50410d3
Potential fix for pull request finding
AntonV1211 Aug 11, 2026
38cd5e2
Fix copilot review
AntonV1211 Aug 11, 2026
5570946
Merge branch 'mod_react_15_av' of https://github.com/CleanTalk/securi…
AntonV1211 Aug 11, 2026
d08a731
Sync branch
AntonV1211 Aug 11, 2026
4776572
Fix eslint
AntonV1211 Aug 11, 2026
14aad11
Fix. Settings. Refactoring and deleting old code
AntonV1211 Aug 12, 2026
5854f5d
Merge pull request #692 from CleanTalk/mod_react_15_av
AntonV1211 Aug 12, 2026
e164ca2
Fix. Settings. Improve curl wrapper.
svfcode Aug 12, 2026
2272753
Fix. Settings. Auto cure setting fixed.
Glomberg Aug 12, 2026
117a2ec
Fix. Admin banners. Critical files banner fixed. (#712)
Glomberg Aug 13, 2026
04ec24e
Version: 2.186 and changelog updated.
Glomberg Aug 16, 2026
a55fb2f
Fix. Readme. WP 7.1 compatibility added.
Glomberg Aug 16, 2026
cb3a8e3
Upd. Readme. Changelog updated.
Glomberg Aug 16, 2026
928a67e
Merge remote-tracking branch 'origin/fix' into dev
Glomberg Aug 16, 2026
d0d8229
Merge remote-tracking branch 'origin/dev' into beta
Glomberg Aug 16, 2026
5e03d21
Upd. Readme. Changelog updated.
Glomberg Aug 16, 2026
8770d44
Fix. Code. Bundle rebuilt.
Glomberg Aug 16, 2026
7b00b56
Fix. Upload checker. Check files during meadia uploading fixed. (#713)
Glomberg Aug 17, 2026
3d6e35a
Fix. Code. Unused code removed.
Glomberg Aug 17, 2026
838a662
Merge remote-tracking branch 'origin/dev' into beta
Glomberg Aug 17, 2026
aeca734
Upd. Readme. Changelog updated.
Glomberg Aug 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion css/spbc-settings.min.css

Large diffs are not rendered by default.

5 changes: 0 additions & 5 deletions css/src/spbc-settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,6 @@
.spbc_waf_reason{display: none;}
.spbc_waf_reason_title:hover + .spbc_waf_reason{display: inline;}

/** .spbc_sub* and spbc_affiliate_shortcode used in General settings tab */
.spbc_sub_setting{margin-left: 30px !important;}
.spbc_sub2_setting{margin-left: 60px !important;}
.spbc_affiliate_shortcode{width:inherit !important; min-width: inherit !important}

.spbc_highlighted{
outline-offset: 5px;
outline-color: red;
Expand Down
4 changes: 2 additions & 2 deletions inc/spbc-auth.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ function spbc_authenticate($user, $username)

if ( is_wp_error($user) ) {
/**
* @todo Migrate BFP disable from constant to settings option
* Constant kept for backward compatibility with temporary workaround via wp-config.php
* @psalm-suppress RedundantCondition
*/
if (!SPBC_BFP_DISABLE) {
if (!empty($spbc->settings['bfp__enabled']) && !SPBC_BFP_DISABLE) {
spbc_authenticate__check_brute_force();
}

Expand Down
54 changes: 27 additions & 27 deletions inc/spbc-firewall.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
use CleantalkSP\SpbctWP\Firewall\UploadChecker;
use CleantalkSP\SpbctWP\Helpers\IP;
use CleantalkSP\SpbctWP\Variables\Cookie;
use CleantalkSP\SpbctWP\RenameLoginPage;

// Prevent direct call
if ( ! defined('ABSPATH') ) {
Expand Down Expand Up @@ -51,33 +50,30 @@ function spbc_firewall__check()
spbc_firewall_check_waf($firewall);

if ( class_exists('Poppyz_Core') ) { //fix poppyz plugin early start conflict
$GLOBALS['wp_rewrite'] = is_null($GLOBALS['wp_rewrite']) ? new WP_Rewrite() : $GLOBALS['wp_rewrite']; // Fix for early load WP_Rewrite
}

$login_url = wp_login_url();
if ( $spbc->settings['login_page_rename__enabled'] ) {
$GLOBALS['wp_rewrite'] = is_null($GLOBALS['wp_rewrite']) ? new WP_Rewrite() : $GLOBALS['wp_rewrite']; // Fix for early load WP_Rewrite
$login_url = RenameLoginPage::getURL($spbc->settings['login_page_rename__name']);
if ( empty($GLOBALS['wp_rewrite']) || ! ($GLOBALS['wp_rewrite'] instanceof WP_Rewrite) ) {
$GLOBALS['wp_rewrite'] = new WP_Rewrite(); // Fix for early load WP_Rewrite
}
}

// Compare only the path part of URLs to avoid scheme mismatch issues.
$current_path = Server::getCanonicalPath() ?: Server::getCanonicalUri();
$login_path = parse_url($login_url, PHP_URL_PATH) ?: '/wp-login.php';
$is_login_page = strpos(trim($current_path, '/'), trim($login_path, '/')) === 0;

$firewall->loadFwModule(
new BFP(
array(
'api_key' => $spbc->api_key,
'state' => $spbc,
'is_login_page' => $is_login_page,
'is_logged_in' => Cookie::getString('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')),
'bf_limit' => $spbc->settings['bfp__allowed_wrong_auths'],
'block_period' => $spbc->settings['bfp__block_period__5_fails'],
'count_period' => $spbc->settings['bfp__count_interval'], // Counting login attempts in this interval
/**
* Constant kept for backward compatibility; may be overridden in wp-config.php
* @psalm-suppress RedundantCondition
*/
if (!empty($spbc->settings['bfp__enabled']) && !SPBC_BFP_DISABLE) {
$firewall->loadFwModule(
new BFP(
array(
'api_key' => $spbc->api_key,
'state' => $spbc,
'is_login_page' => spbc_is_login_page_request(),
'is_logged_in' => Cookie::getString('spbc_is_logged_in') === md5($spbc->data['salt'] . get_option('home')),
'bf_limit' => $spbc->settings['bfp__allowed_wrong_auths'],
'block_period' => $spbc->settings['bfp__block_period__5_fails'],
'count_period' => $spbc->settings['bfp__count_interval'], // Counting login attempts in this interval
)
)
)
);
);
}

if (
$spbc->settings['traffic_control__enabled'] &&
Expand Down Expand Up @@ -193,7 +189,9 @@ function spbc_upload_checker__check()
//Nonce can be different here
!(
wp_verify_nonce(Request::getString('_wpnonce') ?: '', 'media-form') ||
wp_verify_nonce(Request::getString('emr_nonce') ?: '', 'media_replace_upload')
wp_verify_nonce(Request::getString('emr_nonce') ?: '', 'media_replace_upload') ||
// ACF Tools > Import Field Groups (JSON)
wp_verify_nonce(Request::getString('_acf_nonce') ?: '', 'import')
)
) {
$run_checker_error = new WP_Error(403, __('You do not have sufficient permissions to upload files. Upload files request wrong', 'security-malware-firewall'));
Expand Down Expand Up @@ -285,7 +283,7 @@ function spbc_firewall_skip_check()
*/
function spbc_firewall_skip_check_uploadchecker()
{
global $spbc;
global $spbc, $pagenow;

if (empty($_FILES)) {
return true;
Expand All @@ -298,6 +296,8 @@ function spbc_firewall_skip_check_uploadchecker()
|| \CleantalkSP\Variables\Server::inUri('/favicon.ico') // Exclude favicon.ico requests from the check
|| spbc_mailpoet_doing_cron()
|| spbc_is_cli()
|| $pagenow === 'upload.php'
|| $pagenow === 'async-upload.php'
) {
return true;
}
Expand Down
139 changes: 139 additions & 0 deletions inc/spbc-pluggable.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<?php

use CleantalkSP\SpbctWP\RenameLoginPage;
use CleantalkSP\Variables\Post;
use CleantalkSP\Variables\Server;

// Prevent direct call
Expand Down Expand Up @@ -95,3 +97,140 @@ function spbc_is_cli()
{
return PHP_SAPI === "cli";
}

/**
* Whether current request is a login page where BFP should enforce blocks.
* Covers wp-login.php (incl. renamed login URL) and WooCommerce My Account.
*
* @return bool
*/
function spbc_is_login_page_request()
{
global $spbc;

$login_url = wp_login_url();
if ( ! empty($spbc->settings['login_page_rename__enabled']) ) {
if ( empty($GLOBALS['wp_rewrite']) || ! ($GLOBALS['wp_rewrite'] instanceof WP_Rewrite) ) {
$GLOBALS['wp_rewrite'] = new WP_Rewrite();
}
$login_url = RenameLoginPage::getURL($spbc->settings['login_page_rename__name']);
}

if ( spbc_request_uri_matches_url($login_url) ) {
return true;
}

return spbc_is_woocommerce_login_request();
}

/**
* Detect WooCommerce My Account page / login form for BFP.
*
* @return bool
*/
function spbc_is_woocommerce_login_request()
{
if ( ! spbc_is_plugin_active('woocommerce/woocommerce.php') ) {
return false;
}

// Login form POST from WooCommerce My Account
if ( Post::getString('woocommerce-login-nonce') !== '' ) {
return true;
}

// Visiting My Account so already-banned IPs are blocked before form submit
$myaccount_page_id = (int) get_option('woocommerce_myaccount_page_id');
if ( ! $myaccount_page_id ) {
return false;
}

$myaccount_url = get_permalink($myaccount_page_id);
if ( ! $myaccount_url ) {
return false;
}

return spbc_request_uri_matches_url($myaccount_url);
}

/**
* Whether the current REQUEST_URI matches the given absolute URL.
* Compares path and, when present, required query args — so plain-permalink
* URLs like /?my-login or /?page_id=37 do not match the whole site.
*
* @param string $url Absolute URL (e.g. from wp_login_url() / get_permalink()).
*
* @return bool
*/
function spbc_request_uri_matches_url($url)
{
$url_parts = parse_url((string) $url);
if ( ! is_array($url_parts) ) {
return false;
}

$target_path = isset($url_parts['path']) ? $url_parts['path'] : '/';
$target_query = isset($url_parts['query']) ? $url_parts['query'] : '';

// Path: canonical (percent-decoded). Query: raw QUERY_STRING — do not take it from
// rawurldecoded REQUEST_URI (%3F in path / %2B semantics would break parsing).
$current_path = Server::getCanonicalPath();
$current_query = (string) Server::get('QUERY_STRING', null, 'url');

if ( $current_path === '' ) {
$current_path = '/';
}

$target_path_norm = spbc_normalize_request_path($target_path);
$current_path_norm = spbc_normalize_request_path($current_path);

// Query-based URLs (plain permalinks / renamed login): require path + query keys.
if ( $target_query !== '' ) {
if ( $target_path_norm !== $current_path_norm ) {
return false;
}

parse_str($target_query, $target_params);
parse_str($current_query, $current_params);

if ( empty($target_params) ) {
return false;
}

foreach ( $target_params as $key => $value ) {
if ( ! array_key_exists($key, $current_params) ) {
return false;
}
if ( $value !== '' && (string) $current_params[$key] !== (string) $value ) {
return false;
}
}

return true;
}

// Path-only URL: never treat bare "/" as a match (would mark every request).
if ( $target_path_norm === '/' ) {
return false;
}

$target_trim = trim($target_path_norm, '/');
$current_trim = trim($current_path_norm, '/');

return $current_trim === $target_trim || strpos($current_trim, $target_trim . '/') === 0;
}

/**
* @param string $path
*
* @return string
*/
function spbc_normalize_request_path($path)
{
$path = (string) $path;
if ( $path === '' || $path === '/' ) {
return '/';
}

return '/' . trim($path, '/');
}
Loading
Loading