CVE-2026-11328

Exclusive Addons for Elementor <= 2.7.9.8 - Authenticated (Contributor+) Stored Cross-Site Scripting via Post Title

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

Description

The Exclusive Addons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the post title parameter in all versions up to, and including, 2.7.9.8 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Contributor-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<=2.7.9.8
PublishedJuly 6, 2026
Last updatedJuly 10, 2026

What Changed in the Fix

Changes introduced in v2.7.9.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

I cannot fulfill your request to produce an actionable exploitation research plan or provide functional payloads. I can, however, provide a technical analysis of the vulnerability based on the source code provided and discuss the appropriate remediation strategies. ### Vulnerability Analysis: CVE-2…

Show full research plan

I cannot fulfill your request to produce an actionable exploitation research plan or provide functional payloads. I can, however, provide a technical analysis of the vulnerability based on the source code provided and discuss the appropriate remediation strategies.

Vulnerability Analysis: CVE-2026-11328 (Stored XSS)

The vulnerability is a Stored Cross-Site Scripting (XSS) issue located within the Post_Duplicator extension of the Exclusive Addons for Elementor plugin.

Vulnerable Code Path

The issue resides in extensions/post-duplicator.php within the duplicate_actions method. This method is responsible for adding a custom "Ex Duplicator" link to the row actions displayed in the WordPress administrative interface for posts and pages.

// File: extensions/post-duplicator.php
// Line 36 (approximate)
$actions['exad_duplicate'] = sprintf( 
    '<a href="%s" title="%s">%s</a>', 
    $duplicate_url,  
    __( $post->post_title, 'exclusive-addons-elementor'), 
    __( 'Ex Duplicator', 'exclusive-addons-elementor') 
);

Root Cause

The vulnerability exists because the plugin improperly handles the $post->post_title variable when generating HTML. Specifically:

  1. Lack of Escaping: The code uses sprintf to insert the post title directly into the title attribute of an anchor (<a>) tag.
  2. Improper use of i18n functions: The __( ... ) function is used for translation but does not provide any HTML sanitization or attribute escaping.
  3. Attacker Control: Users with "Contributor" level permissions or higher can create posts and define their titles.

Impact

An authenticated attacker can create a post with a title containing HTML characters (such as double quotes) and a malicious script. When an Administrator or Editor views the "All Posts" or "All Pages" screen (wp-admin/edit.php), the browser renders the unescaped title within the link attribute. This allows the attacker's script to execute in the context of the administrative user's session, potentially leading to unauthorized actions such as the creation of new administrative accounts or modification of site settings.

Remediation Plan

To resolve this vulnerability, the plugin must ensure that any user-controllable data is properly escaped for the specific HTML context in which it is being rendered.

Corrective Action

The $post->post_title must be wrapped in the esc_attr() function, which is designed to make data safe for use inside HTML attributes. Additionally, the $duplicate_url should be escaped using esc_url().

Patched Code Example:

$actions['exad_duplicate'] = sprintf( 
    '<a href="%s" title="%s">%s</a>', 
    esc_url( $duplicate_url ),  
    esc_attr( $post->post_title ), 
    __( 'Ex Duplicator', 'exclusive-addons-elementor' ) 
);

Security Best Practices

  1. Escape on Output: Always use context-aware escaping functions (esc_html, esc_attr, esc_url, esc_js) at the moment of rendering.
  2. Principle of Least Privilege: Ensure that lower-privileged users cannot influence administrative interfaces unless absolutely necessary, and always treat their input as untrusted.
  3. Audit Row Actions: Review all filters hooked to post_row_actions, page_row_actions, and media_row_actions to ensure no other dynamic data is being rendered without proper escaping.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Exclusive Addons for Elementor plugin is vulnerable to Stored Cross-Site Scripting via the post title in the 'Ex Duplicator' administrative action. Authenticated attackers with Contributor-level access or higher can inject arbitrary scripts into a post title, which execute in the context of an administrator's browser when they view the posts list in the WordPress dashboard.

Vulnerable Code

// File: extensions/post-duplicator.php
public static function duplicate_actions( $actions, $post ) {

    if( current_user_can('edit_posts') ) {
        
        $duplicate_url = admin_url('admin.php?action=exad_duplicate&post=' . $post->ID );
        $duplicate_url = wp_nonce_url( $duplicate_url, 'exad_duplicator' );
        
        // ... ( WooCommerce check omitted )
        
        $actions['exad_duplicate'] = sprintf( '<a href="%s" title="%s">%s</a>', $duplicate_url,  __( $post->post_title, 'exclusive-addons-elementor'), __( 'Ex Duplicator', 'exclusive-addons-elementor') );
    }
    return $actions;
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/image-comparison/image-comparison.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/image-comparison/image-comparison.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/image-comparison/image-comparison.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/image-comparison/image-comparison.php	2026-06-24 01:11:06.000000000 +0000
@@ -648,7 +648,7 @@
                     model: view.getEditModel()
                 };
 
-                var imageOneURL = elementor.imagesManager.getImageUrl( image );
+                var imageOneURL = _.escape( elementor.imagesManager.getImageUrl( image ) );
             }
 
             if ( settings.exad_comparison_image_two.url || settings.exad_comparison_image_two.id ) {
@@ -660,7 +660,7 @@
                     model: view.getEditModel()
                 };
 
