CVE-2025-50383
Description
alextselegidis Easy!Appointments v1.5.1 was discovered to contain a SQL injection vulnerability via the order_by parameter.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Easy!Appointments version 1.5.1 contains a SQL injection vulnerability in the 'order_by' parameter, fixed in version 1.5.2.
Vulnerability
Description
Easy!Appointments version 1.5.1 is vulnerable to SQL injection via the order_by parameter in various API endpoints. The root cause is that the application passed user-controlled order-by values directly to the database query builder's order_by() method without sanitization or escaping [1]. This allowed an attacker to inject arbitrary SQL fragments.
Exploitation
Details
An attacker with access to administrative backend functionality, such as managing appointments, users, or blocked periods, could manipulate the order_by parameter in HTTP requests to inject malicious SQL [1][3]. No authentication bypass is required—the attacker needs valid backend credentials. The vulnerability exists in multiple methods, including get(), search(), and others.
Impact
Successful exploitation could allow an attacker to read, modify, or delete data within the application's database. This may include sensitive appointment information, user credentials, or other stored data. Additionally, an attacker might leverage the injection for further attacks such as privilege escalation or data exfiltration.
Mitigation
The vulnerability was addressed in commit [1] and is fixed in version 1.5.2 [2]. Users are strongly advised to upgrade to the latest version. The fix involves escaping the order_by parameter using the framework's built-in escape() method, preventing SQL injection [1].
AI Insight generated on May 19, 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.2-beta.1 | 1.5.2-beta.1 |
Affected products
2- alextselegidis/Easy!Appointmentsdescription
- Range: =1.5.1
Patches
10f0d71cfe069Escape the order_by parameters so that we avoid invalid SQL being executed
14 files changed · +28 −28
application/models/Admins_model.php+2 −2 modified@@ -205,7 +205,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $admins = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); @@ -512,7 +512,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Appointments_model.php+2 −2 modified@@ -185,7 +185,7 @@ public function get( } if ($order_by) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $appointments = $this->db @@ -492,7 +492,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Blocked_periods_model.php+2 −2 modified@@ -241,7 +241,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -273,7 +273,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $blocked_periods = $this->db->get('blocked_periods', $limit, $offset)->result_array();
application/models/Consents_model.php+2 −2 modified@@ -206,7 +206,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -238,7 +238,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $consents = $this->db->get('consents', $limit, $offset)->result_array();
application/models/Customers_model.php+2 −2 modified@@ -167,7 +167,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $customers = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); @@ -415,7 +415,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Providers_model.php+2 −2 modified@@ -219,7 +219,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $providers = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); @@ -701,7 +701,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Roles_model.php+2 −2 modified@@ -283,7 +283,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -315,7 +315,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $roles = $this->db->get('roles', $limit, $offset)->result_array();
application/models/Secretaries_model.php+2 −2 modified@@ -217,7 +217,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $secretaries = $this->db->get_where('users', ['id_roles' => $role_id], $limit, $offset)->result_array(); @@ -538,7 +538,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Service_categories_model.php+2 −2 modified@@ -235,7 +235,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -267,7 +267,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $service_categories = $this->db->get('service_categories', $limit, $offset)->result_array();
application/models/Services_model.php+2 −2 modified@@ -318,7 +318,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $services = $this->db->get('services', $limit, $offset)->result_array(); @@ -361,7 +361,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Settings_model.php+2 −2 modified@@ -226,7 +226,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -258,7 +258,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $settings = $this->db->get('settings', $limit, $offset)->result_array();
application/models/Unavailabilities_model.php+2 −2 modified@@ -153,7 +153,7 @@ public function get( } if ($order_by) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $unavailabilities = $this->db @@ -330,7 +330,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array();
application/models/Users_model.php+2 −2 modified@@ -355,7 +355,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -388,7 +388,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $users = $this->db->get('users', $limit, $offset)->result_array();
application/models/Webhooks_model.php+2 −2 modified@@ -221,7 +221,7 @@ public function search(string $keyword, ?int $limit = null, ?int $offset = null, ->group_end() ->limit($limit) ->offset($offset) - ->order_by($order_by) + ->order_by($this->db->escape($order_by)) ->get() ->result_array(); @@ -253,7 +253,7 @@ public function get( } if ($order_by !== null) { - $this->db->order_by($order_by); + $this->db->order_by($this->db->escape($order_by)); } $webhooks = $this->db->get('webhooks', $limit, $offset)->result_array();
Vulnerability mechanics
Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
7- github.com/advisories/GHSA-2f28-69j7-85hfghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2025-50383ghsaADVISORY
- easyappointments.orgghsaWEB
- github.com/alextselegidis/easyappointments/commit/0f0d71cfe0692daed9aee59bc424ce2a084fd59eghsaWEB
- github.com/alextselegidis/easyappointments/releases/tag/1.5.2-beta.1ghsaWEB
- alextselegidis.commitre
- easyappointments.orgmitre
News mentions
0No linked articles in our index yet.