REPORT / 01

Analysis Report · Folder Analysis cache/wp-simple-firewall_21.0.9 → cache/wp-simple-firewall_21.0.10 — CVE-2025-15370

Shared security patch analysis results

mode patchdiff ai claude_cli haiku
02 · Lifecycle actions cancel · resume · skip · regenerate
03 · Share this analysis copy link · embed report
03 · CVE Security Analysis & Writeups ai-generated · per cve

Comprehensive security analysis generated by AI for each confirmed CVE match. Click on a CVE to view the detailed writeup including vulnerability background, technical details, patch analysis, and PoC guide.

CVE-2025-15370 NVD
AI-Generated Analysis
05 · Findings filter · search · paginate
Use quotes for exact: "SQL injection" · Operators: hello AND bye, admin OR root, -error, NOT warning
Showing 0 to 0 of 0 results
src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigEdit.php AI: 1 vulnerabilities 1 true positive CVE-2025-15370
--- cache/wp-simple-firewall_21.0.9/src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigEdit.php	2026-01-16 00:19:52.739173051 +0000+++ cache/wp-simple-firewall_21.0.10/src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigEdit.php	2026-01-16 00:20:17.732743029 +0000@@ -3,6 +3,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Actions\Render\Components\UserMfa;  use FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Actions\Traits\SecurityAdminNotRequired;+use FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Exceptions\ActionException; use FernleafSystems\Wordpress\Services\Services;  class ConfigEdit extends UserMfaBase {@@ -15,7 +16,15 @@  	protected function getRenderData() :array { 		$con = self::con();-		$user = Services::WpUsers()->getUserById( (int)$this->action_data[ 'user_id' ] );++		$WPU = Services::WpUsers();+		$currentUser = $WPU->getCurrentWpUser();+		$requestedUserID = (int)( $this->action_data[ 'user_id' ] ?? 0 );+		if ( $requestedUserID > 0 && $currentUser->ID !== $requestedUserID && !$WPU->isUserAdmin( $currentUser ) ) {+			throw new ActionException( __( 'Invalid profile request.', 'wp-simple-firewall' ) );+		}++		$user = $requestedUserID > 0 ? $WPU->getUserById( $requestedUserID ) : $currentUser;  		$providers = \array_map( 			fn( $provider ) => $provider->getProviderName(),
AI Analysis
Vulnerability Existed: yes
TRUE POSITIVE
Privilege Escalation / Improper Access Control - CWE-639 - src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigEdit.php Lines 19-24

Old Code:
```php
$user = Services::WpUsers()->getUserById( (int)$this->action_data[ 'user_id' ] );
```

Fixed Code:
```php
$WPU = Services::WpUsers();
$currentUser = $WPU->getCurrentWpUser();
$requestedUserID = (int)( $this->action_data[ 'user_id' ] ?? 0 );
if ( $requestedUserID > 0 && $currentUser->ID !== $requestedUserID && !$WPU->isUserAdmin( $currentUser ) ) {
	throw new ActionException( __( 'Invalid profile request.', 'wp-simple-firewall' ) );
}

$user = $requestedUserID > 0 ? $WPU->getUserById( $requestedUserID ) : $currentUser;
```

Explanation:
The original code allowed any user to access MFA configuration for any other user by simply providing a `user_id` parameter without proper authorization checks. This is a classic privilege escalation vulnerability where a non-admin user could potentially view or modify the MFA settings of any other user account. The fix adds proper access control by:
1. Retrieving the current authenticated user
2. Validating that non-admin users can only access their own MFA configuration
3. Only allowing admin users to access other users' configurations
4. Throwing an `ActionException` if an unauthorized access attempt is made
5. Defaulting to the current user if no valid user_id is provided

This directly addresses CWE-639 (Authorization through User-Controlled Key).
CVE Analysis Results:
CVE-2025-15370: Yes
View CVE Description
The Shield: Blocks Bots, Protects Users, and Prevents Security Breaches plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 21.0.9 via the MfaGoogleAuthToggle class due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to disable Google Authenticator for any user.
src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigForm.php AI: 1 vulnerabilities 1 true positive CVE-2025-15370
--- cache/wp-simple-firewall_21.0.9/src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigForm.php	2026-01-16 00:19:52.739173051 +0000+++ cache/wp-simple-firewall_21.0.10/src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigForm.php	2026-01-16 00:20:17.732743029 +0000@@ -3,6 +3,7 @@ namespace FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Actions\Render\Components\UserMfa;  use FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Actions\Traits\AnyUserAuthRequired;+use FernleafSystems\Wordpress\Plugin\Shield\ActionRouter\Exceptions\ActionException; use FernleafSystems\Wordpress\Services\Services;  class ConfigForm extends UserMfaBase {@@ -22,7 +23,13 @@  	protected function getRenderData() :array { 		$WPU = Services::WpUsers();-		$user = $WPU->getUserById( (int)$this->action_data[ 'user_id' ] ?? $WPU->getCurrentWpUserId() );+		$currentUser = $WPU->getCurrentWpUser();+		$requestedUserID = (int)( $this->action_data[ 'user_id' ] ?? 0 );+		if ( $requestedUserID > 0 && $currentUser->ID !== $requestedUserID && !self::con()->this_req->is_security_admin ) {+			throw new ActionException( __( 'Invalid profile request.', 'wp-simple-firewall' ) );+		}++		$user = $requestedUserID > 0 ? $WPU->getUserById( $requestedUserID ) : $currentUser;  		$providerRenders = \array_map( 			fn( $provider ) => $provider->renderUserProfileConfigFormField(),
AI Analysis
```
Vulnerability Existed: yes
TRUE POSITIVE
Broken Access Control - CWE-639 - src/lib/src/ActionRouter/Actions/Render/Components/UserMfa/ConfigForm.php - Lines 26-31

[Old Code]
$user = $WPU->getUserById( (int)$this->action_data[ 'user_id' ] ?? $WPU->getCurrentWpUserId() );

[Fixed Code]
$currentUser = $WPU->getCurrentWpUser();
$requestedUserID = (int)( $this->action_data[ 'user_id' ] ?? 0 );
if ( $requestedUserID > 0 && $currentUser->ID !== $requestedUserID && !self::con()->this_req->is_security_admin ) {
    throw new ActionException( __( 'Invalid profile request.', 'wp-simple-firewall' ) );
}

$user = $requestedUserID > 0 ? $WPU->getUserById( $requestedUserID ) : $currentUser;

Explanation:
The original code allowed any authenticated user to view or configure MFA settings for any other user by simply passing a `user_id` parameter in the request, with no authorization check. An authenticated user could manipulate the `user_id` value to access another user's MFA configuration form.

The fix introduces proper authorization validation: it retrieves the current user, extracts the requested user ID, and explicitly checks that either (1) the requested user matches the current user's ID, or (2) the current user is a security administrator. If neither condition is met, an ActionException is thrown, preventing unauthorized access to other users' MFA configurations.
```
CVE Analysis Results:
CVE-2025-15370: Yes
View CVE Description
The Shield: Blocks Bots, Protects Users, and Prevents Security Breaches plugin for WordPress is vulnerable to Insecure Direct Object Reference in all versions up to, and including, 21.0.9 via the MfaGoogleAuthToggle class due to missing validation on a user controlled key. This makes it possible for authenticated attackers, with Subscriber-level access and above, to disable Google Authenticator for any user.
Showing 1 to 2 of 2 results