CVE-2026-59511

Exclusive Addons for Elementor <= 2.7.9.9 - Unauthenticated Information Exposure

mediumExposure of Sensitive Information to an Unauthorized Actor
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.8.0
Patched in
4d
Time to patch

Description

The Exclusive Addons for Elementor plugin for WordPress is vulnerable to Sensitive Information Exposure in all versions up to, and including, 2.7.9.9. This makes it possible for unauthenticated attackers to extract sensitive user or configuration data.

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<=2.7.9.9
PublishedJuly 5, 2026
Last updatedJuly 8, 2026

What Changed in the Fix

Changes introduced in v2.8.0

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-59511 ## 1. Vulnerability Summary The **Exclusive Addons for Elementor** plugin (versions <= 2.7.9.9) is vulnerable to **Unauthenticated Information Exposure**. The vulnerability stems from the plugin's failure to filter sensitive configuration data when pass…

Show full research plan

Exploitation Research Plan - CVE-2026-59511

1. Vulnerability Summary

The Exclusive Addons for Elementor plugin (versions <= 2.7.9.9) is vulnerable to Unauthenticated Information Exposure. The vulnerability stems from the plugin's failure to filter sensitive configuration data when passing widget settings to the frontend for features like AJAX pagination and "Load More" functionality. Specifically, widgets like the Facebook Feed include sensitive API credentials (e.g., exad_facebook_access_token) in the settings object, which is then exposed to unauthenticated visitors via localized JavaScript variables or AJAX responses.

2. Attack Vector Analysis

  • Endpoint: admin-ajax.php (for AJAX-based exposure) or any public page containing the affected widget (for source-based exposure).
  • Vulnerable Action: exad_ajax_pagination and exad_facebook_feed_action.
  • Authentication: None (Unauthenticated).
  • Preconditions: A "Facebook Feed" widget must be configured on a published page with an Access Token.
  • Severity: Medium (CVSS 5.3) - Allows extraction of sensitive API tokens, which can be used to impersonate the site owner on third-party platforms (Facebook).

3. Code Flow

  1. Registration: In base.php, the plugin registers unauthenticated AJAX handlers:
    add_action( 'wp_ajax_nopriv_ajax_pagination', [ __CLASS__, 'exad_ajax_pagination' ] );
    add_action( 'wp_ajax_nopriv_exad_facebook_feed_action', [ $this, 'exad_facebook_feed_ajax' ] );
    
  2. Control Definition: In elements/facebook-feed/facebook-feed.php, the widget defines sensitive controls:
    $this->add_control(
        'exad_facebook_access_token',
        [
            'label' => esc_html__('Access Token', 'exclusive-addons-elementor' ),
            'type' => Controls_Manager::TEXT,
            'default' => 'EAAkn4TitXB...', // Default token provided
            // ...
        ]
    );
    
  3. Exposure (Frontend): When the widget renders, it enqueues scripts. The plugin's core logic (likely in the enqueue_scripts method of Base) uses wp_localize_script to pass the entire $settings array of the widget to the frontend to facilitate AJAX "Load More" actions.
  4. Exposure (AJAX): The exad_ajax_pagination function (in base.php) may return the settings object or require it to be sent back and forth. If the server retrieves and returns these settings without stripping exad_facebook_access_token, the information is exposed.

4. Nonce Acquisition Strategy

The AJAX actions require a nonce for verification. This nonce is exposed in the frontend HTML.

  1. Identify Trigger: The exad-facebook-feed widget or Post Grid widget triggers the script loading.
  2. Create Test Page:
    wp post create --post_type=page --post_title="Exploit Test" --post_status=publish --post_content='[exad-facebook-feed]'
    
  3. Navigate and Extract: Use browser_navigate to the new page.
  4. Extract via JS: Use browser_eval to find the localized data. Based on the plugin structure, the variable is likely exad_ajax_query_config (inferred) or part of the exclusive-addons-elementor localization.
    • Check: browser_eval("window.exad_ajax_query_config")
    • Check: browser_eval("window.exad_facebook_feed_settings") (inferred)
    • The nonce key is typically nonce or ajax_nonce.

5. Exploitation Strategy

The goal is to retrieve the exad_facebook_access_token from an unauthenticated context.

Method A: Direct Page Source Extraction (Most Likely)

  1. Step 1: Use http_request (GET) to fetch the URL of a page containing a Facebook Feed.
  2. Step 2: Search the response body for the configuration object.
    • Target string: "exad_facebook_access_token":"
  3. Expected Payload Location: Inside a <script> tag with the ID exclusive-addons-elementor-js-extra or similar.

