CVE-2025-12448

Smartsupp – live chat, AI shopping assistant and chatbots <= 3.9.1 - Authenticated (Subscriber+) Stored Cross-Site Scripting

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

Description

The Smartsupp – live chat, AI shopping assistant and chatbots plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'code' parameter in all versions up to, and including, 3.9.1 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Subscriber-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

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<=3.9.1
PublishedFebruary 18, 2026
Last updatedFebruary 19, 2026
Affected pluginsmartsupp-live-chat

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan focuses on exploiting a Stored Cross-Site Scripting (XSS) vulnerability in the **Smartsupp – live chat, AI shopping assistant and chatbots** plugin (CVE-2025-12448). Since source files were not provided, this plan is based on the vulnerability description and common patterns found…

Show full research plan

This research plan focuses on exploiting a Stored Cross-Site Scripting (XSS) vulnerability in the Smartsupp – live chat, AI shopping assistant and chatbots plugin (CVE-2025-12448). Since source files were not provided, this plan is based on the vulnerability description and common patterns found in live-chat plugins.


1. Vulnerability Summary

The Smartsupp plugin fails to adequately sanitize and escape the code parameter when saving its settings. This parameter is intended to hold the Smartsupp chat integration script. Because the plugin allows users with Subscriber-level permissions (or higher) to update this value, and subsequently renders it unescaped on both the frontend and the admin dashboard, an attacker can inject arbitrary JavaScript.

2. Attack Vector Analysis

  • Vulnerable Endpoint: admin-ajax.php or wp-admin/options.php.
  • Vulnerable Parameter: code (or potentially smartsupp_code / chat_code - inferred).
  • Authentication: Authenticated (Subscriber+).
  • Preconditions: The plugin must be active. The attacker needs valid Subscriber credentials.
  • Sink: The injected code is likely stored in the wp_options table and rendered in the <head> or <footer> of all public-facing pages and/or the plugin's admin settings page.

3. Code Flow (Inferred)

  1. Entry Point: An AJAX action (e.g., wp_ajax_smartsupp_save_settings) or a settings save hook (e.g., admin_init) is registered.
  2. Lack of Authorization: The handler fails to check current_user_can('manage_options'), instead only checking for is_user_logged_in() or a lower capability like read.
  3. Insecure Storage: The handler receives the code parameter and calls update_option('smartsupp_chat_code', $_POST['code']) without using sanitize_text_field or wp_kses.
  4. Insecure Output: A frontend hook (e.g., wp_head or wp_footer) calls get_option('smartsupp_chat_code') and echoes it directly without esc_js() or esc_html().

4. Nonce Acquisition Strategy

To update settings, the plugin likely requires a WordPress nonce localized into the admin dashboard or the settings page.

  1. Identify Script Enqueue: The plugin likely enqueues its settings scripts on its own menu page.
  2. Create Setup: The agent will log in as a Subscriber and navigate to the Smartsupp settings page (usually /wp-admin/admin.php?page=smartsupp-settings).
  3. Extraction:
    • The agent will use browser_eval to look for localized data.
    • Inferred Variable Name: window.smartsuppData or window.smartsupp_settings.
    • Action: browser_eval("window.smartsuppData?.nonce") or browser_eval("document.querySelector('#_wpnonce')?.value").
  4. Bypass Check: If no nonce check exists in the AJAX handler (a common oversight), the agent will attempt the request without it first.

5. Exploitation Strategy

The exploit will attempt to overwrite the chat integration code with a malicious script.

  • Step 1: Authenticate as a Subscriber.
  • Step 2: Locate the AJAX action. (The agent will grep the plugin directory for wp_ajax_ to find the exact action string).
  • Step 3: Prepare the payload:
    </script><script>alert(document.domain);//
    
  • Step 4: Send the HTTP POST request via http_request:
    • URL: https://target.example.com/wp-admin/admin-ajax.php
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      action=smartsupp_save_settings&code=</script><script>alert(document.domain);//&_wpnonce=[EXTRACTED_NONCE]
      
      (Note: The exact action name and nonce key will be refined after the agent greps the source code.)

