GitHub Advisoryadvisory · Packagist
GHSA-996f-334j-67g7 Easy!Appointments disable_booking_message rendered as raw HTML on public booking page — Stored XSS
LOW
Official page ↗
- Aliases
- CVE-2026-52838
- Ecosystem
- Packagist
- Packages
- alextselegidis/easyappointments
- Severity
- Low
- CVSS vector
- CVSS:3.1/AV:N/AC:H/PR:H/UI:R/S:C/C:N/I:L/A:N
- Weaknesses
- CWE-79
- Reviewed
- 2026-07-29
Affected packages
• Packagist alextselegidis/easyappointments: <= 1.5.2 (no fix yet)
Description
Summary
Easy!Appointments allows administrators to define a custom "booking disabled" message through the booking settings page. That value is stored in the `disable_booking_message` setting via a rich-text editor and later passed directly to the public `booking_message` view without escaping or sanitization:
```php
```
An authenticated administrator can store HTML or JavaScript in this field, enable disabled-booking mode, and trigger stored XSS in every unauthenticated visitor who opens the public booking page.
---
Root Cause — Step by Step Code Flow
Step 1 — Rich text editor value stored without sanitization
The booking settings page collects the message value from the Trumbowyg rich-text editor and submits it as raw HTML:
```javascript
// assets/js/pages/booking_settings.js line 61-92
bookingSettings.push({
name: 'disable_booking_message',
value: $disableBookingMessage.trumbowyg('html'),
});
```
Step 2 — Settings controller saves value verbatim
The backend settings controller persists the submitted value without any HTML sanitization:
```php
// application/controllers/Booking_settings.php line 76-104
$this->settings_model->save($setting);
```
Step 3 — Public booking controller forwards stored value to view
When booking is disabled, the public booking controller loads the stored message and passes it directly to the view:
```php
// application/controllers/Booking.php line 113-132
$disable_booking_message = setting('disable_booking_message');
html_vars([
'message_text' => $disable_booking_message,
]);
```
Step 4 — Public view renders value without escaping
The booking message view emits the value raw using PHP's short echo tag with no escaping:
```php
// application/views/pages/booking_message.php line 10-12
```
No `htmlspecialchars()`, no sanitization, no template escaping is applied at any point in this rendering path.
---
Proof of Concept
Step 1 — Store malicious disabled-booking message as admin:
```http
POST /index.php/booking_settings/save HTTP/1.1
Host: 127.0.0.1:18094
Cookie:
Content-Type: application/x-www-form-urlencoded
csrf_token=&booking_settings[0][name]=disable_booking&booking_settings[0][value]=1&booking_settings[1][name]=disable_booking_message&booking_settings[1][value]=
```
Response: `200 OK` — settings saved successfully
Step 2 — Unauthenticated visitor opens public booking page:
```http
GET / HTTP/1.1
Host: 127.0.0.1:18094
(no authentication)
```
Observed response fragment:
```html
```
Observed browser behavior:
`alert("easyappointments xss by ashrexon")` executes immediately on page load with no authentication required. Confirmed via browser screenshot attached as comment.
Runtime verification result:
```
admin login ok
settings save ok
payload reflected on public page
PASS
```
---
Real World Impact
Easy!Appointments is deployed as a public-facing appointment booking surface for businesses, clinics, and service providers. An administrator can abuse the disabled-booking message — a customer-facing feature intended for maintenance or holiday notices — to plant JavaScript that executes in every visitor's browser when the booking page is disabled. This can be used to:
• Execute arbitrary JavaScript in visitor browsers on the trusted booking domain
• Phish visitor credentials or personal information during booking downtime
• Deface the public booking page during maintenance or outage windows
• Redirect visitors to attacker-controlled sites
---
Suggested Fix
Escape the message value before rendering in the view:
```php
// application/views/pages/booking_message.php
```
Alternatively apply a strict HTML sanitizer (allowing only safe formatting tags, no event handlers or script elements) to the `disable_booking_message` value before storage or before rendering, to preserve intended rich-text formatting while preventing script injection.
---
Reporter
Yash Shendge (ashrexon)
2026-05-25
Related
Alias · CVE (1)
- CVE-2026-52838 Easy!Appointments is a self hosted appointment scheduler. vulnerability
Weakness · CWE (1)
- CWE-79 Improper Neutralization of Input During Web Page Generation weakness
References
- https://github.com/alextselegidis/easyappointments/security/advisories/GHSA-996f-334j-67g7 web
- https://nvd.nist.gov/vuln/detail/CVE-2026-52838 advisory
- https://github.com/alextselegidis/easyappointments/commit/629a0415f54f75556c17f4f5d9c77fda1fdbdeae web
- https://github.com/alextselegidis/easyappointments package
- https://github.com/alextselegidis/easyappointments/releases/tag/1.6.0 web