CVE-2026-2511 JS Help Desk – AI-Powered Support & Ticketing System <= 3.0.4 - Unauthenticated SQL Injection via ‘multiformid’ Parameter

Overview
Published: 2026-03-26 CVE-ID: CVE-2026-2511 CVSS: 7.5 High Affected Plugin: JS Help Desk – AI-Powered Support & Ticketing System Affected Versions: <= 3.0.4 Vulnerability Type: Unauthenticate SQL Injection CWE: CWE-89 Improper Neutralization of Special Elements used in an SQL Command
Description
The JS Help Desk – AI-Powered Support & Ticketing System plugin for WordPress is vulnerable to SQL Injection via the multiformid parameter in the storeTickets() function in all versions up to, and including, 3.0.4. This is due to the user-supplied multiformid value being passed to esc_sql() without enclosing the result in quotes in the SQL query, rendering the escaping ineffective against payloads that do not contain quote characters. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.
Patch And Commit Analysis

Make a look at the plugin’s changelog, we can see that there was a security updating at 3.0.5 version, which use to patch SQL Injection vulnerability at 3.0.4 version. To make a detail analysis, I will make a compare between version 3.0.4(vulnerable) and 3.0.5(patch).
// Before PATCH (vulnerable)
$jsst_inquery = " AND multiformid = ".esc_sql($jsst_formid);
// After PATCH
$jsst_inquery = " AND multiformid = ".intval($jsst_formid);
Vulnerable Functions :
| Function | Vulnerable Parameters | Fix |
|---|---|---|
getFieldOrderingForList() |
$jsst_formid |
intval() |
getFieldsOrderingforForm() |
$jsst_formid |
intval() |
getFieldsForListing() |
$jsst_formid |
intval() |
getPublishedFieldsForTicketDetail() |
$jsst_formid |
intval() |
getFieldTitleByFieldfor() |
$jsst_formid |
intval() |

At getFieldOrderingForList(), the $jsst_formid parameter is retrieved
from jssupportticket::$jsst_data['formid'] without proper sanitization.
Before the patch, the value was passed directly through esc_sql() and
concatenated into the query without surrounding quotes:
$jsst_inquery = " AND multiformid = " . esc_sql($jsst_formid);
Since esc_sql() only escapes special characters inside string literals,
it provides no protection for numeric context (no quotes). An attacker
could inject arbitrary SQL after the parameter.
The patch replaces this with intval(), which casts the value to an
integer, making any SQL payload mathematically impossible to inject:
$jsst_inquery = " AND multiformid = " . intval($jsst_formid);
The same vulnerable pattern is present in four additional functions:
getFieldsOrderingforForm()— $jsst_formid sourced from parameter, same esc_sql() without quotes fix → intval()

getFieldsForListing()— $jsst_formid sourced from parameter argument, same fix applied

getPublishedFieldsForTicketDetail()— identical pattern, intval() applied

getFieldTitleByFieldfor()— two branches both fixed with intval()

In all cases, the root cause and fix are identical to getFieldOrderingForList().
Root Cause Analysis (From Sink to Source)
The vulnerability stems from flawed SQL input sanitization. WordPress’s esc_sql() function is intended to escape special characters in strings before they’re used in SQL queries. However, it assumes the escaped value will be enclosed in quotes within the query. In this case, the multiformid parameter is inserted without surrounding quotes, which opens the door for attackers to inject SQL syntax. By crafting payloads that exploit numeric or boolean logic instead of string literals, they can bypass the intended protections and execute malicious queries.
Source (Entry Point)
The attack begins at saveticket() in JSSTicketController(modules/ticket/controller.php:183). After the nonce check passes,
raw POST data is collected and passed directly into storeTickets()
without any type validation on the multiformid parameter.

Propagation
Inside storeTickets() in JSSTticketModel (modules/ticket/model.php:1193), the tainted multiformid value is passed as an argument to getUserfieldsfor() with no is_numeric() or intval() check applied:

$jsst_userfield = JSSTincluder::getJSModel('fieldordering')
->getUserfieldsfor(1, $jsst_data['multiformid']);
Sink (Execution Point)
The tainted value reaches getUserfieldsfor() in JSSTfieldorderingModel
(modules/fieldordering/model.php:995-998). Here it is passed through
esc_sql() and concatenated into the query without surrounding quotes:
$jsst_inquery = " AND multiformid = " . esc_sql($jsst_multiformid);
$jsst_query = "SELECT field,userfieldparams,userfieldtype,fieldtitle
FROM `js_ticket_fieldsordering`
WHERE fieldfor = " . esc_sql($jsst_fieldfor)
. $jsst_inquery . " ORDER BY field";
Since esc_sql() provides no protection in a numeric context, the payload
survives intact. As seen in the debugger, $jsst_multiformid contains
“1 AND SLEEP(5)”, causing the final query to become:
...WHERE fieldfor = 1 AND multiformid = 1 AND SLEEP(5) ORDER BY field

The malicious query is then executed at line 1000 via get_results($jsst_query),
confirming successful SQL injection.

POC Poof Of Concept
To confirm the SQL Injection vulnerability, a time-based blind injection technique was used by injecting a SLEEP() payload into the multiformid
parameter during ticket submission.
Test Case 1: multiformid = 1 AND SLEEP(1)
The server took approximately 24 seconds to respond — significantly longer than the baseline response time of a normal request.

The extended delay is due to a multiplier effect: the plugin iterates the multiformid value across multiple internal queries during ticket processing, causing SLEEP(1) to execute multiple times within a single request.
Test Case 2: multiformid = 1 AND SLEEP(2)
The server response time doubled to approximately 48 seconds, directly correlating with the increased sleep duration.

The linear correlation between the SLEEP() duration and the total response time confirms that the multiformid parameter is being concatenated directly into SQL queries without proper sanitization. This allows an unauthenticated attacker to execute arbitrary SQL commands against the database.