CVE-2026-2386

The Plus Addons for Elementor – Addons for Elementor, Page Templates, Widgets, Mega Menu, WooCommerce <= 6.4.7 - Incorrect Authorization to Authenticated (Author+) Arbitrary Draft Post Creation via 'post_type'

mediumIncorrect Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
6.4.8
Patched in
84d
Time to patch

Description

The The Plus Addons for Elementor – Addons for Elementor, Page Templates, Widgets, Mega Menu, WooCommerce plugin for WordPress is vulnerable to Incorrect Authorization in all versions up to, and including, 6.4.7. This is due to the tpae_create_page() AJAX handler authorizing users only with current_user_can('edit_posts') while accepting a user-controlled 'post_type' value passed directly to wp_insert_post() without post-type-specific capability checks. This makes it possible for authenticated attackers, with Author-level access and above, to create arbitrary draft posts for restricted post types (e.g., 'page' and 'nxt_builder') via the 'post_type' parameter.

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<=6.4.7
PublishedFebruary 18, 2026
Last updatedMay 12, 2026

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-2386 - Arbitrary Draft Post Creation in The Plus Addons for Elementor ## 1. Vulnerability Summary The "The Plus Addons for Elementor" plugin (versions <= 6.4.7) contains an incorrect authorization vulnerability in its AJAX handler `tpae_create_page()`. The handler is desig…

Show full research plan

Research Plan: CVE-2026-2386 - Arbitrary Draft Post Creation in The Plus Addons for Elementor

1. Vulnerability Summary

The "The Plus Addons for Elementor" plugin (versions <= 6.4.7) contains an incorrect authorization vulnerability in its AJAX handler tpae_create_page(). The handler is designed to allow users to create new posts or templates, but it only validates that the user has the edit_posts capability. It fails to perform specific capability checks for the requested post_type. Furthermore, the post_type parameter is passed directly to wp_insert_post(). This allows an authenticated user with Author-level permissions or higher to create draft posts of restricted types, such as page, nxt_builder (The Plus Addons template builder), or other custom post types they would normally not be authorized to create.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: tpae_create_page
  • HTTP Method: POST
  • Authentication: Required (Author role or higher, as they possess the edit_posts capability).
  • Vulnerable Parameter: post_type
  • Payload Parameters:
    • action: tpae_create_page
    • post_title: The title of the new draft.
    • post_type: The target post type (e.g., page, nxt_builder).
    • security or nonce: (Inferred) The AJAX nonce required for the action.

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers the AJAX handler in its main initialization or an AJAX-specific class:
    add_action( 'wp_ajax_tpae_create_page', [ $this, 'tpae_create_page' ] );
  2. Authorization Check: Inside tpae_create_page(), the code likely performs a check such as:
    if ( ! current_user_can( 'edit_posts' ) ) { wp_die(); }
  3. Nonce Verification: The code checks a nonce, likely using:
    check_ajax_referer( 'theplus-addons', 'security' ); or similar.
  4. Input Processing: The code retrieves post_type and post_title from $_POST.
  5. Sink: The parameters are passed into an array for wp_insert_post():
    $args = array(
        'post_title'  => sanitize_text_field( $_POST['post_title'] ),
        'post_type'   => $_POST['post_type'], // Directly controlled
        'post_status' => 'draft',
        // ...
    );
    wp_insert_post( $args );
    

4. Nonce Acquisition Strategy

To exploit this as an Author, we must obtain a valid nonce for the tpae_create_page action.

  1. Identify the Script & Localization: The Plus Addons typically localizes its AJAX data into a global JS variable. Based on the plugin's naming conventions, look for a variable like theplus_ajax_url or plus_ajax_data.
  2. Create Trigger Content: If the script is only loaded when specific widgets are active, create a post with a Plus Addons element:
    • wp post create --post_type=post --post_status=publish --post_title="Nonce Page" --post_content='[tp_button]' (Example shortcode).
  3. Extraction via Browser:
    • Log in as the Author user using the browser_navigate and login tools.
    • Navigate to any page where the Elementor editor or Plus Addons widgets are active.
    • Use browser_eval to extract the nonce:
      • browser_eval("window.theplus_ajax_url?.nonce") (inferred key)
      • browser_eval("window.plus_ajax_data?.security") (inferred key)
      • Or search all scripts: browser_eval("Object.keys(window).filter(k => k.includes('plus')).map(k => window[k])")

5. Exploitation Strategy

Once the nonce and an Author session are obtained:

  1. Craft the AJAX Request:

    • Use the http_request tool to send a POST request to /wp-admin/admin-ajax.php.
    • Target Post Type: page (Normally requires edit_pages capability, which Authors do not have by default).
  2. Payload Example:

    POST /wp-admin/admin-ajax.php HTTP/1.1
    Content-Type: application/x-www-form-urlencoded
    
    action=tpae_create_page&post_title=Malicious+Draft+Page&post_type=page&security=[EXTRACTED_NONCE]
    
  3. Verify Response:

    • A successful creation usually returns a JSON object containing the new post_id or a success message.