6. Test Data Setup

  1. Plugin Installation: Install and activate smartsupp-live-chat version 3.9.1.
  2. User Creation: Create a user with the subscriber role.
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  3. Public Page: Ensure at least one public post exists to verify frontend rendering.
    • wp post create --post_type=post --post_status=publish --post_title="Vulnerable Page"

7. Expected Results

  • Response: The AJAX handler should return a 200 OK or a JSON success message (e.g., {"success":true}).
  • Storage: The smartsupp_chat_code (or similar) option in the database will contain the raw <script> tag.
  • Execution: When any user (including the Admin) visits the homepage, a JavaScript alert box will appear.

8. Verification Steps

  1. Database Check: Use WP-CLI to verify the option is stored unsanitized:
    • wp option get smartsupp_chat_code (or the actual option name found during research).
  2. Frontend Check: Use http_request to fetch the homepage and verify the payload exists in the HTML:
    • http_request("GET", "https://target.example.com/")
    • Confirm the presence of alert(document.domain).

9. Alternative Approaches

  • Settings API: If the plugin uses the standard WordPress Settings API (options.php), the Subscriber might be able to POST directly to wp-admin/options.php if the option group was registered with __return_true for the capability check or no capability check at all.
  • REST API: Check for any registered REST routes using register_rest_route that might allow updating settings without proper permission_callback checks.
  • Blind Payload: If the XSS does not fire on the frontend, check the Admin dashboard (specifically the Smartsupp settings page) to see if the payload executes there (Admin-only XSS).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Smartsupp plugin for WordPress is vulnerable to Stored Cross-Site Scripting due to a lack of authorization checks and input sanitization in its settings update functionality. This allows authenticated attackers with Subscriber-level permissions to save malicious JavaScript in the 'code' parameter, which is then rendered unescaped on site pages.

Vulnerable Code

// File: smartsupp-live-chat/src/Smartsupp/Admin.php (inferred logic)
// The plugin registers an AJAX action to save settings without performing capability checks.
add_action('wp_ajax_smartsupp_save_settings', 'smartsupp_save_settings_handler');

function smartsupp_save_settings_handler() {
    // Vulnerability: No check for current_user_can('manage_options')
    // Vulnerability: No nonce verification
    
    if (isset($_POST['code'])) {
        // Vulnerability: Direct storage of unsanitized input
        update_option('smartsupp_chat_code', $_POST['code']);
    }
    
    wp_send_json_success();
}

---

// File: smartsupp-live-chat/src/Smartsupp/Frontend.php (inferred logic)
// The stored code is echoed directly onto the page.
add_action('wp_head', 'smartsupp_render_chat_code');

function smartsupp_render_chat_code() {
    $code = get_option('smartsupp_chat_code');
    if ($code) {
        echo $code; // Vulnerability: Unescaped output
    }
}

Security Fix

--- a/smartsupp-live-chat/src/Smartsupp/Admin.php
+++ b/smartsupp-live-chat/src/Smartsupp/Admin.php
@@ -10,6 +10,14 @@
 
 function smartsupp_save_settings_handler() {
+    if ( ! current_user_can( 'manage_options' ) ) {
+        wp_send_json_error( array( 'message' => 'Unauthorized' ), 403 );
+        return;
+    }
+
+    check_ajax_referer( 'smartsupp_save_settings', 'nonce' );
+
     if ( isset( $_POST['code'] ) ) {
-        update_option( 'smartsupp_chat_code', $_POST['code'] );
+        update_option( 'smartsupp_chat_code', wp_kses_post( $_POST['code'] ) );
     }
 
     wp_send_json_success();
 }

Exploit Outline

1. Authenticate to the WordPress site as a user with Subscriber-level privileges. 2. Identify the AJAX action used by the plugin to save settings (e.g., 'smartsupp_save_settings'). 3. Locate or extract a valid AJAX nonce if required (though the vulnerability description suggests an authorization bypass, meaning a nonce might be absent or not checked for Subscribers). 4. Send a POST request to /wp-admin/admin-ajax.php with the 'action' parameter set to the plugin's save handler and the 'code' parameter containing a malicious script payload (e.g., "</script><script>alert(document.domain)</script>"). 5. The plugin saves the payload into the site's options table without sanitization. 6. Visit any page on the site where the Smartsupp chat widget is rendered. The malicious script will execute in the context of the user's browser session.

Check if your site is affected.

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