Authorization Bypass Through User-Controlled Key in alextselegidis/easyappointments
Description
Authorization Bypass Through User-Controlled Key in GitHub repository alextselegidis/easyappointments prior to 1.5.0.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Easy!Appointments before 1.5.0 allows unauthorized appointment management via user-controlled keys, enabling arbitrary appointment modification.
The vulnerability is an authorization bypass through user-controlled keys in Easy!Appointments versions prior to 1.5.0 [1]. The root cause is insufficient permission checks on user-supplied data, such as appointment_data and provider IDs, allowing manipulation of appointment records without proper authorization [3].
Attackers can exploit this by crafting HTTP requests that modify the id_users_provider field or other appointment-related parameters. No special privileges are required; any user with access to the booking interface can potentially exploit this flaw [4].
Successful exploitation enables an attacker to create, modify, or delete appointments for any provider, bypassing intended access controls. This could lead to disruption of scheduling and unauthorized data manipulation [1].
The issue is fixed in version 1.5.0, which adds permission checks in the relevant controller methods, as evidenced by the commit b37b460 [3]. Users are advised to upgrade to the latest version.
AI Insight generated on May 20, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
alextselegidis/easyappointmentsPackagist | < 1.5.0 | 1.5.0 |
Affected products
2- alextselegidis/alextselegidis/easyappointmentsv5Range: unspecified
Patches
1b37b46019553Only allow authorized users to manage appointments from the calendar page (#1387)
1 file changed · +30 −4
application/controllers/Calendar.php+30 −4 modified@@ -181,9 +181,12 @@ public function save_appointment() { try { - // Save customer changes to the database. $customer_data = request('customer_data'); + $appointment_data = request('appointment_data'); + + $this->check_event_permissions($appointment_data['id_users_provider']); + // Save customer changes to the database. if ($customer_data) { $customer = $customer_data; @@ -216,8 +219,6 @@ public function save_appointment() } // Save appointment changes to the database. - $appointment_data = request('appointment_data'); - $manage_mode = ! empty($appointment_data['id']); if ($appointment_data) @@ -323,6 +324,9 @@ public function delete_appointment() // Store appointment data for later use in this method. $appointment = $this->appointments_model->find($appointment_id); + + $this->check_event_permissions($appointment['id_users_provider']); + $provider = $this->providers_model->find($appointment['id_users_provider'], TRUE); $customer = $this->customers_model->find($appointment['id_users_customer'], TRUE); $service = $this->services_model->find($appointment['id_services'], TRUE); @@ -373,7 +377,11 @@ public function save_unavailability() throw new RuntimeException('You do not have the required permissions for this task.'); } - $provider = $this->providers_model->find($unavailability['id_users_provider']); + $provider_id = $unavailability['id_users_provider']; + + $this->check_event_permissions($provider_id); + + $provider = $this->providers_model->find($provider_id); $unavailability_id = $this->unavailabilities_model->save($unavailability); @@ -409,6 +417,8 @@ public function delete_unavailability() $unavailability_id = request('unavailability_id'); $unavailability = $this->appointments_model->find($unavailability_id); + + $this->check_event_permissions($unavailability['id_users_provider']); $provider = $this->providers_model->find($unavailability['id_users_provider']); @@ -742,4 +752,20 @@ public function get_calendar_appointments() json_exception($e); } } + + private function check_event_permissions($provider_id) + { + $user_id = (int)session('user_id'); + $role_slug = session('role_slug'); + + if ($role_slug === DB_SLUG_SECRETARY && ! $this->secretaries_model->is_provider_supported($user_id, $provider_id)) + { + abort(403); + } + + if ($role_slug === DB_SLUG_PROVIDER && $user_id !== $provider_id) + { + abort(403); + } + } }
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
4News mentions
0No linked articles in our index yet.