CVE-2025-10736

ReviewX – WooCommerce Product Reviews with Multi-Criteria, Reminder Emails, Google Reviews, Schema & More <= 2.2.10 - Incorrect Authorization to Unauthenticated Information Exposure and Data Manipulation

mediumImproper Authorization
6.5
CVSS Score
6.5
CVSS Score
medium
Severity
2.2.12
Patched in
1d
Time to patch

Description

The ReviewX – WooCommerce Product Reviews with Multi-Criteria, Reminder Emails, Google Reviews, Schema & More plugin for WordPress is vulnerable to unauthorized access of data due to improper authorization checks on the userAccessibility() function in all versions up to, and including, 2.2.10. This makes it possible for unauthenticated attackers to access protected REST API endpoints, extract and modify information related to users and plugin's configuration

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=2.2.10
PublishedMarch 22, 2026
Last updatedMarch 23, 2026
Affected pluginreviewx

What Changed in the Fix

Changes introduced in v2.2.12

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2025-10736 ReviewX Improper Authorization ## 1. Vulnerability Summary The **ReviewX** plugin (versions <= 2.2.10) contains an improper authorization vulnerability in its REST API implementation. The core of the issue lies in the `userAccessibility()` function, which serves as a…

Show full research plan

Research Plan: CVE-2025-10736 ReviewX Improper Authorization

1. Vulnerability Summary

The ReviewX plugin (versions <= 2.2.10) contains an improper authorization vulnerability in its REST API implementation. The core of the issue lies in the userAccessibility() function, which serves as a permission_callback for various REST API routes. This function fails to correctly validate the authentication status or capabilities of the requester, allowing unauthenticated users to access endpoints intended for administrators. This leads to the exposure of sensitive user data and the ability to manipulate plugin configurations.

2. Attack Vector Analysis

  • Endpoint Namespace: reviewx/v1 (inferred from plugin slug and WpApi.php logic).
  • Base Route: /wp-json/reviewx/v1/admin (based on BaseApi::getPrefix() returning /admin/api/v1).
  • Target Endpoints:
    • GET /wp-json/reviewx/v1/admin/get-settings: Information Exposure (Plugin Config).
    • GET /wp-json/reviewx/v1/admin/get-users: Information Exposure (User Data).
    • POST /wp-json/reviewx/v1/admin/update-settings: Data Manipulation (Plugin Config).
  • Authentication: None required (Unauthenticated).
  • Preconditions: The plugin must be active. No specific settings are required as the vulnerability exists in the core API registration.

3. Code Flow

  1. Request Entry: An unauthenticated HTTP request is made to a REST route registered by the plugin (e.g., /wp-json/reviewx/v1/admin/get-settings).
  2. Route Matching: WordPress matches the request to the ReviewX REST controller.
  3. Permission Check: WordPress calls the permission_callback associated with the route. Based on the vulnerability description, this is the userAccessibility() function.
  4. Vulnerable Logic: The userAccessibility() function (likely located in app/Rest/RestRoute.php or similar, though file not provided) returns true or fails to perform a current_user_can('manage_options') check for unauthenticated users.
  5. Execution: Because the permission check passes, the controller method (e.g., get_settings) executes and returns sensitive data or processes a configuration update.

4. Nonce Acquisition Strategy

While the vulnerability description suggests improper authorization (meaning the permission_callback itself is flawed), WordPress REST API generally requires a X-WP-Nonce for authenticated stateful requests (via cookies). For unauthenticated requests, the permission_callback is the primary gatekeeper.

If the userAccessibility() function explicitly checks for a nonce or if we need to simulate a "legitimate" request context:

  1. Identify Script Loading: ReviewX enqueues scripts on pages containing its shortcodes.
  2. Create Trigger Page: Create a page with the [reviewx_pagination] shortcode.
    • wp post create --post_type=page --post_status=publish --post_content='[reviewx_pagination]'
  3. Navigate and Extract: Use the browser to load the page and extract the localized data.
  4. JS Variable: ReviewX typically uses rvx_params.
  5. Extraction Command:
    • browser_eval("window.rvx_params?.nonce") or browser_eval("window.rvx_params?.rest_nonce")

Note: If userAccessibility() returns true unconditionally, no nonce is required for the exploit.

5. Exploitation Strategy

Phase 1: Information Exposure (Plugin Settings)

  • Target: Retrieve plugin configuration.
  • Request:
    GET /wp-json/reviewx/v1/admin/get-settings HTTP/1.1
    Host: TARGET_HOST
    
  • Tool: http_request

Phase 2: Information Exposure (User Data)

  • Target: Retrieve list of users.
  • Request:
    GET /wp-json/reviewx/v1/admin/get-users HTTP/1.1
    Host: TARGET_HOST
    
  • Tool: http_request

Phase 3: Data Manipulation (Configuration Update)

  • Target: Disable a feature or change a setting (e.g., setting enable_photo_review to false).
  • Request:
    POST /wp-json/reviewx/v1/admin/update-settings HTTP/1.1
    Host: TARGET_HOST
    Content-Type: application/json
    
    {
      "settings": {
          "enable_photo_review": false
      }
    }
    
  • Tool: http_request

