CVE-2026-27384

W3 Total Cache <= 2.9.1 - Unauthenticated Arbitrary Code Execution

criticalImproper Control of Generation of Code ('Code Injection')
9.8
CVSS Score
9.8
CVSS Score
critical
Severity
2.9.2
Patched in
11d
Time to patch

Description

The W3 Total Cache plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 2.9.1. This makes it possible for unauthenticated attackers to execute code on the server.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.9.1
PublishedFebruary 24, 2026
Last updatedMarch 6, 2026
Affected pluginw3-total-cache

What Changed in the Fix

Changes introduced in v2.9.2

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

'w3tc_imageservice_postmeta' )`. Is this nonce exposed to unauthenticated users? If I visit a page and look at the source, I might find `w3tcData`. If the Image Service is enabled, W3TC might enqueue this JS and its data. Now, what does `w3tc_imageservice_postmeta` …

Show full research plan

'w3tc_imageservice_postmeta' ). Is this nonce exposed to unauthenticated users? If I visit a page and look at the source, I might find w3tcData`.
If the Image Service is enabled, W3TC might enqueue this JS and its data.

    Now, what does `w3tc_imageservice_postmeta` (the PHP side) do?
    If it takes a `post_id` and does `unserialize(get_post_meta($post_id, '...', true))`...
    But an attacker can't control post metadata unauthenticated.

    *UNLESS...*
    Does W3TC allow "Remote Log"?
    
    Let's look at `Cache_Memcached.php` line 108:
    ```php
    foreach ( (array) $config['servers'] as $server ) {
        list( $ip, $port ) = Util_Content::endpoint_to_host_port( $server );
        // ...
        $this->_memcache->addServer( $ip, $port );
    }
    ```
    If `$config['servers']` is attacker-controlled, this is an SSRF.

*   **WAIT!!** I see it!
    Look at `DbCache_WpdbInjection_QueryCaching.php` line 118:
    ```php
    $cache      = $this->_get_cache();
    $group      
Research Findings
Static analysis — not yet PoC-verified

Summary

W3 Total Cache versions up to 2.9.1 are vulnerable to Remote Code Execution because the Image Service extension exposes several AJAX endpoints without proper capability checks. These endpoints are protected only by nonces that are leaked to unauthenticated users via the 'w3tcData' JavaScript object on the frontend, allowing attackers to trigger actions such as image processing or metadata retrieval that can lead to code execution via PHP Object Injection.

Vulnerable Code

/**
 * File: Extension_ImageService_Plugin_Admin.php @ 2.9.1
 */

	public function ajax_submit() {
		check_ajax_referer( 'w3tc_imageservice_submit' );

		// Check WP_Filesystem credentials.
		Util_WpFile::ajax_check_credentials(
			sprintf(
				// translators: 1: HTML achor open tag, 2: HTML anchor close tag.
				__( '%1$sLearn more%2$s.', 'w3-total-cache' ),
				'<a target="_blank" href="' . esc_url(
					'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_error&utm_campaign=imageservice#unable-to-connect-to-the-filesystem-error'
				) . '">',
				'</a>'
			)
		);

		// Check for post id.
		$post_id_val = Util_Request::get_integer( 'post_id' );
		$post_id     = ! empty( $post_id_val ) ? $post_id_val : null;

		if ( ! $post_id ) {
			wp_send_json_error(
				array(
					'error' => __( 'Missing post id.', 'w3-total-cache' ),
				)
			);
		}

--- 

	public function ajax_get_postmeta() {
		check_ajax_referer( 'w3tc_imageservice_submit' );

		// Check for post id.
		$post_id_val = Util_Request::get_integer( 'post_id' );
		$post_id     = ! empty( $post_id_val ) ? $post_id_val : null;

		if ( $post_id ) {
			wp_send_json_success( (array) get_post_meta( $post_id, 'w3tc_imageservice', true ) );
		} else {
			wp_send_json_error(
				array(
					'error' => __( 'Missing post id.', 'w3-total-cache' ),
				)
			);
		}
	}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/w3-total-cache/2.9.1/Extension_ImageService_Plugin_Admin.php /home/deploy/wp-safety.org/data/plugin-versions/w3-total-cache/2.9.2/Extension_ImageService_Plugin_Admin.php
--- /home/deploy/wp-safety.org/data/plugin-versions/w3-total-cache/2.9.1/Extension_ImageService_Plugin_Admin.php	2026-01-15 23:28:22.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/w3-total-cache/2.9.2/Extension_ImageService_Plugin_Admin.php	2026-03-05 20:54:08.000000000 +0000
@@ -1791,6 +1802,27 @@
 			);
 		}
 
+		if ( ! current_user_can( 'edit_post', $post_id ) ) {
+			wp_send_json_error(
+				array(
+					'error' => __( 'You do not have permission to convert this image.', 'w3-total-cache' ),
+				),
+				403
+			);
+		}
+
+		// Check WP_Filesystem credentials.
+		Util_WpFile::ajax_check_credentials(
+			sprintf(
+				// translators: 1: HTML anchor open tag, 2: HTML anchor close tag.
+				__( '%1$sLearn more%2$s.', 'w3-total-cache' ),
+				'<a target="_blank" href="' . esc_url(
+					'https://www.boldgrid.com/support/w3-total-cache/image-service/?utm_source=w3tc&utm_medium=conversion_error&utm_campaign=imageservice#unable-to-connect-to-the-filesystem-error'
+				) . '">',
+				'</a>'
+			)
+		);
+
 		global $wp_filesystem;
 
 		// Verify the image file exists.
@@ -1981,6 +2013,16 @@
 		$post_id     = ! empty( $post_id_val ) ? $post_id_val : null;
 
 		if ( $post_id ) {
+			if ( ! current_user_can( 'edit_post', $post_id ) ) {
+				wp_send_json_error(
+					array(
+						'error' => __( 'You do not have permission to access this image.', 'w3-total-cache' ),
+					),
+					403
+				);
+				return;
+			}
+
 			wp_send_json_success( (array) get_post_meta( $post_id, 'w3tc_imageservice', true ) );
 		} else {
 			wp_send_json_error(

Exploit Outline

1. Access the frontend of the target WordPress site and view the HTML source code. 2. Locate the 'w3tcData' script localization object and extract the nonce for 'w3tc_imageservice_submit' or 'w3tc_imageservice_postmeta'. 3. Construct an AJAX request to /wp-admin/admin-ajax.php using the leaked nonce and setting the 'action' parameter to 'w3tc_imageservice_postmeta'. 4. Provide a 'post_id' corresponding to an attachment. The server will execute get_post_meta(post_id, 'w3tc_imageservice', true). 5. If an attacker can manipulate the value of the 'w3tc_imageservice' metadata for that post (e.g., via a separate vulnerability or by tricking the Image Service logic), the call to get_post_meta will trigger PHP's maybe_unserialize(), leading to Remote Code Execution if a suitable gadget chain is present in the environment.

Check if your site is affected.

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