CVE-2026-39535

Display Eventbrite Events <= 6.5.6 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
6.5.7
Patched in
57d
Time to patch

Description

The Display Eventbrite Events plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 6.5.6. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=6.5.6
PublishedFebruary 18, 2026
Last updatedApril 15, 2026

What Changed in the Fix

Changes introduced in v6.5.7

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

### 1. Vulnerability Summary The **Display Eventbrite Events** plugin for WordPress (versions <= 6.5.6) is vulnerable to **Missing Authorization** in its AJAX handlers. Specifically, several AJAX actions registered with the `wp_ajax_nopriv_` hook (intended for unauthenticated users) fail to perform …

Show full research plan

1. Vulnerability Summary

The Display Eventbrite Events plugin for WordPress (versions <= 6.5.6) is vulnerable to Missing Authorization in its AJAX handlers. Specifically, several AJAX actions registered with the wp_ajax_nopriv_ hook (intended for unauthenticated users) fail to perform any capability checks or nonce verification. This allows unauthenticated attackers to invoke functions that interact with the Eventbrite API using the site's configured credentials, potentially exposing sensitive account information (organizations, events, organizers) or performing unauthorized API requests.

The vulnerability resides in the WidgetForEventbriteAPI\Includes\Widgets\Elementor\Eventbrite_Widget_Elementor_Helpers class, where handlers like get_organizations_for_key and send_events_for_key explicitly ignore nonce verification and lack current_user_can() checks.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Actions: fetch_organizations_for_key, send_events_for_key, update_widget_content.
  • Payload Parameters:
    • action: The AJAX action name.
    • token: An index (e.g., 0) corresponding to a stored API key, or a raw API token.
    • organizationID: (For events) The Eventbrite organization ID.
  • Authentication: None required (wp_ajax_nopriv_ hooks are used).
  • Preconditions: The plugin must have at least one Eventbrite API key configured in its settings (stored in the widget-for-eventbrite-api-settings option).

3. Code Flow

  1. Entry Point: An unauthenticated request is sent to admin-ajax.php with action=fetch_organizations_for_key.
  2. Hook Registration: In includes/class-core.php (inside define_admin_hooks or define_component_hooks), the plugin registers:
    add_action( 'wp_ajax_nopriv_fetch_organizations_for_key', array($widget_helpers, 'get_organizations_for_key') );
    
  3. Vulnerable Handler: The request is routed to WidgetForEventbriteAPI\Includes\Widgets\Elementor\Eventbrite_Widget_Elementor_Helpers::get_organizations_for_key().
  4. Processing:
    • The handler retrieves the token from $_POST.
    • It explicitly skips nonce verification: // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up.
    • It calls $this->utilities->map_api_index_to_key( $token ). If token is 0, it retrieves the first API key stored in the plugin's settings.
    • It then calls get_organizations_list($token), which makes a remote request to the Eventbrite API using the server's key.
  5. Sink: The result (organization data) is returned directly to the unauthenticated user via wp_send_json().

4. Nonce Acquisition Strategy

According to the source code in includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php, the functions get_organizations_for_key and send_events_for_key do not require a nonce.

The developer explicitly included // phpcs:ignore WordPress.Security.NonceVerification.Missing in these methods, confirming that the security check is absent by design. Therefore, no nonce acquisition is necessary for exploitation.

5. Exploitation Strategy

We will demonstrate the unauthorized access by retrieving the organization list associated with the site's configured Eventbrite API key.

Step 1: Retrieve Organizations

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=fetch_organizations_for_key&token=0
  • Expected Response: A JSON array of organization objects.

Step 2: Retrieve Events (if Organization ID is found)

  • Tool: http_request
  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers: Content-Type: application/x-www-form-urlencoded
  • Body: action=send_events_for_key&token=0&organizationID=[ID_FROM_STEP_1]
  • Expected Response: A JSON object mapping Eventbrite event IDs to titles.

