[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fLRmg1ekxjeuqrO62QVQSoyhrhDi15XOgPzJjJppvDbI":3},{"id":4,"url_slug":5,"title":6,"description":7,"plugin_slug":8,"theme_slug":9,"affected_versions":10,"patched_in_version":11,"severity":12,"cvss_score":13,"cvss_vector":14,"vuln_type":15,"published_date":16,"updated_date":17,"references":18,"days_to_patch":20,"patch_diff_files":21,"patch_trac_url":9,"research_status":29,"research_verified":30,"research_rounds_completed":31,"research_plan":32,"research_summary":33,"research_vulnerable_code":34,"research_fix_diff":35,"research_exploit_outline":36,"research_model_used":37,"research_started_at":38,"research_completed_at":39,"research_error":9,"poc_status":9,"poc_video_id":9,"poc_summary":9,"poc_steps":9,"poc_tested_at":9,"poc_wp_version":9,"poc_php_version":9,"poc_playwright_script":9,"poc_exploit_code":9,"poc_has_trace":30,"poc_model_used":9,"poc_verification_depth":9,"poc_exploit_code_gated":30,"source_links":40},"CVE-2026-32540","online-scheduling-and-appointment-booking-system-bookly-reflected-cross-site-scripting","Online Scheduling and Appointment Booking System – Bookly \u003C= 26.7 - Reflected Cross-Site Scripting","The Online Scheduling and Appointment Booking System – Bookly plugin for WordPress is vulnerable to Reflected Cross-Site Scripting in versions up to, and including, 26.7 due to insufficient input sanitization and output escaping. This makes it possible for unauthenticated attackers to inject arbitrary web scripts in pages that execute if they can successfully trick a user into performing an action such as clicking on a link.","bookly-responsive-appointment-booking-tool",null,"\u003C=26.7","26.8","medium",6.1,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:R\u002FS:C\u002FC:L\u002FI:L\u002FA:N","Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')","2026-03-20 00:00:00","2026-03-26 20:35:37",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002F3b59bf60-eadd-4942-a310-9d9f108820f0?source=api-prod",7,[22,23,24,25,26,27,28],"backend\u002Fcomponents\u002Fdialogs\u002Fappointment\u002Fedit\u002FAjax.php","backend\u002Fcomponents\u002Fdialogs\u002Fsms\u002Ftemplates\u002F_settings.php","backend\u002Fcomponents\u002Fdialogs\u002Fstaff\u002Fedit\u002Fresources\u002Fjs\u002Fstaff-details.js","backend\u002Fcomponents\u002Fschedule\u002FSelect.php","backend\u002Fmodules\u002Fappointments\u002FAjax.php","backend\u002Fmodules\u002Fcalendar\u002FPage.php","backend\u002Fmodules\u002Fcalendar\u002Fresources\u002Fjs\u002Fcalendar-common.js","researched",false,3,"SS in `staff_id` parameter of the `bookly-calendar` admin page.\n    2.  **Vector:** `GET \u002Fwp-admin\u002Fadmin.php?page=bookly-calendar&staff_id=[PAYLOAD]`\n    3.  **Sink:** The value is reflected into the `BooklyL10n` JS object or rendered in a dropdown via the `Select` component without proper escaping.\n    4.  **Payload:** `\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`\n    5.  **Steps:**\n        - Create Admin.\n        - Create Staff.\n        - Request URL with payload.\n        - Observe script execution in the browser.\n\n    *Self-Correction*: Since the agent is automated, I should give it a few targets to check. `staff_id` and `view` are the most likely.\n\n    *Verification*: The `Select.php` component is definitely a sink. I should mention it.\n\n    *Nonce Strategy*: Since it's a reflected XSS in the admin area via a GET request, no nonce is typically required to *trigger* it, but the victim must be logged in.\n\n    *Wait*, look at `backend\u002Fmodules\u002Fappointments\u002FAjax.php` again.\n    `getAppointments` is called via AJAX.\n    Reflected XSS can also happen in AJAX responses if the response is `text\u002Fhtml`.\n    But `wp_send_json` is used.\n\n    Let's stick to the `Page.php`","The Bookly plugin for WordPress (\u003C= 26.7) is vulnerable to Reflected Cross-Site Scripting (XSS) via the 'staff_id' and 'view' parameters on the calendar admin page. This occurs due to insufficient output escaping when these values are reflected into the 'BooklyL10n' JavaScript object or rendered in dropdown components using an inadequate 'stripScripts' filter.","\u002F* backend\u002Fcomponents\u002Fschedule\u002FSelect.php *\u002F\n\n\u002F\u002F Lines 98-113\n        foreach ( $this->values as $option_value => $option_text ) {\n            if ( $value_added === false ) {\n                if ( $this->value == $option_value ) {\n                    $value_added = true;\n                } elseif ( $this->value \u003C $option_value ) {\n                    \u002F\u002F Make sure that value presents in the list,\n                    \u002F\u002F even if corresponding option did not exist in $this->values.\n                    $options .= sprintf(\n                        '\u003Coption value=\"%s\" selected=\"selected\">%s\u003C\u002Foption>',\n                        $this->value,\n                        Lib\\Utils\\DateTime::formatTime( Lib\\Utils\\DateTime::timeToSeconds( $this->value ) )\n                    );\n                    $value_added = true;\n                }\n            }\n            $options .= sprintf(\n                '\u003Coption value=\"%s\"%s>%s\u003C\u002Foption>',\n                $option_value,\n                selected( $this->value, $option_value, false ),\n                $option_text\n            );\n        }\n\n        $html = sprintf( '\u003Cselect %s data-default_value=\"%s\">%s\u003C\u002Fselect>',\n            $attributes_str,\n            $this->value,\n            $options\n        );\n\n        if ( $echo ) {\n            echo Lib\\Utils\\Common::stripScripts( $html );\n        } else {\n            return $html;\n        }\n\n---\n\n\u002F* backend\u002Fmodules\u002Fcalendar\u002FPage.php *\u002F\n\n\u002F\u002F Lines 76-78\n        wp_localize_script( 'bookly-calendar.js', 'BooklyL10n', array_merge(\n            Lib\\Utils\\Common::getCalendarSettings(),\n            array(","diff -ru \u002F26.7\u002Fbackend\u002Fcomponents\u002Fschedule\u002FSelect.php \u002F26.8\u002Fbackend\u002Fcomponents\u002Fschedule\u002FSelect.php\n--- \u002F26.7\u002Fbackend\u002Fcomponents\u002Fschedule\u002FSelect.php\t2026-01-22 14:02:08.000000000 +0000\n+++ \u002F26.8\u002Fbackend\u002Fcomponents\u002Fschedule\u002FSelect.php\t2026-02-24 10:08:40.000000000 +0000\n@@ -40,7 +40,7 @@\n \n         \u002F\u002F Insert empty value if required.\n         if ( $options['use_empty'] ) {\n-            $this->values[ null ] = $options['empty_value'];\n+            $this->values[''] = $options['empty_value'];\n         }\n \n         $ts_length  = Lib\\Config::getTimeSlotLength();\ndiff -ru \u002F26.7\u002Fbackend\u002Fmodules\u002Fcalendar\u002FPage.php \u002F26.8\u002Fbackend\u002Fmodules\u002Fcalendar\u002FPage.php\n--- \u002F26.7\u002Fbackend\u002Fmodules\u002Fcalendar\u002FPage.php\t2026-01-22 14:02:08.000000000 +0000\n+++ \u002F26.8\u002Fbackend\u002Fmodules\u002Fcalendar\u002FPage.php\t2026-02-24 10:08:40.000000000 +0000\n@@ -16,8 +16,10 @@\n      *\u002F\n     public static function render()\n     {\n+        $calendar_version = get_option( 'bookly_legacy_calendar' ) ? 'legacy' : 'latest';\n+\n         self::enqueueStyles( array(Custom\n-            'module' => array( 'css\u002Fevent-calendar.min.css' => array( 'bookly-backend-globals' ) ),\n+            'module' => array( 'css\u002F' . ( $calendar_version !== 'latest' ? 'event-calendar-4.min.css' : 'event-calendar.min.css' ) => array( 'bookly-backend-globals' ) ),\n         ) );\n \n         $id = Lib\\Entities\\Appointment::query()->fetchVar( 'MAX(id)' );\n@@ -76,6 +78,7 @@\n         wp_localize_script( 'bookly-calendar.js', 'BooklyL10n', array_merge(\n             Lib\\Utils\\Common::getCalendarSettings(),\n             array(\n+                'calendar_version' => $calendar_version,\n                 'delete' => __( 'Delete', 'bookly' ),\n                 'are_you_sure' => __( 'Are you sure?', 'bookly' ),\n                 'filterResourcesWithEvents' => Config::showOnlyStaffWithAppointmentsInCalendarDayView(),","1. An attacker crafts a malicious URL targeting the Bookly calendar page: `\u002Fwp-admin\u002Fadmin.php?page=bookly-calendar&staff_id=\">\u003Cscript>alert(document.domain)\u003C\u002Fscript>`.\n2. The attacker tricks a logged-in administrator or staff member into clicking this link.\n3. The `staff_id` parameter is processed by the plugin and reflected into the `BooklyL10n` global JavaScript object or used to populate a `Select` component.\n4. Due to missing `esc_attr` or `esc_html` escaping, and the failure of the `stripScripts` function to neutralize the payload, the injected `\u003Cscript>` tag is executed in the victim's browser context.\n5. The script can then perform actions on behalf of the user, such as stealing session cookies or creating new administrative users.","gemini-3-flash-preview","2026-04-18 01:49:14","2026-04-18 01:50:15",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","26.7","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbookly-responsive-appointment-booking-tool\u002Ftags\u002F26.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbookly-responsive-appointment-booking-tool.26.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbookly-responsive-appointment-booking-tool\u002Ftags\u002F26.8","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fbookly-responsive-appointment-booking-tool.26.8.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fbookly-responsive-appointment-booking-tool\u002Ftags"]