Skip to main content
CVE Vulnerability Database
Vulnerability Database/CVE-2026-52841

CVE-2026-52841: Easy!Appointments Auth Bypass Vulnerability

CVE-2026-52841 is an authentication bypass flaw in Easy!Appointments that allows authenticated users to hijack Google OAuth tokens and access peer providers' calendar data with customer details. This article covers the exploit mechanism, affected versions, and patches.

Published:

CVE-2026-52841 Overview

CVE-2026-52841 is an Insecure Direct Object Reference [CWE-639] vulnerability in Easy!Appointments, a self-hosted appointment scheduling application. The flaw affects all versions prior to 1.6.0. The Google::oauth handler in application/controllers/Google.php accepts a URL-supplied provider_id, stores it in the session, and the oauth_callback writes the issued Google OAuth token to that provider row without verifying ownership. Any authenticated backend user, including a provider or secretary, can rebind another provider's Google Calendar sync to a Google account they control. Peer appointments then synchronize into the attacker's calendar, exposing customer names and email addresses as attendee data.

Critical Impact

An authenticated backend user can hijack a peer provider's Google Calendar sync and exfiltrate customer names and email addresses through attendee metadata on synchronized appointments.

Affected Products

  • Easy!Appointments versions prior to 1.6.0
  • application/controllers/Google.php OAuth flow
  • Backend accounts of any role (admin, provider, secretary)

Discovery Timeline

  • 2026-07-14 - CVE-2026-52841 published to NVD
  • 2026-07-14 - Last updated in NVD database

Technical Details for CVE-2026-52841

Vulnerability Analysis

Easy!Appointments implements Google Calendar sync through a two-step OAuth flow. The Google::oauth action at application/controllers/Google.php:278 reads a provider_id value from the request URL and stores it in the server-side session as oauth_provider_id. After the user completes Google consent, the oauth_callback action retrieves that session value and writes the resulting OAuth token, sync flag, and calendar identifier to the corresponding provider record.

The callback does not verify that the authenticated user owns the target provider_id. Because the value originated from a URL parameter under the attacker's control, any backend user can seed the session with another provider's identifier before completing OAuth against a Google account they control. The saved token replaces the victim's legitimate sync configuration.

Once rebound, the victim's future appointments propagate into the attacker's calendar. Attendee metadata attached to each event includes customer names and email addresses, producing an ongoing information disclosure channel.

Root Cause

The root cause is a missing authorization check between the authenticated session identity and the provider_id written by the OAuth callback. The application trusted URL-supplied input to select the target row, matching the Insecure Direct Object Reference pattern described in [CWE-639].

Attack Vector

Exploitation requires an authenticated backend account and user interaction to complete the Google consent screen. The attacker requests Google::oauth with the victim provider's identifier, authenticates to an attacker-controlled Google account, and lets the callback persist the malicious token.

php
// Patch: application/controllers/Google.php
// fix: enforce provider ownership in google oauth callback

// Store the token into the database for future reference.
-$oauth_provider_id = session('oauth_provider_id');
+$oauth_provider_id = filter_var(session('oauth_provider_id'), FILTER_VALIDATE_INT);
+$user_id = (int) session('user_id');
+
+if ($oauth_provider_id && $oauth_provider_id > 0) {
+    if (cannot('edit', PRIV_USERS) && $user_id !== (int) $oauth_provider_id) {
+        show_error('Forbidden', 403);
+
+        return;
+    }

-if ($oauth_provider_id) {
     $this->providers_model->set_setting($oauth_provider_id, 'google_sync', true);
     $this->providers_model->set_setting($oauth_provider_id, 'google_token', json_encode($token));
     $this->providers_model->set_setting($oauth_provider_id, 'google_calendar', 'primary');
+    session(['oauth_provider_id' => null]);

Source: GitHub Commit 4b2d245

Detection Methods for CVE-2026-52841

Indicators of Compromise

  • Unexpected changes to google_sync, google_token, or google_calendar settings in the ea_user_settings table for a provider who did not initiate reconfiguration.
  • Access log entries where Google::oauth is called with a provider_id that does not match the authenticated session user.
  • Provider accounts whose calendar sync target changed without a corresponding audit record from the account owner.

Detection Strategies

  • Compare the provider_id parameter on OAuth requests against the session user_id and alert on mismatches unless the actor holds PRIV_USERS edit rights.
  • Review database change history for writes to Google sync settings that were not preceded by a login from the affected provider.
  • Correlate Google API token issuance events with the internal user who initiated the OAuth flow.

Monitoring Recommendations

  • Enable verbose logging on the Google controller and forward events to a centralized log store for retention and search.
  • Monitor for repeated OAuth attempts from a single backend account against multiple provider_id values.
  • Alert on outbound Google Calendar API traffic tied to provider accounts that have not historically used sync.

How to Mitigate CVE-2026-52841

Immediate Actions Required

  • Upgrade Easy!Appointments to version 1.6.0 or later, which enforces provider ownership in the OAuth callback.
  • Revoke all existing Google OAuth tokens stored in provider settings and require providers to re-authorize sync after upgrade.
  • Audit every provider row for unexpected google_token or google_calendar values and clear untrusted entries.

Patch Information

The fix is delivered in Easy!Appointments 1.6.0. Commit 4b2d245 validates the session oauth_provider_id as an integer, compares it to the authenticated user_id, and returns HTTP 403 when a non-privileged user attempts to bind sync to another provider. See the GitHub Security Advisory GHSA-8hm4-r66f-29wr for advisory details.

Workarounds

  • Restrict backend access to trusted administrators until the upgrade is complete.
  • Temporarily disable the Google Calendar sync feature by removing OAuth credentials from the application configuration.
  • Rotate Google API client secrets after upgrading to invalidate any tokens issued during the exposure window.
bash
# Upgrade Easy!Appointments to the patched release
git fetch --tags
git checkout 1.6.0
php composer.phar install --no-dev

# Clear stored Google tokens after upgrade (example SQL)
# mysql> UPDATE ea_user_settings SET setting_value = NULL
#         WHERE setting_name IN ('google_token', 'google_sync', 'google_calendar');

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.