CVE-2025-10734

ReviewX – WooCommerce Product Reviews with Multi-Criteria, Reminder Emails, Google Reviews, Schema & More <= 2.2.12 - Unauthenticated Sensitive Information Exposure

mediumInsecure Storage of Sensitive Information
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.3.0
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 Sensitive Information Exposure in all versions up to, and including, 2.2.12 via the syncedData function. This makes it possible for unauthenticated attackers to extract sensitive data including user names, emails, phone numbers, addresses.

CVSS Vector Breakdown

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

Technical Details

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

What Changed in the Fix

Changes introduced in v2.3.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This plan outlines the research and exploitation strategy for **CVE-2025-10734**, a sensitive information exposure vulnerability in the **ReviewX** plugin (<= 2.2.12). ### 1. Vulnerability Summary The vulnerability exists in the `syncedData` function, which is exposed via the plugin's REST API. Due…

Show full research plan

This plan outlines the research and exploitation strategy for CVE-2025-10734, a sensitive information exposure vulnerability in the ReviewX plugin (<= 2.2.12).

1. Vulnerability Summary

The vulnerability exists in the syncedData function, which is exposed via the plugin's REST API. Due to a lack of authentication and authorization checks, any user (unauthenticated) can call this endpoint. The function is designed to facilitate data synchronization between the WordPress site and the ReviewX SaaS platform (reviewx.io). It retrieves and returns detailed information about product reviews, including sensitive Personal Identifiable Information (PII) of the reviewers such as full names, email addresses, and potentially phone numbers or addresses linked to WooCommerce orders.

2. Attack Vector Analysis

  • Endpoint: Inferred to be a REST API route under the reviewx/v1 namespace (likely /wp-json/reviewx/v1/synced-data or /wp-json/reviewx/v1/sync).
  • HTTP Method: GET (most likely for data extraction).
  • Authentication: None required (PR:N).
  • Preconditions: The plugin must be active. For the data to be "sensitive," there must be existing reviews in the system.

3. Code Flow (Inferred)

  1. Registration: The plugin registers a REST route during the rest_api_init hook.
  2. Route Mapping: The route (e.g., synced-data) is mapped to a callback method named syncedData within a REST controller class.
  3. Missing Permission Check: The register_rest_route call likely lacks a permission_callback or uses __return_true, allowing unauthenticated access.
  4. Data Retrieval: The syncedData function queries the wp_comments and wp_commentmeta tables (and possibly wp_posts for WooCommerce order data).
  5. Sink: The function returns a WP_REST_Response containing a JSON array of reviewer details:
    • comment_author (User Name)
    • comment_author_email (Email)
    • WooCommerce billing data (Phone/Address) if the review is verified/linked to an order.

4. Nonce Acquisition Strategy

Based on the "Unauthenticated" nature of this vulnerability and the likely purpose of the endpoint (SaaS synchronization), it is highly probable that no WordPress nonce is required.

However, if a nonce is required for the REST API (wp_rest), it can be obtained as follows:

  1. Identify Shortcode: ReviewX commonly uses the [reviewx_pagination] or [reviewx_reviews] shortcodes.
  2. Setup Page: Create a public page containing one of these shortcodes.
  3. Extract Nonce:
    • Navigate to the page using browser_navigate.
    • Execute browser_eval("window.rvx_params?.nonce") or browser_eval("window.rvx_params?.rest_nonce").
    • The localization key is often rvx_params or reviewx_data.

5. Exploitation Strategy

Step 1: Identify the Endpoint

Query the WordPress REST API index to find the exact ReviewX route mapping.

  • Action: http_request
  • Method: GET
  • URL: /wp-json/reviewx/v1
  • Goal: Look for routes containing "sync" or "data" and identify the callback associated with syncedData.

Step 2: Populate Target Data

To confirm exposure, the environment must contain reviews with PII.

  • Action: Use WP-CLI to create a WooCommerce product and multiple reviews.
    wp eval "
    \$product_id = wc_create_product(['name' => 'Vulnerable Product']);
    wp_insert_comment([
        'comment_post_ID' => \$product_id,
        'comment_author' => 'John Doe',
        'comment_author_email' => 'john.doe@example.com',
        'comment_content' => 'Great product!',
        'comment_type' => 'review',
        'comment_approved' => 1
    ]);
    "
    

