@@ -1095,10 +1095,57 @@ public static function save_settings_fields() {
10951095 }
10961096 }
10971097
1098+ /**
1099+ * Validate access to Stripe webhook AJAX handlers.
1100+ *
1101+ * @since 3.2.6
1102+ *
1103+ * @param bool $silent Whether to return errors instead of exiting.
1104+ * @return true|array
1105+ */
1106+ private static function authorize_stripe_webhook_request ( $ silent = false ) {
1107+ if ( ! current_user_can ( 'manage_options ' ) && ! current_user_can ( 'pmpro_paymentsettings ' ) ) {
1108+ $ r = array (
1109+ 'success ' => false ,
1110+ 'notice ' => 'error ' ,
1111+ 'message ' => esc_html__ ( 'You do not have permission to perform this action. ' , 'paid-memberships-pro ' ),
1112+ );
1113+
1114+ if ( $ silent ) {
1115+ return $ r ;
1116+ }
1117+
1118+ echo wp_json_encode ( $ r ); // Values escaped above.
1119+ exit ;
1120+ }
1121+
1122+ if ( wp_doing_ajax () && false === check_ajax_referer ( 'pmpro_stripe_webhook_nonce ' , 'nonce ' , false ) ) {
1123+ $ r = array (
1124+ 'success ' => false ,
1125+ 'notice ' => 'error ' ,
1126+ 'message ' => esc_html__ ( 'Your session has expired. Please refresh and try again. ' , 'paid-memberships-pro ' ),
1127+ );
1128+
1129+ if ( $ silent ) {
1130+ return $ r ;
1131+ }
1132+
1133+ echo wp_json_encode ( $ r ); // Values escaped above.
1134+ exit ;
1135+ }
1136+
1137+ return true ;
1138+ }
1139+
10981140 /**
10991141 * AJAX callback to create webhooks.
11001142 */
11011143 public static function wp_ajax_pmpro_stripe_create_webhook ( $ silent = false ) {
1144+ $ access_check = self ::authorize_stripe_webhook_request ( $ silent );
1145+ if ( true !== $ access_check ) {
1146+ return $ access_check ;
1147+ }
1148+
11021149 $ stripe = new PMProGateway_stripe ();
11031150 $ update_webhook_response = $ stripe ->update_webhook_events ();
11041151
@@ -1129,6 +1176,11 @@ public static function wp_ajax_pmpro_stripe_create_webhook( $silent = false ) {
11291176 * AJAX callback to disable webhooks.
11301177 */
11311178 public static function wp_ajax_pmpro_stripe_delete_webhook ( $ silent = false ) {
1179+ $ access_check = self ::authorize_stripe_webhook_request ( $ silent );
1180+ if ( true !== $ access_check ) {
1181+ return $ access_check ;
1182+ }
1183+
11321184 $ stripe = new PMProGateway_stripe ();
11331185 $ webhook = $ stripe ->does_webhook_exist ();
11341186
@@ -1162,6 +1214,9 @@ public static function wp_ajax_pmpro_stripe_delete_webhook( $silent = false ) {
11621214 * AJAX callback to rebuild webhook.
11631215 */
11641216 public static function wp_ajax_pmpro_stripe_rebuild_webhook () {
1217+ // This handler always sends its own response, so we do not need silent auth handling here.
1218+ self ::authorize_stripe_webhook_request ();
1219+
11651220 // First try to delete the webhook.
11661221 $ r = self ::wp_ajax_pmpro_stripe_delete_webhook ( true ) ;
11671222 if ( $ r ['success ' ] ) {
0 commit comments