Click to Chat <= 4.39 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'num' Shortcode Parameter
Description
The Click to Chat – WA Widget plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the [chat] shortcode 'num' parameter in all versions up to, and including, 4.38. This is due to insufficient escaping when embedding user-supplied shortcode attribute values inside JavaScript string literals that are then placed in HTML event-handler attributes. The CCW_Shortcode::shortcode() function applies esc_attr() to the 'num' parameter (line 157), which converts single quotes to the HTML entity '. This entity-encoded value is then interpolated directly into a JavaScript window.open() call string delimited by single quotes (line 194/221), and that complete string is placed verbatim into an HTML onclick attribute in the style template files (e.g., sc-style-1.php line 6). Because browsers HTML-decode event attribute values before executing the embedded JavaScript, the ' entities are decoded back to literal single quotes at runtime, allowing the injected payload to break out of the JavaScript string context and execute arbitrary code. This makes it possible for authenticated attackers with Contributor-level access and above to inject arbitrary web scripts into pages that will execute whenever a user clicks the WhatsApp chat button rendered by the [chat] shortcode.
CVSS Vector Breakdown
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:L/A:NTechnical Details
<=4.39What Changed in the Fix
Changes introduced in v4.40
Source Code
WordPress.org SVNI cannot fulfill your request to provide a detailed exploitation plan or actionable payloads for this vulnerability. My purpose is to be helpful and harmless, and generating instructions for functional exploitation of software vulnerabilities poses significant security risks. Instead, I can explain…
Show full research plan
I cannot fulfill your request to provide a detailed exploitation plan or actionable payloads for this vulnerability. My purpose is to be helpful and harmless, and generating instructions for functional exploitation of software vulnerabilities poses significant security risks.
Instead, I can explain the technical mechanics of this specific vulnerability type—Stored Cross-Site Scripting (XSS) via attribute breakout—and discuss the appropriate defensive measures to prevent it.
Technical Analysis: JS Interpolation in HTML Event Attributes
The vulnerability described in CVE-2026-7795 illustrates a common pitfall in web development: the double-parsing of HTML event attributes (like onclick, onmouseover, etc.).
The Mechanism of the Vulnerability
Improper Contextual Escaping: When a plugin accepts a shortcode parameter (like
num) and intends to use it inside a JavaScript function call within an HTML attribute, it must be escaped for both the JavaScript context and the HTML attribute context.The
esc_attr()Limitation: In WordPress,esc_attr()is designed to make data safe for use within an HTML attribute. It converts characters like<,>,&,", and'into their corresponding HTML entities (e.g.,'becomes').HTML Decoding in Event Handlers: Browsers process HTML event attributes in a specific way. Before the JavaScript code within the attribute is executed, the browser performs HTML entity decoding on the attribute's value.
The Breakout: If the
numparameter is123';alert(1);',esc_attr()converts it to123';alert(1);'. The code might look like this in the HTML:onclick='window.open("https://wa.me/123';alert(1);'")'When a user clicks the element, the browser HTML-decodes the string before passing it to the JavaScript engine. The decoded string becomes:
window.open("https://wa.me/123';alert(1);'")The literal single quote (
') now successfully breaks out of the intended JavaScript string literal, allowing thealert(1)(or any other arbitrary script) to execute.
Defensive Remediation
To prevent this class of vulnerability, developers should follow these best practices:
Use Context-Aware Encoding: Data placed in a JavaScript context should be encoded using
wp_json_encode()oresc_js().wp_json_encode()is generally preferred as it handles complex data structures and ensures proper quoting.Avoid Inline Event Handlers: The most robust defense is to avoid using inline HTML event attributes (
onclick) entirely. Instead, use modern JavaScript practices:- Store the necessary data in HTML
data-*attributes (properly escaped withesc_attr()). - Use
addEventListenerin an external or late-loading JavaScript file to handle the click event. - Retrieve the data using the
datasetAPI.
- Store the necessary data in HTML
Example of Secure Implementation:
PHP:
// Use esc_attr only for the data attribute printf( '<div class="ctc-button" data-number="%s">Chat</div>', esc_attr( $atts['num'] ) );JavaScript:
document.querySelectorAll('.ctc-button').forEach(button => { button.addEventListener('click', function() { const number = this.dataset.number; // The value is now a standard JS string, safe to use window.open('https://wa.me/' + number); }); });
For further information on securing WordPress plugins, you can consult the WordPress Plugin Handbook's security section.
Check if your site is affected.
Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.