CVE-2026-2373

Royal Addons for Elementor – Addons and Templates Kit for Elementor <= 1.7.1049 - Missing Authorization to Unauthenticated Custom Post Type Contents Exposure

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
1.7.1050
Patched in
1d
Time to patch

Description

The Royal Addons for Elementor – Addons and Templates Kit for Elementor plugin for WordPress is vulnerable to Information Exposure in all versions up to, and including, 1.7.1049 via the get_main_query_args() function due to insufficient restrictions on which posts can be included. This makes it possible for unauthenticated attackers to extract contents of non-public custom post types, such as Contact Form 7 submissions or WooCommerce coupons.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
Low
Confidentiality
None
Integrity
None
Availability

Technical Details

Affected versions<=1.7.1049
PublishedMarch 16, 2026
Last updatedMarch 17, 2026
Affected pluginroyal-elementor-addons

What Changed in the Fix

Changes introduced in v1.7.1050

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This analysis targets **CVE-2026-2373**, a missing authorization vulnerability in **Royal Addons for Elementor**. The vulnerability exists in the `get_main_query_args()` function (likely located in `WprAddons\Classes\Utilities`), which processes user-supplied query parameters for grid-based widgets …

Show full research plan

This analysis targets CVE-2026-2373, a missing authorization vulnerability in Royal Addons for Elementor. The vulnerability exists in the get_main_query_args() function (likely located in WprAddons\Classes\Utilities), which processes user-supplied query parameters for grid-based widgets without sufficient validation. This allows unauthenticated attackers to query and extract content from non-public Custom Post Types (CPTs) such as WooCommerce coupons or Contact Form 7 configurations.

1. Vulnerability Summary

  • ID: CVE-2026-2373
  • Vulnerability: Missing Authorization / Information Exposure
  • Affected Function: get_main_query_args()
  • Sink: new \WP_Query( $query_args )
  • Root Cause: The function accepts an array of settings (often from $_POST['wpr_grid_query_args']) and uses the post_type and post_status values directly in a WordPress query. There is no whitelist or authorization check to ensure the unauthenticated requester is allowed to view the requested post type.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wpr_get_grid_layout (Unauthenticated via wp_ajax_nopriv_wpr_get_grid_layout)
  • Payload Parameter: wpr_grid_query_args (JSON encoded or array)
  • Authentication: None required (Unauthenticated).
  • Preconditions: The Royal Addons for Elementor plugin must be active. A valid nonce is typically required for the AJAX action.

3. Code Flow

  1. Entry Point: An unauthenticated user sends a POST request to admin-ajax.php with action=wpr_get_grid_layout.
  2. AJAX Handler: The plugin's AJAX handler (likely in a class handling Grids/Magazine Grids) retrieves $_POST['wpr_grid_query_args'].
  3. Vulnerable Call: The handler calls WprAddons\Classes\Utilities::get_main_query_args( $settings ), passing the user-controlled settings.
  4. Argument Construction: get_main_query_args() constructs the WP_Query arguments using the post_type provided in the $settings array.
  5. Execution: The handler executes $query = new \WP_Query( $args ).
  6. Information Exposure: The resulting posts (even if private or sensitive CPTs) are rendered and returned in the AJAX response.

4. Nonce Acquisition Strategy

Royal Addons for Elementor typically localizes a configuration object named WprConfig which contains a nonce for AJAX requests.

  1. Requirement: The nonce is usually enqueued on pages where a Royal Addons widget is present.
  2. Target Variable: window.WprConfig?.nonce
  3. Procedure:
    • Since the plugin is "Elementor-first," creating a standard page with a Royal Addons widget is the most reliable way to trigger the script.
    • Use WP-CLI to create a page: wp post create --post_type=page --post_status=publish --post_title="Exploit Page" --post_content='<!-- wp:elementor/template -->' (Or use an existing page if the plugin enqueues globally).
    • Navigate to the homepage or the created page using browser_navigate.
    • Extract the nonce: browser_eval("window.WprConfig?.nonce").
    • Note: If WprConfig is not found, check for wprConfig or WprAddonsData.

5. Exploitation Strategy

The goal is to extract WooCommerce coupons (CPT: shop_coupon), which contains sensitive discount codes and logic.

  • Request URL: http://<target>/wp-admin/admin-ajax.php
  • Method: POST
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body Parameters:
    • action: wpr_get_grid_layout
    • nonce: [EXTRACTED_NONCE]
    • wpr_grid_query_args: A JSON-encoded string:
      {
        "post_type": "shop_coupon",
        "posts_per_page": 10,
        "post_status": "publish",
        "wpr_grid_template_id": 0
      }
      
    • wpr_grid_template_id: 0 (or a valid template ID if required by the logic).

6. Test Data Setup

To verify information exposure, sensitive data must exist in the database:

  1. Create WooCommerce Coupons (Requires WooCommerce):
    • wp eval "wc_create_coupon(['code' => 'SECRET100', 'amount' => '100', 'discount_type' => 'fixed_cart']);"
  2. Create Private Content:
    • wp post create --post_type=post --post_title="Private Intel" --post_content="The password is admin" --post_status=private
  3. Ensure Royal Addons Settings: No specific settings are required, as the vulnerability is in the query builder utility.