6. Test Data Setup

  1. Install Plugin: Ensure ReviewX <= 2.2.10 is installed and active.
  2. Create Dummy Users: Create a few users with different roles to verify they appear in the get-users output.
    • wp user create victim1 victim1@example.com --role=editor
  3. Configure Settings: Set some initial values in the ReviewX admin panel (if accessible) or via CLI to have something to change.
  4. Create Page for Nonce (Backup):
    • wp post create --post_type=page --post_title="Review Test" --post_status=publish --post_content='[reviewx_pagination]' --post_name='review-test'

7. Expected Results

  • Information Exposure: The get-settings request should return a JSON object containing plugin configuration keys (e.g., license_key, email_settings, etc.). The get-users request should return a list of WordPress users.
  • Data Manipulation: The update-settings request should return a success message (e.g., {"success": true}).

8. Verification Steps

  1. Check Exposed Data: Inspect the JSON response from Phase 1 and 2 for sensitive fields.
  2. Verify Configuration Change: Use WP-CLI to check the option value in the database after Phase 3.
    • wp option get reviewx_settings (Note: the option name might be rvx_settings or similar; check wp option list --search="*reviewx*" first).
  3. Compare State: Verify the change in the WordPress admin dashboard under ReviewX Settings.

9. Alternative Approaches

  • Alternative Namespaces: If reviewx/v1 fails, try rvx/v1 or reviewx/api/v1 (based on WpApi.php base URL logic).
  • Alternative Methods: Some plugins use _method=POST or _method=PUT parameters if the server blocks certain verbs.
  • Parameter Fuzzing: If update-settings requires a specific structure, use the output of get-settings as a template for the POST payload.
  • Direct Option Access: Check for routes like GET /wp-json/reviewx/v1/admin/options if the above endpoints are 404.
Research Findings
Static analysis — not yet PoC-verified

Summary

The ReviewX plugin fails to implement proper authorization checks within the `userAccessibility()` function, which acts as a permission callback for various REST API routes. This oversight allows unauthenticated attackers to access administrative endpoints to retrieve sensitive user data and modify the plugin's internal configuration.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.10/app/Api/BaseApi.php /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/BaseApi.php
--- /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.10/app/Api/BaseApi.php	2025-09-21 15:15:14.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/BaseApi.php	2025-10-15 13:32:48.000000000 +0000
@@ -35,6 +35,6 @@
      */
     public function getDefaultHeaders() : array
     {
-        return ['Authorization' => 'Bearer ' . Helper::getAuthToken(), 'Accept' => 'application/json', 'X-Domain' => Helper::getWpDomainNameOnly(), 'X-Theme' => wp_get_theme()->get('Name'), 'X-Site-Locale' => get_locale(), 'X-Request-Id' => \sha1(\time() . Client::getUid()), 'X-Wp-Version' => get_bloginfo("version"), 'X-Reviewx-Version' => RVX_VERSION, 'X-Environment' => Helper::plugin()->isProduction() ? 'production' : 'development'];
+        return ['Authorization' => 'Bearer ' . Helper::getAuthToken(), 'X-Auth-Token' => 'Bearer ' . Helper::getAuthToken(), 'Accept' => 'application/json', 'X-Domain' => Helper::getWpDomainNameOnly(), 'X-Theme' => wp_get_theme()->get('Name'), 'X-Site-Locale' => get_locale(), 'X-Request-Id' => \sha1(\time() . Client::getUid()), 'X-Wp-Version' => get_bloginfo("version"), 'X-Reviewx-Version' => RVX_VERSION, 'X-Environment' => Helper::plugin()->isProduction() ? 'production' : 'development'];
     }
 }
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.10/app/Api/WpApi.php /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/WpApi.php
--- /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.10/app/Api/WpApi.php	2025-09-21 15:15:14.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/WpApi.php	2025-10-15 13:32:48.000000000 +0000
@@ -72,6 +72,7 @@
         $headers = ['Content-Type' => 'application/json'];
         if ($this->token) {
             $headers['Authorization'] = 'Bearer ' . $this->token;
+            $headers['X-Auth-Token'] = 'Bearer ' . $this->token;
         }
         return $headers;
     }

Exploit Outline

The exploit involves sending unauthenticated requests to the plugin's REST API endpoints located under the `/wp-json/reviewx/v1/admin/` namespace. Because the `userAccessibility()` permission callback incorrectly returns true for unauthenticated users, an attacker can access sensitive information or perform unauthorized actions. To extract data, an attacker sends a GET request to `/wp-json/reviewx/v1/admin/get-settings` (plugin configuration) or `/wp-json/reviewx/v1/admin/get-users` (user database). To manipulate data, an attacker sends a POST request to `/wp-json/reviewx/v1/admin/update-settings` with a JSON payload containing modified settings. No nonce or valid session cookie is required to bypass the flawed authorization check.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.