Easy!Appointments versions up to 1.6.0 have an authorization bypass vulnerability in the Booking::register() function. This flaw allows unauthenticated attackers to modify any appointment by supplying an appointment ID without the required hash. Attackers can enumerate appointment IDs sequentially, use a self-asserted manage_mode flag to alter appointment details, reassign appointments to attacker-controlled customers, and obtain management hashes for rescheduling or cancellation.
Plainpad through 1.1.1, fixed in commit d3823fc, contains a missing rate limiting vulnerability that allows unauthenticated attackers to send unbounded login requests to the POST /v1/sessions endpoint due to dead code in App\Http\Kernel.php that is never instantiated under the Laravel 11+ skeleton, leaving the API throttle configuration unattached to any route. Attackers can exploit this by sending unlimited credential attempts with no lockout or CAPTCHA enforcement, and additionally trigger CPU exhaustion by forcing repeated bcrypt comparisons on each request.
Easy!Appointments is a self hosted appointment scheduler. In version 1.5.2, an Excessive Data Exposure vulnerability in the customers search endpoint allows an authenticated user to obtain appointment hashes belonging to other users.
Using these hashes, an attacker can modify or delete appointments of other providers, resulting in an Appointments Takeover. Version 1.6.0 fixes the issue.
Easy!Appointments is a self hosted appointment scheduler. In versions prior to 1.6.0, `Google::oauth` at `application/controllers/Google.php:278` stores its URL-supplied `provider_id` in the session, and `oauth_callback` saves the issued Google OAuth token against that row without checking the caller owns the provider. Any logged-in backend user (admin, provider, or secretary) rebinds a peer provider's Google sync to a Google account they control. The peer's appointments then sync into the attacker's calendar with each customer's name and email attached as attendee data. Version 1.6.0 patches the issue.
Easy!Appointments is a self hosted appointment scheduler. In versions prior to 1.6.0, `Caldav::connect_to_server` at `application/controllers/Caldav.php:60` hands the request's `caldav_url` to a Guzzle `REPORT` call without scheme or host validation. A logged-in backend user (admin, provider, or secretary) reaches loopback, RFC1918, and link-local hosts on the deployment's network. The Guzzle exception path returns the upstream status code plus ~120 bytes of response body in the JSON `message` field (`Caldav.php:74-78`), so the SSRF is semi-blind. Version 1.6.0 contains a patch.
Easy!Appointments is a self hosted appointment scheduler. Versions prior to 1.6.0 correctly filter provider-scoped appointments in the `appointments/search` response, proving that provider isolation is an intended security boundary. However, the direct mutation endpoints `appointments/store` and `appointments/update` only check generic appointment privileges and never verify that the submitted `id_users_provider` belongs to the current session. A normal authenticated provider can inject new appointments into another provider's schedule via `store`, or reassign existing appointments into a foreign provider's calendar via `update`. The `store` path contains an additional write-before-crash bug: the unauthorized row is committed to the database before the controller crashes on a type error, so the attacker receives an error response while the foreign appointment is already persisted. Version 1.6.0 patches the issue.
Easy!Appointments is a self hosted appointment scheduler. Versions prior to 1.6.0 allow 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. 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. Version 1.6.0 fixes the issue.
Easy!Appointments is a self hosted appointment scheduler. In versions up to and including 1.5.2, the booking reschedule view at `/index.php/booking/reschedule/{appointment_hash}` (handled by `Booking::index()`) embeds the entire customer record as inline JavaScript (`const vars = {... "customer_data": {...}, ...}`) without authentication and without field whitelisting. Anyone in possession of the 12-character `appointment_hash` — which appears in plain text in reschedule emails, confirmation page URLs, and operator-side calendar links — can read every column of that customer's row in the `ea_users` table. Version 1.6.0 contains a patch.
Plainpad is a self hosted note taking app. Prior to version 1.1.1, Plainpad allows a low-privilege authenticated user to self-escalate to administrator by submitting admin=true in PUT /api.php/v1/users/{id}. The endpoint directly persists the admin attribute from user input, and the escalated account can immediately access admin-only routes. This issue has been patched in version 1.1.1.
CVE-2026-23622 is a high-severity Cross-Site Request Forgery (CSRF) vulnerability affecting Easy! Appointments versions 1.5.2 and earlier. The vulnerability arises because the application only enforces CSRF protection on POST requests, while some state-changing operations accept parameters via GET requests, allowing attackers to craft malicious GET requests to perform unauthorized actions. Exploitation can lead to creation of admin accounts, modification of admin credentials, and full admin account takeover without requiring authentication. This flaw significantly compromises confidentiality, integrity, and availability of affected systems. European organizations using Easy! Appointments self-hosted scheduler are at risk, especially those with public-facing installations. Mitigation involves applying patches when available, restricting state-changing operations to POST methods only, and implementing CSRF tokens for all state-changing endpoints regardless of HTTP method.
The Easy!Appointments plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the plugin's 'easyappointments' shortcode in all versions up to, and including, 1.3.1 due to insufficient input sanitization and output escaping on user supplied attributes. This makes it possible for authenticated attackers with contributor-level and above permissions to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.