Jul 30, 2026·6 min read·3 visits
An authorization bypass flaw in Easy!Appointments allows authenticated backend users to bind their personal Google OAuth token to other providers' profiles, syncing external scheduling metadata and customer PII directly to the attacker's calendar.
An authorization bypass vulnerability exists in Easy!Appointments before version 1.6.0. The application fails to validate ownership of the provider ID during the Google OAuth synchronization process. This allows authenticated backend users to link their personal Google Calendars to peer providers, leading to unauthorized access to scheduled appointments and associated customer metadata.
Easy!Appointments is an open-source, self-hosted appointment scheduler written in PHP. To facilitate workflow integration, the application allows provider accounts to synchronize their schedules with Google Calendar. This sync engine relies on OAuth 2.0 to safely exchange credentials and interact with Google's APIs.
Historically, the application managed the OAuth handshaking phase using a multi-step redirection workflow. The configuration process starts at /google/oauth/<provider_id> and concludes when the Google authorization server redirects the browser back to the /google/oauth_callback callback route. This multi-step process introduces a state-tracking dependency.
The vulnerability is categorized under CWE-639 (Authorization Bypass Through User-Controlled Key). Because the application lacks permission checks when restoring and writing state during the finalization phase, authenticated attackers can reconfigure third-party settings. This mechanism exposes internal appointment schedules and associated client Personally Identifiable Information (PII).
The root cause of this flaw lies in the insecure handling of session state data in the Google controller (application/controllers/Google.php). When a provider initiates synchronization, the browser calls /google/oauth/<provider_id>, passing the target provider's identifier. The application stores this parameter directly inside the active PHP session variable oauth_provider_id.
The initialization step does not verify whether the currently logged-in user owns the specified provider ID or possesses administrative privileges to alter settings for peer users. Any authenticated user can supply an arbitrary ID in the URL. This action forces the server to update the attacker's active session state with the targeted provider's ID.
Upon successful authentication at the Google OAuth gateway, Google redirects the client to the callback endpoint /google/oauth_callback. The server retrieves the target provider ID from the attacker's active session and applies the OAuth sync configuration. Because the backend trusts the value of oauth_provider_id without validating it against the active user_id or administrative permissions, the session pollution results in an unauthorized configuration change.
Before the fix was applied, the application's callback logic did not validate the ownership of the session state. The following code fragment demonstrates the vulnerable execution flow:
// application/controllers/Google.php (Vulnerable version)
// The oauth() method trustingly populates the session:
// session('oauth_provider_id', $provider_id);
public function oauth_callback(): void
{
// ... [Token retrieval logic is executed] ...
// Vulnerable step: retrieve value and modify DB without access controls
$oauth_provider_id = session('oauth_provider_id');
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');
}
}The security vulnerability is addressed in commit 4b2d245d2cd2058dc76e05f6eb65b26699268471 by introducing robust data sanitization, explicit integer casting, and active validation rules:
// application/controllers/Google.php (Patched version)
public function oauth_callback(): void
{
// ... [Token retrieval logic is executed] ...
// Store the token into the database for future reference.
$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) {
// Verify permissions and ensure ownership matching
if (cannot('edit', PRIV_USERS) && $user_id !== (int) $oauth_provider_id) {
show_error('Forbidden', 403);
return;
}
$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');
// Clear session state to prevent replay attacks
session(['oauth_provider_id' => null]);
}
}The integration of the authorization guard blocks unauthorized updates. If the active $user_id does not match the $oauth_provider_id session value and the caller lacks global administration permissions (cannot('edit', PRIV_USERS)), the request is rejected with an HTTP 403 response. Additionally, purging the session variable post-binding prevents replay exploitation vectors.
Exploitation of CVE-2026-52841 requires an active authenticated session within the Easy!Appointments system. This vulnerability cannot be exploited by an unauthenticated network actor. The attacker must occupy a legitimate backend role, such as a low-privileged provider or secretary.
To perform the attack, the attacker interacts with the OAuth initialization endpoint using a target provider's identifier. For example, if the attacker wishes to compromise provider user ID 2, they navigate directly to the following path:
https://<target-app>/google/oauth/2
This HTTP request populates the attacker's session state. The attacker then undergoes the standard OAuth approval process with their own Google credentials. Upon redirection back to /google/oauth_callback, the server reads the target ID of the victim from the session storage and links the attacker's Google API credentials to the victim's scheduling profile. The execution flow is summarized below:
Following the successful completion of this handshake, all new bookings and schedule changes associated with the victim automatically sync to the attacker's Google Calendar.
The operational impact of this vulnerability is the compromise of confidential client booking details. This data exposure poses a risk of regulatory non-compliance with frameworks like GDPR. Information synced to the external calendar database includes customer names, emails, phone numbers, and reservation metadata.
Additionally, calendar hijacking impairs business operations. The victim provider is prevented from syncing their appointments to their legitimate Google Calendar. Instead, they lose synchronization functionality, while the unauthorized attacker gains persistent oversight of their client queues and operational timelines.
Although the low CVSS v3.1 score of 3.1 reflects high privilege requirements and necessary user interaction, the vulnerability remains critical in multi-tenant environments. In organizations where multiple independent providers operate on a shared scheduler, the ability to spy on peers represents a direct compromise of the application's isolation model.
To address this vulnerability, self-hosted administrators must update their Easy!Appointments instances to version 1.6.0 or newer. This release implements explicit identity matching and privilege controls within the Google OAuth callback handler.
If immediate software upgrades are not feasible, administrators should audit their active configurations to identify potential signs of exploitation. You can query the configuration table to identify unexpected duplicate token strings or suspicious settings values shared between different provider profiles.
Reviewing web server access logs is also recommended. Look for pattern sequences where a single user session initiates /google/oauth/<id> queries for multiple distinct numeric identifiers in close temporal proximity. This log signature indicates active session manipulation attempts.
CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:U/C:L/I:L/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
Easy!Appointments Alextselegidis | < 1.6.0 | 1.6.0 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-639 |
| Attack Vector | Network |
| CVSS v3.1 Score | 3.1 (Low) |
| EPSS Score | 0.00129 |
| CISA KEV Status | Not Listed |
| Exploit Status | No public PoC |
| Vulnerable Versions | < 1.6.0 |
The system's authorization mechanism does not adequately verify the identity of the user requesting to access or modify resources, relying instead on user-provided keys.
An unauthenticated Personally Identifiable Information (PII) disclosure vulnerability exists in Easy!Appointments versions up to and including 1.5.2. Requesting the booking reschedule endpoint with a valid appointment hash causes the system to embed the raw customer database record into the HTML response as inline JavaScript variables, exposing sensitive details. This includes email addresses, phone numbers, physical addresses, custom database metadata, and internal directory configurations such as LDAP DNs. The vulnerability has been resolved in version 1.6.0.
This report provides a comprehensive technical teardown of CVE-2026-52838 (GHSA-996f-334j-67g7), a stored Cross-Site Scripting (XSS) vulnerability in Easy!Appointments. The flaw occurs in how the application manages the 'booking disabled' custom message configuration, allowing high-privileged administrators to persist unsanitized payloads that execute on unauthenticated guest landing pages.
CVE-2026-54574 (GHSA-9xq3-3fqg-4vg7) is a critical Symlink Escape and Arbitrary Host File Write vulnerability in proot-distro, an open-source utility for managing rootless PRoot containers on Termux and general Linux environments. The vulnerability is rooted in an asymmetric validation flaw during the archive extraction process of container installations, Docker/OCI layers, and container backup restorations. While the extraction engine successfully validated file names to prevent standard directory traversal (e.g., rejecting components containing '..'), it failed to validate symbolic link targets. An attacker could craft a malicious tar archive or container image that plants an absolute host-path symlink. Subsequent file members within the same archive could then traverse through this symlink, writing arbitrary files directly onto the host filesystem under the privileges of the executing process.
A container isolation bypass vulnerability exists in proot-distro prior to version 5.1.6. The utility accepted hardlink entries pointing outside the container directory being restored, allowing cross-container file read and write capabilities.
A critical security flaw (CVE-2026-54680) in the Kubernetes Logging Operator allows authenticated attackers with namespace-level access to craft malicious Custom Resources that inject arbitrary configuration directives into the downstream Fluentd logging aggregator, resulting in unauthenticated remote code execution (RCE) in the context of the aggregator pod.
A protection mechanism failure in the netfoil DNS proxy prior to version 0.4.0 causes blocked domains to resolve to null IP addresses (0.0.0.0 or ::) with a NOERROR status instead of NXDOMAIN. On Linux systems, connections to these addresses are routed to the loopback interface (localhost), allowing local processes to intercept sensitive HTTP traffic, including authorization headers and session cookies, intended for the blocked domains.