CVE-2025-13369

Premmerce WooCommerce Customers Manager <= 1.1.14 - Reflected Cross-Site Scripting

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

Description

The Premmerce WooCommerce Customers Manager plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via the 'money_spent_from', 'money_spent_to', 'registered_from', and 'registered_to' parameters in all versions up to, and including, 1.1.14 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick an administrator into performing an action such as clicking on a link.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.1.14
PublishedJanuary 6, 2026
Last updatedFebruary 25, 2026
Affected pluginwoo-customers-manager

What Changed in the Fix

Changes introduced in v1.1.15

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill this request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or specific HTTP requests designed to demonstrate the exploitation of real-world vulnerabilities. To learn about identifying and remediating Reflected Cross-Site Scripting (XSS)…

Show full research plan

I cannot fulfill this request. I am prohibited from generating detailed exploitation research plans, actionable payloads, or specific HTTP requests designed to demonstrate the exploitation of real-world vulnerabilities.

To learn about identifying and remediating Reflected Cross-Site Scripting (XSS) vulnerabilities in WordPress environments, I recommend exploring the following defensive and educational resources:

  1. WordPress Developer Documentation: Review the official guides on Data Sanitization and Escaping to understand how to properly handle user-controlled input before outputting it to the browser.
  2. OWASP XSS Prevention: The OWASP Cross-Site Scripting (XSS) Prevention Cheat Sheet provides comprehensive strategies for protecting web applications from XSS.
  3. Secure Coding Practices: When working with WordPress admin filters and table navigation, always ensure that values retrieved from $_GET or $_POST are both sanitized on input (e.g., using sanitize_text_field() or casting to specific types like (float)) and escaped on output using context-aware functions such as esc_attr() or esc_html().
  4. Vulnerability Research Databases: For technical details regarding patched vulnerabilities and security best practices, you can consult resources like Patchstack or the WPScan Vulnerability Database.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Premmerce WooCommerce Customers Manager plugin for WordPress is vulnerable to Reflected Cross-Site Scripting via multiple filter parameters in the admin user list. This occurs because the plugin directly accepts and reflects input from the 'money_spent_from', 'money_spent_to', 'registered_from', and 'registered_to' GET parameters into HTML input fields without sufficient sanitization or escaping.

Vulnerable Code

// src/Admin/Admin.php, around line 66
            $defaults = array(
                'money_spent_from' => '',
                'money_spent_to'   => '',
                'registered_from'  => null,
                'registered_to'    => null,
            );

            $defaults = array_replace($defaults, $_GET);

            $moneySpentFrom = $defaults['money_spent_from'];
            $moneySpentTo   = $defaults['money_spent_to'];

---

// src/Admin/Admin.php, around line 120
    public function renderFilters($position)
    {
        if ($position == 'top') {
            $defaults = array(
                'money_spent_from' => null,
                'money_spent_to'   => null,
                'registered_from'  => null,
                'registered_to'    => null,
            );

            $defaults = array_replace($defaults, $_GET);

            $filters = array(
                'registered_from'  => $defaults['registered_from'],
                'registered_to'    => $defaults['registered_to'],
                'money_spent_from' => $defaults['money_spent_from'],
                'money_spent_to'   => $defaults['money_spent_to'],
            );

            $this->fileManager->includeTemplate('admin/filter.php', $filters);

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/woo-customers-manager/1.1.14/src/Admin/Admin.php /home/deploy/wp-safety.org/data/plugin-versions/woo-customers-manager/1.1.15/src/Admin/Admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/woo-customers-manager/1.1.14/src/Admin/Admin.php	2023-07-21 07:44:26.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/woo-customers-manager/1.1.15/src/Admin/Admin.php	2026-02-19 17:51:54.000000000 +0000
@@ -55,19 +55,10 @@
             $metaQuery = array();
             $dateQuery = array();
 
-            $defaults = array(
-                'money_spent_from' => '',
-                'money_spent_to'   => '',
-                'registered_from'  => null,
-                'registered_to'    => null,
-            );
-
-            $defaults = array_replace($defaults, $_GET);
-
-            $moneySpentFrom = $defaults['money_spent_from'];
-            $moneySpentTo   = $defaults['money_spent_to'];
-            $registeredFrom = (bool)strtotime($defaults['registered_from']) ? $defaults['registered_from'] : null;
-            $registeredTo   = (bool)strtotime($defaults['registered_to']) ? $defaults['registered_to'] : null;
+            $moneySpentFrom = isset($_GET['money_spent_from']) ? sanitize_text_field($_GET['money_spent_from']) : '';
+            $moneySpentTo   = isset($_GET['money_spent_to']) ? sanitize_text_field($_GET['money_spent_to']) : '';
+            $registeredFrom = isset($_GET['registered_from']) && strtotime($_GET['registered_from']) ? sanitize_text_field($_GET['registered_from']) : null;
+            $registeredTo   = isset($_GET['registered_to']) && strtotime($_GET['registered_to']) ? sanitize_text_field($_GET['registered_to']) : null;
 
             $value   = null;
             $compare = null;
@@ -125,20 +116,11 @@
     public function renderFilters($position)
     {
         if ($position == 'top') {
-            $defaults = array(
-                'money_spent_from' => null,
-                'money_spent_to'   => null,
-                'registered_from'  => null,
-                'registered_to'    => null,
-            );
-
-            $defaults = array_replace($defaults, $_GET);
-
             $filters = array(
-                'registered_from'  => $defaults['registered_from'],
-                'registered_to'    => $defaults['registered_to'],
-                'money_spent_from' => $defaults['money_spent_from'],
-                'money_spent_to'   => $defaults['money_spent_to'],
+                'registered_from'  => isset($_GET['registered_from']) ? sanitize_text_field($_GET['registered_from']) : '',
+                'registered_to'    => isset($_GET['registered_to']) ? sanitize_text_field($_GET['registered_to']) : '',
+                'money_spent_from' => isset($_GET['money_spent_from']) ? sanitize_text_field($_GET['money_spent_from']) : '',
+                'money_spent_to'   => isset($_GET['money_spent_to']) ? sanitize_text_field($_GET['money_spent_to']) : '',
             );
 
             $this->fileManager->includeTemplate('admin/filter.php', $filters);

Exploit Outline

To exploit this vulnerability, an attacker must construct a URL targeting the WordPress admin user list page (`/wp-admin/users.php`). The attacker appends a malicious script to one of the affected parameters, such as `money_spent_from`. For example: `wp-admin/users.php?money_spent_from="><script>alert(1)</script>`. When an authenticated administrator clicks this link, the plugin retrieves the value from `$_GET` and includes it in the `admin/filter.php` template. Because the value is not sanitized or escaped, the attacker's script executes within the context of the administrator's browser session, potentially allowing for session hijacking or unauthorized administrative actions.

Check if your site is affected.

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