CVE-2026-52837 Overview
CVE-2026-52837 is an information disclosure vulnerability in Easy!Appointments, a self-hosted appointment scheduler. Versions up to and including 1.5.2 expose the entire customer record through the booking reschedule view at /index.php/booking/reschedule/{appointment_hash}. The Booking::index() handler embeds the customer row from the ea_users table as inline JavaScript without authentication or field whitelisting. Anyone possessing the 12-character appointment_hash can read every column of the associated customer record. This hash appears in plain text in reschedule emails, confirmation page URLs, and operator-side calendar links. The issue is classified under [CWE-200] Exposure of Sensitive Information to an Unauthorized Actor. Version 1.6.0 contains the patch.
Critical Impact
Unauthenticated attackers who obtain a 12-character appointment hash can read all columns of a customer's row in the ea_users table, including personal data stored by the application.
Affected Products
- Easy!Appointments versions up to and including 1.5.2
- The vulnerable code path is Booking::index() in the booking reschedule flow
- Fixed in Easy!Appointments 1.6.0
Discovery Timeline
- 2026-07-14 - CVE-2026-52837 published to NVD
- 2026-07-14 - Last updated in NVD database
Technical Details for CVE-2026-52837
Vulnerability Analysis
The vulnerability resides in the booking reschedule view exposed at /index.php/booking/reschedule/{appointment_hash}. When a client requests this endpoint, the Booking::index() controller retrieves the linked customer record from the ea_users table and serializes the full row into an inline JavaScript object. The rendered page contains a block similar to const vars = {... "customer_data": {...}, ...}, exposing every column of the customer record.
The endpoint enforces no authentication and applies no field whitelist. Any actor who obtains the 12-character appointment_hash can request the page and parse customer_data from the returned HTML. Because the hash is transmitted in reschedule emails, confirmation page URLs, and operator calendar links, it can leak through email forwarding, browser history, referer headers, or shared calendar exports.
Root Cause
The root cause is a missing access control combined with unrestricted output of database columns to the response body. The controller trusts the appointment_hash as a sole authorization token and treats the full ea_users record as safe to render client-side. There is no distinction between fields required by the reschedule UI and sensitive fields such as address, phone number, or notes.
Attack Vector
Attack is remote and unauthenticated. An attacker who obtains an appointment_hash from an email header, forwarded confirmation, screenshot, referer leak, or log file issues a single HTTP GET to the reschedule URL. The server responds with HTML containing the complete customer record inline. Parsing the JavaScript object yields all fields stored for that user.
// Excerpt from the security patch commit
// Source: https://github.com/alextselegidis/easyappointments/commit/725eafa647308846ce887657db12771a829e42ef
$appointment = json_decode(request('appointment'), true);
// Validate decoded appointment is an array
if (!is_array($appointment)) {
throw new InvalidArgumentException('Invalid appointment data provided.');
}
$user_id = (int) session('user_id');
$role_slug = session('role_slug');
if ($role_slug === DB_SLUG_PROVIDER) {
$appointment['id_users_provider'] = $user_id;
}
$this->appointments_model->only($appointment, $this->allowed_appointment_fields);
$this->appointments_model->optional($appointment, $this->optional_appointment_fields);
$appointment_id = $this->appointments_model->save($appointment);
$appointment = $this->appointments_model->find($appointment_id);
The security patch commit introduces server-side validation and role checks in the appointments controller and, in the same release, restricts the customer data exposed by the reschedule view.
Detection Methods for CVE-2026-52837
Indicators of Compromise
- Unauthenticated GET requests to /index.php/booking/reschedule/ followed by a 12-character hash string in access logs.
- Repeated requests to the reschedule endpoint from a single source enumerating different hash values.
- Response bodies larger than expected for the reschedule page, indicating full customer record embedding.
- Requests to the reschedule URL with Referer headers pointing to external mail providers or search engines.
Detection Strategies
- Parse web server access logs for booking/reschedule/ requests and correlate hashes with issued appointments to identify hash values used by unrelated clients.
- Deploy a web application firewall rule that inspects response bodies for the customer_data JavaScript block and alerts when it contains fields beyond those required for rescheduling.
- Compare source IP addresses accessing reschedule URLs against the IPs of the original customers where available.
Monitoring Recommendations
- Monitor outbound email systems for reschedule links being forwarded to addresses outside the original recipient's domain.
- Alert on spikes in HTTP requests to the Booking::index() route, especially from a small set of source IPs.
- Enable audit logging on the ea_users table access patterns if the database backend supports it.
How to Mitigate CVE-2026-52837
Immediate Actions Required
- Upgrade Easy!Appointments to version 1.6.0 or later, which contains the fix.
- Rotate all outstanding appointment_hash values by regenerating appointments or invalidating pending reschedule links.
- Review web server access logs for prior unauthenticated access to /index.php/booking/reschedule/ and identify potentially exposed customer records.
- Notify affected customers if logs indicate their records were accessed by unauthorized parties.
Patch Information
The fix is delivered in Easy!Appointments 1.6.0. The upstream changes are documented in the GitHub Security Advisory GHSA-xgr6-pqjv-3pf8 and the GitHub commit 725eafa. Administrators should apply the upgrade before rotating hashes to prevent the new hashes from being exposed by the same bug.
Workarounds
- Restrict access to /index.php/booking/reschedule/ at the reverse proxy or WAF, requiring an authenticated session or an additional token for the pre-patch versions.
- Modify the Booking::index() controller locally to strip sensitive fields from customer_data before rendering, keeping only the fields required by the reschedule UI.
- Shorten the lifetime of appointment_hash values and invalidate them after the reschedule window closes.
# Example nginx rule to block the vulnerable endpoint until patched
location ~* ^/index\.php/booking/reschedule/ {
return 403;
}
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

