CVE-2026-2712

WP-Optimize <= 4.5.0 - Missing Authorization to Authenticated (Subscriber+) Plugin Settings Update and Image Manipulation

mediumIncorrect Authorization
5.4
CVSS Score
5.4
CVSS Score
medium
Severity
4.5.1
Patched in
1d
Time to patch

Description

The WP-Optimize plugin for WordPress is vulnerable to unauthorized access of functionality due to missing capability checks in the `receive_heartbeat()` function in `includes/class-wp-optimize-heartbeat.php` in all versions up to, and including, 4.5.0. This is due to the Heartbeat handler directly invoking `Updraft_Smush_Manager_Commands` methods without verifying user capabilities, nonce tokens, or the allowed commands whitelist that the normal AJAX handler (`updraft_smush_ajax`) enforces. This makes it possible for authenticated attackers, with Subscriber-level access and above, to invoke admin-only Smush operations including reading log files (`get_smush_logs`), deleting all backup images (`clean_all_backup_images`), triggering bulk image processing (`process_bulk_smush`), and modifying Smush options (`update_smush_options`).

CVSS Vector Breakdown

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

Technical Details

Affected versions<=4.5.0
PublishedApril 9, 2026
Last updatedApril 10, 2026
Affected pluginwp-optimize

What Changed in the Fix

Changes introduced in v4.5.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2026-2712 ## 1. Vulnerability Summary The **WP-Optimize** plugin (up to version 4.5.0) contains an **Incorrect Authorization** vulnerability in its Heartbeat API integration. Specifically, the `receive_heartbeat()` function in `includes/class-wp-optimize-heartbeat.…

Show full research plan

Exploitation Research Plan: CVE-2026-2712

1. Vulnerability Summary

The WP-Optimize plugin (up to version 4.5.0) contains an Incorrect Authorization vulnerability in its Heartbeat API integration. Specifically, the receive_heartbeat() function in includes/class-wp-optimize-heartbeat.php fails to perform capability checks (current_user_can) or verify security nonces before executing commands intended for administrators.

The Heartbeat handler acts as a proxy, directly invoking methods in the Updraft_Smush_Manager_Commands class. While the standard AJAX handler (updraft_smush_ajax) properly restricts access, this Heartbeat-based entry point is accessible to any authenticated user, including those with Subscriber-level permissions. This allows an attacker to manipulate image optimization settings, delete backup images, and view logs.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: heartbeat
  • Method: POST
  • Authentication: Required (Subscriber+)
  • Vulnerable Hook: heartbeat_received (Filter)
  • Vulnerable File: includes/class-wp-optimize-heartbeat.php
  • Vulnerable Function: receive_heartbeat()
  • Impact: Unauthorized modification of plugin settings (update_smush_options), deletion of data (clean_all_backup_images), and information disclosure (get_smush_logs).

3. Code Flow

  1. Entry Point: A user logged into WordPress (even as a Subscriber) triggers a Heartbeat request. This is a standard POST request to admin-ajax.php with action=heartbeat.
  2. Hook Execution: WordPress triggers the heartbeat_received filter.
  3. Vulnerable Handler: WP_Optimize_Heartbeat::receive_heartbeat($response, $data) is invoked.
  4. Logic Path:
    • The function checks if $data['wp-optimize'] is present.
    • It iterates through the provided commands in the data.
    • It directly calls methods in Updraft_Smush_Manager_Commands based on the input.
    • Critical Failure: There is no check for manage_options capability or a specific WP-Optimize nonce inside this specific Heartbeat flow.
  5. Sink: The call reaches Updraft_Smush_Manager_Commands::update_smush_options(), which updates the updraft_smush_options row in the wp_options table.

4. Nonce Acquisition Strategy

The WordPress Heartbeat API requires a standard WordPress Heartbeat nonce. This nonce is available to all logged-in users.

  1. Access Site: Use a Subscriber-level user to log in.
  2. Retrieve Nonce: Navigate to any admin page (e.g., /wp-admin/profile.php). The Heartbeat nonce is localized by WordPress core.
  3. Browser Eval:
    // The Heartbeat nonce is typically stored in the heartbeatSettings object
    window.heartbeatSettings?.nonce
    
  4. Verification: Confirm the nonce is a 10-character hexadecimal string.

5. Exploitation Strategy

Goal: Unauthorized Modification of Plugin Settings

We will attempt to disable image backups using the update_smush_options command.

  1. Preparation: Log in as a Subscriber.
  2. Identify Target Command: update_smush_options.
  3. Construct Payload:
    The Heartbeat request expects a data parameter containing a JSON object or array.
    • action: heartbeat
    • screen_id: profile (or any valid admin screen)
    • _nonce: [Heartbeat Nonce]
    • data[wp-optimize][smush][command]: update_smush_options
    • data[wp-optimize][smush][data][options]: A JSON object representing the new settings (e.g., setting backup to false).

Request Construction (using http_request)

POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=heartbeat&screen_id=profile&_nonce=[NONCE]&data%5Bwp-optimize%5D%5Bsmush%5D%5Bcommand%5D=update_smush_options&data%5Bwp-optimize%5D%5Bsmush%5D%5Bdata%5D%5Boptions%5D%5Bbackup%5D=0

Note: The exact structure of the data array may require slight adjustment based on how the plugin parses the nested array in receive_heartbeat().

6. Test Data Setup

  1. Install WP-Optimize: Ensure version 4.5.0 is installed.
  2. Configure Smush: Ensure Smush is enabled in the admin settings.
  3. Verify Current State: Run wp option get updraft_smush_options and note that backup is likely 1 (true).
  4. Create Attacker: wp user create attacker attacker@example.com --role=subscriber --user_pass=password123.

7. Expected Results

  • Response: The HTTP response will be a JSON object containing Heartbeat data. If successful, it might include a confirmation from the Smush command class within the wp-optimize key.
  • Side Effect: The updraft_smush_options entry in the database will be modified.

8. Verification Steps

  1. Check Options via CLI:
    wp option get updraft_smush_options --format=json
    
    Verify that the backup field (or the target field used in the payload) has changed from its original value to 0.
  2. Check Logs (Optional):
    Attempt to use the same method with the get_smush_logs command to see if logs are returned in the Heartbeat response:
    data[wp-optimize][smush][command]=get_smush_logs
    

9. Alternative Approaches

If update_smush_options requires a more complex payload, try clean_all_backup_images. This command is often a simple string without additional data parameters.

Payload for Backup Deletion:

  • data[wp-optimize][smush][command]: clean_all_backup_images

Verification for Backup Deletion:

  1. Upload an image and smush it so a backup is created in wp-content/uploads/wpo-plugins-tables-list.json or the relevant backup directory.
  2. Run the exploit.
  3. Check if the backup files or the backup record is removed.
Research Findings
Static analysis — not yet PoC-verified

Summary

WP-Optimize versions up to 4.5.0 lack proper authorization and nonce checks within the Heartbeat API handler in `includes/class-wp-optimize-heartbeat.php`. This allows authenticated users with Subscriber-level permissions or higher to execute administrative Smush commands, enabling them to modify plugin settings, delete image backups, and view logs.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/wp-optimize/4.5.0/changelog.txt /home/deploy/wp-safety.org/data/plugin-versions/wp-optimize/4.5.1/changelog.txt
--- /home/deploy/wp-safety.org/data/plugin-versions/wp-optimize/4.5.0/changelog.txt	2026-02-11 11:20:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/wp-optimize/4.5.1/changelog.txt	2026-03-25 10:42:14.000000000 +0000
@@ -1,5 +1,25 @@
 == Changelog ==
 
+= 4.5.1 - 23/Mar/2026 =
+
+* FIX: Fixed compatibility issue with WP Remote 
+* FIX: Notice: Function _load_textdomain_just_in_time was called incorrectly 
+* FIX: Resolved weekly cron not running on WordPress < 5.4 by switching to the wpo_weekly schedule
+* FIX: Database table error when upgrading from free to premium version
+* REFACTOR: Improved WebP conversion flow by separating capability checks from configuration changes
+* REFACTOR: Improved auto-optimization handling by correcting static method usage
+* REFACTOR: Introduced `WP_Optimize_Server_Compatibility` class to centralize all server environment checks
+* REFACTOR: Removed separate `get_schedule_types()` method in premium version
+* SECURITY: Enforced capability checks and allowed-command validation for Smush actions triggered via Heartbeat API. Thanks to WordFence for the responsible disclosure
+* TWEAK: Display the `Enable the caching menu in the admin bar` option only when Cache or Minify is enabled
+* TWEAK: Improved detection of LearnDash plugin tables
+* TWEAK: Improved onboarding wizard RTL support and eliminated dependency on the PHP Reflection class
+* TWEAK: Improved robustness of `uploads/wpo` directory removal during plugin uninstallation
+* TWEAK: Minify - Don't remove the version query argument when the source is not processed by Minify
+* TWEAK: Premium - Unused Images - Enhanced detection of edited WordPress images
+* TWEAK: Prevent deprecation notices in PHP 8.5
+* TWEAK: Add a notice when `.htaccess` file is not available or renamed in Apache servers
+
 = 4.5.0 - 11/Feb/2026 =
 
 * FEATURE: Premium - Cache – Added ability to cache only selected URLs

Exploit Outline

An attacker with Subscriber-level access can exploit this by intercepting or generating a WordPress Heartbeat API request. By sending a POST request to `/wp-admin/admin-ajax.php` with the `action` parameter set to `heartbeat` and a valid Heartbeat nonce, the attacker can include a `data[wp-optimize]` payload. This payload targets the Smush command processor (e.g., setting `data[wp-optimize][smush][command]` to `update_smush_options`) to modify plugin configurations or `clean_all_backup_images` to delete data. Because the `receive_heartbeat()` function fails to verify user capabilities (e.g., `manage_options`) before invoking the Smush command class, the request is processed with administrative privileges.

Check if your site is affected.

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