6. Test Data Setup

To simulate a vulnerable environment, we must configure a mock API key in the plugin settings via WP-CLI:

# Set a dummy API key in the plugin settings option
wp option update widget-for-eventbrite-api-settings '{"key":[{"key":"THIS_IS_A_MOCK_KEY","label":"API Key 1"}],"webhook":"","background_api":0}' --format=json

7. Expected Results

  • Success: The response from fetch_organizations_for_key will be a JSON response. If the key is valid, it returns Eventbrite data. If the key is dummy/invalid, the fact that the plugin attempts the API call and returns an Eventbrite error (e.g., 401 Unauthorized or ARGUMENTS_ERROR) instead of a WordPress 403 Forbidden confirms the missing authorization check.
  • Failure: The server returns a 403 Forbidden or 0 (default WordPress AJAX response for invalid actions).

8. Verification Steps

After performing the HTTP request, verify that the plugin indeed attempted to use the server-side credentials:

  1. Check the response body for strings like "organizations" or Eventbrite-specific error messages ("error": "INVALID_AUTH").
  2. Use WP-CLI to confirm the action was registered as nopriv:
    wp eval 'global $wp_filter; print_r($wp_filter["wp_ajax_nopriv_fetch_organizations_for_key"]);'
    

9. Alternative Approaches

If fetch_organizations_for_key is patched or restricted, try update_widget_content:

  • Action: update_widget_content
  • Payload: action=update_widget_content&[other_params]
  • Note: This action is used by the Elementor widget to refresh content. Triggering it unauthenticated can be used to perform unauthorized cache refreshes or potentially manipulate widget displays depending on the (truncated) implementation of update_elementor_widget_content.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Display Eventbrite Events plugin for WordPress is vulnerable to unauthorized access and information disclosure due to missing capability checks and nonce verification on several AJAX handlers. Unauthenticated attackers can exploit this to leak sensitive Eventbrite account data, such as organization IDs, organizer lists, and venue information, by leveraging the site's stored API credentials.

Vulnerable Code

// includes/class-core.php
        add_action( 'wp_ajax_update_widget_content', array($widget_helpers, 'update_elementor_widget_content') );
        add_action( 'wp_ajax_nopriv_update_widget_content', array($widget_helpers, 'update_elementor_widget_content') );
        add_action( 'wp_ajax_fetch_organizations_for_key', array($widget_helpers, 'get_organizations_for_key') );
        add_action( 'wp_ajax_nopriv_fetch_organizations_for_key', array($widget_helpers, 'get_organizations_for_key') );
        add_action( 'wp_ajax_fetch_events_for_key', array($widget_helpers, 'send_events_for_key') );
        add_action( 'wp_ajax_nopriv_fetch_events_for_key', array($widget_helpers, 'send_events_for_key') );

---

// includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php
    public function get_organizations_for_key() {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
        $token = ( !empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '' );
        $token = $this->utilities->map_api_index_to_key( $token );
        wp_send_json( $this->get_organizations_list( $token ) );
    }

    public function send_events_for_key() {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
        $token = ( !empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : $this->get_default_api_key() );
        $token = $this->utilities->map_api_index_to_key( $token );
        $args = array(
            'token' => $token,
        );
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
        if ( !empty( $_POST['organizationID'] ) ) {
            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
            $args['organization_id'] = sanitize_text_field( wp_unslash( $_POST['organizationID'] ) );
        }

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.6/includes/class-core.php /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.7/includes/class-core.php
--- /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.6/includes/class-core.php	2026-01-23 14:06:44.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.7/includes/class-core.php	2026-01-27 16:05:38.000000000 +0000
@@ -170,19 +170,12 @@
         add_action( 'wp_ajax_wfea_dismiss_notice', array($plugin_admin, 'wfea_dismiss_notice') );
         add_filter( 'site_status_tests', array($plugin_admin, 'site_status_tests') );
         add_action( 'wp_ajax_update_widget_content', array($widget_helpers, 'update_elementor_widget_content') );
-        add_action( 'wp_ajax_nopriv_update_widget_content', array($widget_helpers, 'update_elementor_widget_content') );
         add_action( 'wp_ajax_fetch_organizations_for_key', array($widget_helpers, 'get_organizations_for_key') );
-        add_action( 'wp_ajax_nopriv_fetch_organizations_for_key', array($widget_helpers, 'get_organizations_for_key') );
         add_action( 'wp_ajax_fetch_events_for_key', array($widget_helpers, 'send_events_for_key') );
-        add_action( 'wp_ajax_nopriv_fetch_events_for_key', array($widget_helpers, 'send_events_for_key') );
         add_action( 'wp_ajax_fetch_organizers_for_key', array($widget_helpers, 'send_organizers_for_key') );
-        add_action( 'wp_ajax_nopriv_fetch_organizers_for_key', array($widget_helpers, 'send_organizers_for_key') );
         add_action( 'wp_ajax_fetch_venues_options', array($widget_helpers, 'send_venues_options') );
-        add_action( 'wp_ajax_nopriv_fetch_venues_options', array($widget_helpers, 'send_venues_options') );
         add_action( 'wp_ajax_fetch_api_key_options', array($widget_helpers, 'send_api_key_options') );
-        add_action( 'wp_ajax_nopriv_fetch_api_key_options', array($widget_helpers, 'send_api_key_options') );
         add_action( 'wp_ajax_validate_date', array($widget_helpers, 'validate_date') );
-        add_action( 'wp_ajax_nopriv_validate_date', array($widget_helpers, 'validate_date') );
         add_action( 'init', function () {
             new \WidgetForEventbriteAPI\Includes\Widgets();
         } );
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.6/includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.7/includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php
--- /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.6/includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php	2025-04-15 22:40:04.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/widget-for-eventbrite-api/6.5.7/includes/widgets/elementor/class-eventbrite-widget-elementor-helpers.php	2026-01-27 16:05:38.000000000 +0000
@@ -191,34 +191,28 @@
     }
 
     public function get_organizations_for_key() {
-        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
+        check_ajax_referer( 'wfea-nonce', 'nonce' );
+        if ( !current_user_can( 'edit_posts' ) ) {
+            wp_die( -1 );
+        }
         $token = ( !empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : '' );
         $token = $this->utilities->map_api_index_to_key( $token );
         wp_send_json( $this->get_organizations_list( $token ) );
     }
 
     public function send_events_for_key() {
-        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
+        check_ajax_referer( 'wfea-nonce', 'nonce' );
+        if ( !current_user_can( 'edit_posts' ) ) {
+            wp_die( -1 );
+        }
         $token = ( !empty( $_POST['token'] ) ? sanitize_text_field( wp_unslash( $_POST['token'] ) ) : $this->get_default_api_key() );
         $token = $this->utilities->map_api_index_to_key( $token );
         $args = array(
             'token' => $token,
         );
-        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
         if ( !empty( $_POST['organizationID'] ) ) {
-            // phpcs:ignore WordPress.Security.NonceVerification.Missing -- just a look up
             $args['organization_id'] = sanitize_text_field( wp_unslash( $_POST['organizationID'] ) );
         }

Exploit Outline

To exploit this vulnerability, an unauthenticated attacker can send a POST request to the WordPress AJAX endpoint (/wp-admin/admin-ajax.php) with the 'action' parameter set to one of the vulnerable functions, such as 'fetch_organizations_for_key'. By providing a 'token' parameter (where '0' usually maps to the primary stored API key), the attacker can force the server to execute an API request to Eventbrite and return the JSON response containing sensitive organization and account data. No authentication or nonce is required as the plugin registers these actions using the 'wp_ajax_nopriv_' hook and explicitly skips nonce validation in the handler code.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.