Step 3: Execute Data Extraction

Perform the unauthenticated request to the identified endpoint.

  • Action: http_request
  • Method: GET
  • URL: /wp-json/reviewx/v1/synced-data (or the route found in Step 1).
  • Headers: Accept: application/json

Step 4: Verify PII in Response

Check the JSON response for the email john.doe@example.com and the name John Doe.

6. Test Data Setup

  1. Plugin Status: Ensure reviewx version 2.2.12 is installed and active.
  2. WooCommerce: WooCommerce must be active as ReviewX depends on it.
  3. Reviews:
    • Create a "Guest" review (author name/email).
    • Create a "Customer" review (linked to a WP User).
    • (Optional) Use WP-CLI to add meta keys like _billing_phone to the user to see if the syncedData function pulls extended profile data.

7. Expected Results

  • Vulnerable Response: A 200 OK status with a JSON body containing an array of review objects. Each object includes cleartext comment_author_email and comment_author.
  • Example Payload Snippet:
    [
      {
        "wp_id": 123,
        "reviewer_name": "John Doe",
        "reviewer_email": "john.doe@example.com",
        "feedback": "Great product!",
        "rating": 5
      }
    ]
    

8. Verification Steps

  1. Check Output: Verify that the email and name in the HTTP response match the data created in the "Test Data Setup" step.
  2. Verify Unauthenticated Status: Perform the request without any cookies or Authorization headers to confirm the "Unauthenticated" claim.
  3. Confirm Version: Use wp plugin get reviewx --field=version to ensure the test was performed on <= 2.2.12.

9. Alternative Approaches

If /synced-data is not the route:

  1. Route Discovery: Iterate through all routes returned by /wp-json/reviewx/v1.
  2. Parameter Fuzzing: Some sync functions require a last_sync_id or timestamp. Try ?since=0 or ?page=1 if the initial request returns an empty array.
  3. Check Admin-Ajax: ReviewX also registers many wp_ajax_nopriv_ actions. Search the codebase for add_action('wp_ajax_nopriv_ to see if syncedData is also exposed via AJAX.
    • Target: /wp-admin/admin-ajax.php?action=rvx_get_synced_data (inferred).
Research Findings
Static analysis — not yet PoC-verified

Summary

The ReviewX plugin for WordPress (<= 2.2.12) is vulnerable to unauthenticated sensitive information exposure through its data synchronization REST API endpoint. The `syncedData` function lacks proper authentication and authorization checks, allowing any user to retrieve reviewer PII, including names, email addresses, and WooCommerce billing details.

Security Fix

diff -ru /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.3.0/app/Api/BaseApi.php
--- /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/BaseApi.php	2025-10-15 13:32:48.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.3.0/app/Api/BaseApi.php	2025-12-22 12:17:34.000000000 +0000
@@ -35,6 +35,6 @@
      */
     public function getDefaultHeaders() : array
     {
-        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'];
+        return ['Accept' => 'application/json', 'Authorization' => 'Bearer ' . Helper::getAuthToken(), '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.12/app/Api/WpApi.php /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.3.0/app/Api/WpApi.php
--- /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.2.12/app/Api/WpApi.php	2025-10-15 13:32:48.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/reviewx/2.3.0/app/Api/WpApi.php	2025-12-22 12:17:34.000000000 +0000
@@ -72,7 +72,6 @@
         $headers = ['Content-Type' => 'application/json'];
         if ($this->token) {
             $headers['Authorization'] = 'Bearer ' . $this->token;
-            $headers['X-Auth-Token'] = 'Bearer ' . $this->token;
         }
         return $headers;
     }
... (truncated)

Exploit Outline

1. Query the WordPress REST API index to identify the ReviewX route mapping, typically located under the '/wp-json/reviewx/v1' namespace. 2. Locate the endpoint associated with the 'syncedData' function (e.g., '/wp-json/reviewx/v1/synced-data' or '/wp-json/reviewx/v1/sync'). 3. Execute an unauthenticated GET request to the identified endpoint. No WordPress nonces or authorization headers are required. 4. Analyze the JSON response, which returns an array of review data objects containing sensitive fields like 'comment_author' (name), 'comment_author_email', and linked WooCommerce billing information (phone and address) for verified customers.

Check if your site is affected.

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