Method B: AJAX Response Extraction

  1. Step 1: Obtain a valid nonce and the post_id from the target page.
  2. Step 2: Craft a POST request to admin-ajax.php.
    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=exad_ajax_pagination&id=[POST_ID]&nonce=[NONCE]&widget_id=[WIDGET_ID]
    
  3. Step 3: Analyze the JSON response for the presence of the settings block containing the access token.

6. Test Data Setup

  1. Install Plugin: Ensure exclusive-addons-for-elementor version 2.7.9.9 is active.
  2. Configure Widget:
    • Use wp post create to create a page.
    • Manually or via CLI, update the _elementor_data post meta to include a Facebook Feed widget with a unique, identifiable string as the exad_facebook_access_token.
    • Example identifying string: SENSITIVE_TOKEN_1234567890

7. Expected Results

  • A successful exploit will return the string SENSITIVE_TOKEN_1234567890 in an unauthenticated HTTP response.
  • This proves that an unauthorized actor can extract private API credentials configured by the site administrator.

8. Verification Steps

  1. Check Database:
    wp post meta get <POST_ID> _elementor_data
    
  2. Compare: Verify the string found in the HTTP response matches the token stored in the database.
  3. Validate Unauthenticated: Ensure the http_request was sent without any session cookies.

9. Alternative Approaches

If the Facebook token is not exposed, check other widgets that use external APIs, such as:

  • Instagram Feed
  • Mailchimp
  • Google Maps

The search pattern for any sensitive exposure in the JS localization is:

grep -r "wp_localize_script" . -A 5 | grep "settings"

This will identify where the plugin is passing widget settings to the frontend. Look for any call that passes an unfiltered $settings array.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Exclusive Addons for Elementor plugin exposes sensitive API credentials, such as Facebook Access Tokens, by including them in widget settings passed to the frontend for AJAX pagination features. Unauthenticated attackers can retrieve these tokens from the page source where they are embedded in data attributes or localized JavaScript, enabling them to impersonate the site owner on third-party platforms.

Vulnerable Code