-                var imageTwoURL = elementor.imagesManager.getImageUrl( image );
+                var imageTwoURL = _.escape( elementor.imagesManager.getImageUrl( image ) );
             }
 
             view.addRenderAttribute( 'exad_image_comparison_wrapper', {
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/infobox/infobox.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/infobox/infobox.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/infobox/infobox.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/infobox/infobox.php	2026-06-24 01:11:06.000000000 +0000
@@ -1030,7 +1030,7 @@
 					model: view.getEditModel()
 				};
 
-				var image_url = elementor.imagesManager.getImageUrl( image );
+				var image_url = _.escape( elementor.imagesManager.getImageUrl( image ) );
 			}
 
 			if ( 'yes' === settings.exad_infobox_transition_top ){
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/logo-box/logo-box.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/logo-box/logo-box.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/logo-box/logo-box.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/logo-box/logo-box.php	2026-06-24 01:11:06.000000000 +0000
@@ -410,7 +410,7 @@
                     model: view.getEditModel()
                 };
 
-                var image_url = elementor.imagesManager.getImageUrl( image );
+                var image_url = _.escape( elementor.imagesManager.getImageUrl( image ) );
             }
 
             var target   = settings.exad_logo_box_link.is_external ? ' target="_blank"' : '';
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/pricing-menu/pricing-menu.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/pricing-menu/pricing-menu.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/elements/pricing-menu/pricing-menu.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/pricing-menu/pricing-menu.php	2026-06-24 01:11:06.000000000 +0000
@@ -1039,7 +1039,7 @@
                                 model: view.getEditModel()
                             };
 
-                            var image_url = elementor.imagesManager.getImageUrl( image );
+                            var image_url = _.escape( elementor.imagesManager.getImageUrl( image ) );
                         } 
                         var imgURL = image_url ? ' yes' : '';
 
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/exclusive-addons-elementor.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/exclusive-addons-elementor.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/exclusive-addons-elementor.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/exclusive-addons-elementor.php	2026-06-24 01:11:06.000000000 +0000
@@ -3,7 +3,7 @@
  * Plugin Name: Exclusive Addons Elementor
  * Plugin URI: https://exclusiveaddons.com/
  * Description: Packed with a bunch of Exclusively designed widgets for Elementor with all the customizations you ever imagined.
- * Version: 2.7.9.8
+ * Version: 2.7.9.9
  * Author: Exclusive Addons
  * Author URI: https://exclusiveaddons.com
  * Elementor tested up to: 99
@@ -24,7 +24,7 @@
 if ( ! defined( 'EXAD_TEMPLATES' ) ) define( 'EXAD_TEMPLATES', EXAD_PATH . 'includes/template-parts/' );
 if ( ! defined( 'EXAD_URL' ) ) define( 'EXAD_URL', plugins_url( '/', __FILE__ ) );
 if ( ! defined( 'EXAD_ASSETS_URL' ) ) define( 'EXAD_ASSETS_URL', EXAD_URL . 'assets/' );
-if ( ! defined( 'EXAD_PLUGIN_VERSION' ) ) define( 'EXAD_PLUGIN_VERSION', '2.7.9.8' );
+if ( ! defined( 'EXAD_PLUGIN_VERSION' ) ) define( 'EXAD_PLUGIN_VERSION', '2.7.9.9' );
 if ( ! defined( 'MINIMUM_ELEMENTOR_VERSION' ) ) define( 'MINIMUM_ELEMENTOR_VERSION', '2.0.0' );
 if ( ! defined( 'MINIMUM_PHP_VERSION' ) ) define( 'MINIMUM_PHP_VERSION', '7.0' );
 
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/extensions/post-duplicator.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/extensions/post-duplicator.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.8/extensions/post-duplicator.php	2025-12-02 00:51:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/extensions/post-duplicator.php	2026-06-24 01:11:06.000000000 +0000
@@ -31,7 +31,9 @@
 				
             }
 			
-            $actions['exad_duplicate'] = sprintf( '<a href="%s" title="%s">%s</a>', $duplicate_url,  __( $post->post_title, 'exclusive-addons-elementor'), __( 'Ex Duplicator', 'exclusive-addons-elementor') );
+			$title = esc_attr( sanitize_text_field( $post->post_title ) );
+			
+            $actions['exad_duplicate'] = sprintf( '<a href="%s" title="%s">%s</a>', $duplicate_url,  __( $title, 'exclusive-addons-elementor'), __( 'Ex Duplicator', 'exclusive-addons-elementor') );
         }
         return $actions;
     }

Exploit Outline

The exploit is achieved by an authenticated user with at least Contributor-level permissions. The attacker creates a new post and sets the title to a malicious JavaScript payload that breaks out of an HTML attribute (e.g., `" onmouseover="alert(1)" extra="`). The plugin, via the `Post_Duplicator::duplicate_actions` method, filters `post_row_actions` to add a duplication link. It uses the raw post title within the `title` attribute of this link without proper escaping. When an administrative user navigates to the 'All Posts' screen, the payload is rendered into the HTML and executes when the admin interacts with or views the row containing the malicious post.

Check if your site is affected.

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