6. Test Data Setup

  1. Create Author User:
    • wp user create attacker author@example.com --role=author --user_pass=password123
  2. Install/Activate Plugin:
    • Ensure the-plus-addons-for-elementor-page-builder is active at version 6.4.7.
  3. Identify Registered Types:
    • Note down restricted types like page or nxt_builder.

7. Expected Results

  • The AJAX request should return a success status (HTTP 200) and possibly a post ID.
  • A new post with the specified title and the restricted post_type (e.g., page) should appear in the database as a draft.
  • The user (Author) should successfully create this even though they lack the edit_pages capability.

8. Verification Steps

  1. Check via WP-CLI:
    • wp post list --post_type=page --post_status=draft --fields=ID,post_title,post_author
  2. Check Author Ownership:
    • Verify the post_author matches the ID of the Author user created in step 6.
  3. Attempt Without Nonce:
    • Verify that omitting the security parameter or using an invalid one fails (confirming the nonce is the only barrier).

9. Alternative Approaches

  • Target nxt_builder: This is the internal post type for The Plus Addons templates. Creating arbitrary templates can lead to further exploitation if the Author can then inject content into those templates.
  • Check for other parameters: See if post_status is also user-controlled, potentially allowing the creation of published posts directly.
  • Nonce via Admin Dashboard: If the Author has access to the WP Admin dashboard, the nonce is likely available in the source of /wp-admin/index.php or within the Elementor editor interface. Use browser_navigate("/wp-admin/") then search the page source for "nonce" or "security".
Research Findings
Static analysis — not yet PoC-verified

Summary

The The Plus Addons for Elementor plugin (<= 6.4.7) incorrectly authorizes users when creating new content via the tpae_create_page() AJAX handler. By only checking for the generic edit_posts capability and allowing a user-controlled post_type parameter, the plugin enables Author-level users to create draft posts of restricted types like 'page' or 'nxt_builder'.

Vulnerable Code

// Inferred from plugin version 6.4.7 AJAX handler logic
public function tpae_create_page() {
    check_ajax_referer( 'theplus-addons', 'security' );

    // Vulnerability: Only checks generic edit_posts permission
    if ( ! current_user_can( 'edit_posts' ) ) {
        wp_send_json_error( array( 'message' => 'Insufficient permissions' ) );
    }

    $post_title = isset( $_POST['post_title'] ) ? sanitize_text_field( $_POST['post_title'] ) : 'Untitled';
    $post_type  = isset( $_POST['post_type'] ) ? sanitize_text_field( $_POST['post_type'] ) : 'post';

    $new_post = array(
        'post_title'  => $post_title,
        'post_content' => '',
        'post_status'  => 'draft',
        'post_type'    => $post_type, // Sink: Directly controlled post type
    );

    $post_id = wp_insert_post( $new_post );
    // ... returns success
}

Security Fix

--- a/modules/theplus-addons/includes/ajax-handler.php
+++ b/modules/theplus-addons/includes/ajax-handler.php
@@ -5,9 +5,14 @@
     check_ajax_referer( 'theplus-addons', 'security' );
 
-    if ( ! current_user_can( 'edit_posts' ) ) {
+    $post_type = isset( $_POST['post_type'] ) ? sanitize_text_field( $_POST['post_type'] ) : 'post';
+    $post_type_obj = get_post_type_object( $post_type );
+
+    if ( ! $post_type_obj || ! current_user_can( $post_type_obj->cap->create_posts ) ) {
         wp_send_json_error( array( 'message' => 'Insufficient permissions' ) );
     }
 
     $post_title = isset( $_POST['post_title'] ) ? sanitize_text_field( $_POST['post_title'] ) : 'Untitled';
 
     $new_post = array(
         'post_title'  => $post_title,
         'post_content' => '',
         'post_status'  => 'draft',
-        'post_type'    => $post_type,
+        'post_type'    => $post_type,

Exploit Outline

1. Authenticate as a user with the Author role (or any role possessing the 'edit_posts' capability). 2. Access a page where The Plus Addons or Elementor is active to extract the 'security' nonce (typically found in localized JS variables like 'plus_ajax_data'). 3. Construct a POST request to /wp-admin/admin-ajax.php with the following parameters: - action: tpae_create_page - security: [EXTRACTED_NONCE] - post_title: Malicious Draft - post_type: page (or 'nxt_builder' to target template builder types) 4. Submit the request and verify that a new draft post of the requested type (which requires higher capabilities like 'edit_pages') is created in the WordPress database.

Check if your site is affected.

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