// elements/facebook-feed/facebook-feed.php
		$query_settings = [
			'widget_id' 		=> $id,
			'page_id' 			=> $page_id,
			'access_token' 		=> $access_token,
			'clear_cache' 		=> $settings['clear_cache'],
			'exad_facebook_sort_by' => $settings['exad_facebook_sort_by'],
			'post_limit' 		=> $settings['post_limit'],

---

// base.php
    public function exad_facebook_feed_ajax() {

        $security = check_ajax_referer('exclusive_addons_nonce', 'security');

        if ( true == $security && isset( $_POST['query_settings'] ) ) :
            $settings = $_POST['query_settings'];
            $loaded_item = $_POST['loaded_item'];

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/base.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.8.0/base.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/base.php	2026-06-24 01:11:06.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.8.0/base.php	2026-06-30 23:43:24.000000000 +0000
@@ -10,6 +10,7 @@
 
 use Elementor\Plugin;
 use ExclusiveAddons\Elementor\Exad_WPML_Element_Free_Compatibility;
+use \Elementor\Utils;
 
 if ( ! defined( 'ABSPATH' ) ) {
 	exit;
@@ -340,6 +341,11 @@
 		return $element;
 	}
 	
+	protected function is_widget_id_valid( $widget_id ) {
+		return preg_match( '/^[a-zA-Z0-9]+$/', $widget_id )
+			&& strlen( $widget_id ) === 7;
+	}
+	
 
     /**
      * Facebook Feed ajax call
@@ -351,16 +357,56 @@
         $security = check_ajax_referer('exclusive_addons_nonce', 'security');
 
         if ( true == $security && isset( $_POST['query_settings'] ) ) :
-            $settings = $_POST['query_settings'];
-            $loaded_item = $_POST['loaded_item'];
-
+			$error_message = esc_html__( 'Something went wrong, please refresh the page.', 'exclusive-addons-elementor' );
+		
+			if ( ! is_array( $_POST[ 'query_settings' ] ) ) {
+				
+				return $error_message;
+			}
+			
+			$settings = wp_kses_post_deep( wp_unslash( $_POST[ 'query_settings' ] ) );
+            $loaded_item = wp_kses_post( wp_unslash( $_POST[ 'loaded_item' ] ) );
+			
+			$post_id = absint( $settings['post_id'] );
+			$widget_id = esc_attr( $settings['widget_id'] );
+			
+			if ( ! $post_id || ! $this->is_widget_id_valid( $widget_id ) ) {
+				
+				return $error_message;
+			}
+			
+			Plugin::$instance->db->switch_to_post( $post_id );
+			$document = Plugin::$instance->documents->get( $post_id );
+			
+			// Bail if not Elementor page.
+			if ( ! $document ) {
+				
+				return $error_message;
+			}
+			
+			// Setup $post_id as the WP global $post
+			$post = get_post( $post_id, OBJECT );
+			setup_postdata( $post );
+			
+			$elements_data = $document->get_elements_data();
+			$widget_data = Utils::find_element_recursive( $elements_data, $widget_id );
+			$widget_instance = Plugin::$instance->elements_manager->create_element_instance( $widget_data );
+			$widget_settings = $widget_instance->get_settings_for_display();
+			
+			if ( ! isset( $widget_settings['exad_facebook_access_token'] ) ) {
+				
+				return $error_message;
+			}
+			
+			$settings['access_token'] = $widget_settings['exad_facebook_access_token'];
+			
             $exad_facebook_feed_cache = '_' . $settings['widget_id'] . '_facebook_cache';
             $transient_key = $settings['exad_facebook_page_id'] . $exad_facebook_feed_cache;
             $facebook_feed_data = get_transient($transient_key);
 
             if ( false === $facebook_feed_data ) {
                 $url_queries = 'fields=status_type,created_time,from,message,story,full_picture,permalink_url,attachments.limit(1){type,media_type,title,description,unshimmed_url},comments.summary(total_count),reactions.summary(total_count)';
-                $url = "https://graph.facebook.com/{$settings['page_id']}/posts?{$url_queries}&access_token={$settings['access_token']}";
+                $url = "https://graph.facebook.com/{$settings['exad_facebook_page_id']}/posts?{$url_queries}&access_token={$settings['access_token']}";
                 $data = wp_remote_get( $url );
                 $facebook_feed_data = json_decode( wp_remote_retrieve_body( $data ), true );
                 set_transient( $transient_key, $facebook_feed_data, 0 );
@@ -368,6 +414,17 @@
             if ( $settings['clear_cache'] == 'yes' ) {
                 delete_transient( $transient_key );
             }
+			
+			if ( !empty( $facebook_feed_data ) && array_key_exists( 'error', $facebook_feed_data ) ) {
+				$messages['error'] = $facebook_feed_data['error']['message'];
+			}
+
+			if ( !empty( $messages ) ) {
+				foreach ($messages as $key => $message) {
+					printf('<div class="exad-facebook-error-message">%1$s</div>', esc_html( $message ) );
+				}
+				return;
+			}
 
             switch ($settings['exad_facebook_sort_by']) {
                 case 'old-posts':
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/facebook-feed/facebook-feed.php /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.8.0/elements/facebook-feed/facebook-feed.php
--- /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.7.9.9/elements/facebook-feed/facebook-feed.php	2026-06-24 01:11:06.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/exclusive-addons-for-elementor/2.8.0/elements/facebook-feed/facebook-feed.php	2026-06-30 23:43:24.000000000 +0000
@@ -1489,6 +1490,8 @@
 		if ( empty( $page_id ) || empty( $access_token ) ) {
 			return;
 		}
+		
+		$current_post_id = get_the_ID();
 
 		$this->add_render_attribute(
 			'exad_facebook_feed_wrapper',
@@ -1529,9 +1532,9 @@
 
 
 		$query_settings = [
+			'post_id'			=> $current_post_id,
 			'widget_id' 		=> $id,
-			'page_id' 			=> $page_id,
-			'access_token' 		=> $access_token,
+			'exad_facebook_page_id' => $page_id,
 			'clear_cache' 		=> $settings['clear_cache'],
 			'exad_facebook_sort_by' => $settings['exad_facebook_sort_by'],
 			'post_limit' 		=> $settings['post_limit'],

Exploit Outline

The exploit involves retrieving sensitive API credentials from the frontend of a WordPress site using the Exclusive Addons for Elementor plugin. 1. **Identify Target Page:** Locate a public page that utilizes the 'Facebook Feed' widget. 2. **Inspect Page Source:** Analyze the HTML source code of the identified page. The plugin embeds widget configuration data inside the `data-settings` attribute of the widget's wrapper element (e.g., `.exad-facebook-feed-wrapper`). 3. **Extract Credentials:** Locate the `exad_facebook_access_token` or `access_token` key within the JSON-encoded `data-settings` attribute value. This token can also often be found within localized JavaScript variables passed via `wp_localize_script` (e.g., in a script tag with the ID `exclusive-addons-elementor-js-extra`). 4. **Verification:** Use the extracted Access Token to make authenticated requests to the Facebook Graph API, confirming the exposure and severity. No authentication is required for the attacker to perform the extraction.

Check if your site is affected.

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