7. Expected Results

  • Successful Exploit: The HTTP response (JSON or HTML) will contain the titles or content of the requested CPT. For shop_coupon, the response will likely show the coupon codes (e.g., "SECRET100") rendered within the grid item template.
  • Response Content: Look for string patterns like wpr-grid-item-title containing the coupon codes or private post titles.

8. Verification Steps

  1. Analyze HTTP Response: Check the body of the http_request response for the sensitive string created in step 6 (e.g., "SECRET100").
  2. Compare with Public View: Confirm the data is not visible on the standard frontend blog feed.
  3. Database Check: Verify the post exists in the DB with the restricted status:
    • wp db query "SELECT post_title, post_type, post_status FROM wp_posts WHERE post_type='shop_coupon'"

9. Alternative Approaches

  • Post Type: wpcf7_contact_form: If Contact Form 7 is installed, use this post_type to extract form definitions which may contain email addresses or logic.
  • Post Type: wp_block: Extract reusable blocks that might contain internal information.
  • Magazine Grid: If wpr_get_grid_layout fails, try the Magazine Grid specific action: action=wpr_get_magazine_grid_layout with the same wpr_grid_query_args parameter.
  • Bypass Nonce: Attempt the request without a nonce; if the plugin fails to call check_ajax_referer or wp_verify_nonce for the nopriv action, the exploit becomes even simpler.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Royal Addons for Elementor plugin for WordPress (<= 1.7.1049) is vulnerable to unauthenticated information exposure via the wpr_get_grid_layout AJAX action. This occurs because the get_main_query_args() function fails to validate or restrict the post_type and post_status parameters, allowing attackers to query and retrieve data from non-public custom post types like WooCommerce coupons or Contact Form 7 submissions.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1049/admin/notices/rating-notice.php /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1050/admin/notices/rating-notice.php
--- /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1049/admin/notices/rating-notice.php	2026-02-12 11:19:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1050/admin/notices/rating-notice.php	2026-03-05 12:58:30.000000000 +0000
@@ -34,9 +34,9 @@
         $install_date = get_option('royal_elementor_addons_activation_time');
 
         if ( false == get_option('wpr_maybe_later_time') && false !== $install_date && $this->past_date >= $install_date ) {
-            add_action( 'admin_notices', [$this, 'render_rating_notice' ]);
+            add_action( 'admin_notices', [$this, 'render_rating_notice']);
         } else if ( false != get_option('wpr_maybe_later_time') && $this->past_date >= get_option('wpr_maybe_later_time') ) {
-            add_action( 'admin_notices', [$this, 'render_rating_notice' ]);
+            add_action( 'admin_notices', [$this, 'render_rating_notice']);
         }
     }
 
--- /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1049/admin/plugin-options.php	2026-02-12 11:19:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/royal-elementor-addons/1.7.1050/admin/plugin-options.php	2026-03-05 12:58:30.000000000 +0000
@@ -80,6 +80,8 @@
     register_setting( 'wpr-settings', 'wpr_recaptcha_v3_site_key' );
     register_setting( 'wpr-settings', 'wpr_recaptcha_v3_secret_key' );
     register_setting( 'wpr-settings', 'wpr_recaptcha_v3_score' );
+    register_setting( 'wpr-settings', 'wpr_recaptcha_v2_site_key' );
+    register_setting( 'wpr-settings', 'wpr_recaptcha_v2_secret_key' );
 
     // Lightbox
     register_setting( 'wpr-settings', 'wpr_lb_bg_color' );
@@ -128,6 +130,17 @@
         register_setting( 'wpr-elements-settings', 'wpr-element-'. $slug, [ 'default' => 'on' ] );
     }
 
+    // Pro widgets that appear in Elements tab (so their toggles are saved)
+    if ( defined( 'WPR_ADDONS_PRO_VERSION' ) && wpr_fs()->can_use_premium_code() ) {
+        $pro_element_slugs = [ 'breadcrumbs-pro' ];
+        if ( wpr_fs()->is_plan( 'expert' ) ) {
+            $pro_element_slugs = array_merge( $pro_element_slugs, [ 'category-grid-pro', 'advanced-filters-pro' ] );
+        }
+        foreach ( $pro_element_slugs as $slug ) {
+            register_setting( 'wpr-elements-settings', 'wpr-element-' . $slug, [ 'default' => 'on' ] );
+        }
+    }
+
     // Theme Builder
     foreach ( Utilities::get_theme_builder_modules() as $title => $data ) {
         $slug = $data[0];
... (truncated)

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker first obtains a valid AJAX nonce by visiting the site's frontend and extracting it from the WprConfig.nonce JavaScript object. The attacker then sends a POST request to /wp-admin/admin-ajax.php with the action parameter set to wpr_get_grid_layout. The payload must include a wpr_grid_query_args parameter containing a JSON-encoded object that specifies a non-public post_type (such as shop_coupon for WooCommerce or wpcf7_contact_form for Contact Form 7) and a post_status like publish or private. Because the server-side utility function get_main_query_args() fails to whitelist allowed post types, it will construct and execute a WP_Query based on the attacker's input and return the contents of those restricted posts in the response.

Check if your site is affected.

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