---
id: "CVE-2026-104012"
kind: "vulnerability"
aliases: ["CVE-2026-104012"]
title: "WordPress Rox Appointment Booking plugin lets visitors take over admin accounts"
severity: "high"
cvss: 8.8
epss: null
exploited: false
status: "open"
category: "package"
products: []
ecosystems: []
tags: ["appointment-booking", "package", "rox-appointment-booking", "wordpress"]
not_affected_if: ["plugin-not-installed", "plugin-version-above-1.3.1"]
published_at: "2026-10-31T08:16:47+00:00"
first_seen_at: "2026-10-31T08:34:28+00:00"
updated_at: "2026-10-31T08:35:00+00:00"
sources: [{"source": "nvd", "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-104012", "first_seen_at": "2026-10-31T08:34:28+00:00"}]
---

# WordPress Rox Appointment Booking plugin lets visitors take over admin accounts

The Rox Appointment Booking WordPress plugin, up to and including version 1.3.1, has a public booking endpoint that accepts a user ID field without checks. An unauthenticated attacker can link a booking to an administrator's WordPress account and change that administrator's email, then reset the password to take over the site.

_Summary, check and fix written by a model from the sources; labelled as such._

## How to check

- Check the installed plugin version in the WordPress admin plugin list or the `rox-appointment-booking` plugin header; versions up to and including `1.3.1` are affected.
- Look for the public route `/wp-json/rox-appointment-booking/v1/public/booking` on the site.

## Fix

- Rox Appointment Booking: unknown (the sources do not name a fixed version).

## Timeline

- 2026-10-31T08:34:28+00:00 nvd https://nvd.nist.gov/vuln/detail/CVE-2026-104012

## From the sources

The Rox Appointment Booking – Appointment Booking Scheduling Solution plugin for WordPress is vulnerable to Privilege Escalation via Mass Assignment in all versions up to, and including, 1.3.1 This is due to the public `/rox-appointment-booking/v1/public/booking` REST endpoint performing mass-assignment of the raw request body into a new customer row while `CustomerModel::$fillable` includes the internal `wp_user_id` column, allowing an unauthenticated attacker to persist an arbitrary WordPress user ID alongside an attacker-controlled email address with no authorization check. When an administrator subsequently opens the poisoned customer record and clicks Update Customer, `SaveCustomer::handleRequest()` passes the stored `wp_user_id` and attacker-supplied email to `wp_update_user()` — succeeding because `LinkedAccount::canChange()` unconditionally returns true when the acting user holds the `edit_users` capability — thereby overwriting the targeted administrator's email address and enabling full account takeover via a standard WordPress password-reset request. Successful exploitation requires an administrator to open and save the poisoned record, and the attacker must know or guess a valid administrator user ID (such as the default user ID 1).

---

_Free to read at a human pace. An API with keys and an MCP server are in preparation; early access: hello@infrastack.ai_
