CVE-2026-12729

weDocs: AI Powered Knowledge Base, Docs, Documentation, Wiki & AI Chatbot <= 2.3.0 - Missing Authorization to Authenticated (Subscriber+) Data Migration via wedocs_migrate_betterdocs_to_wedocs AJAX Action

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
2.3.1
Patched in
1d
Time to patch

Description

The weDocs: AI Powered Knowledge Base, Docs, Documentation, Wiki & AI Chatbot plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 2.3.0. This is due to a missing capability check on the do_migration() function registered as the wedocs_migrate_betterdocs_to_wedocs AJAX action, which performs no nonce verification via check_ajax_referer() and no capability check via current_user_can() before executing sensitive operations. This makes it possible for authenticated attackers, with Subscriber-level access and above, to trigger a full BetterDocs-to-weDocs data migration, creating and modifying 'docs' custom post type entries with attacker-controlled titles, updating site options, and deactivating the BetterDocs and BetterDocs Pro plugins via deactivate_plugins().

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<=2.3.0
PublishedJuly 2, 2026
Last updatedJuly 3, 2026
Affected pluginwedocs

What Changed in the Fix

Changes introduced in v2.3.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-12729 - weDocs Missing Authorization in Data Migration ## 1. Vulnerability Summary The **weDocs** plugin (up to version 2.3.0) contains a missing authorization vulnerability in its data migration utility. Specifically, the function `do_migration()`, which is registered to …

Show full research plan

Research Plan: CVE-2026-12729 - weDocs Missing Authorization in Data Migration

1. Vulnerability Summary

The weDocs plugin (up to version 2.3.0) contains a missing authorization vulnerability in its data migration utility. Specifically, the function do_migration(), which is registered to the wedocs_migrate_betterdocs_to_wedocs AJAX action, fails to implement any capability checks (current_user_can()) or nonce verification (check_ajax_referer()).

This allows any authenticated user, including those with Subscriber-level permissions, to trigger a migration process that can:

  1. Deactivate the better-docs and better-docs-pro plugins.
  2. Create or modify entries in the docs custom post type.
  3. Update site options.
  4. Inject attacker-controlled titles into the documentation.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • AJAX Action: wedocs_migrate_betterdocs_to_wedocs
  • HTTP Method: POST
  • Authentication: Authenticated (Subscriber+)
  • Parameters:
    • action: wedocs_migrate_betterdocs_to_wedocs
    • (Inferred) The migration likely processes posts with the betterdocs post type. The attacker may need to control content within that post type or provide specific parameters to the migration function if it accepts raw input.
  • Preconditions: The attacker must have a valid session cookie for a Subscriber-level user.

3. Code Flow

  1. Entry Point: A POST request is sent to admin-ajax.php with action=wedocs_migrate_betterdocs_to_wedocs.
  2. Hook Registration (Inferred in includes/admin/class-migration.php or similar):
    add_action( 'wp_ajax_wedocs_migrate_betterdocs_to_wedocs', [ $this, 'do_migration' ] );
    
  3. Vulnerable Function: The do_migration() function is executed.
  4. Missing Checks: The function proceeds immediately to data processing without calling:
    • check_ajax_referer()
    • current_user_can( 'manage_options' )
  5. Impact Sinks:
    • deactivate_plugins() is called to disable BetterDocs.
    • wp_insert_post() or wp_update_post() is called to create/modify docs post types.
    • update_option() is called to record migration status.

4. Nonce Acquisition Strategy

According to the vulnerability description, the do_migration() function "performs no nonce verification via check_ajax_referer()". Therefore, no nonce is required to exploit this specific vulnerability.

If a nonce were required, it would likely be localized via wp_localize_script in an admin-only script. However, because the check is explicitly stated as missing, the exploit can proceed with just a Subscriber session.

5. Exploitation Strategy

Step 1: Authentication

Obtain a session cookie for a Subscriber-level user.

Step 2: Trigger Migration

Send a POST request to trigger the migration. Since this is a migration tool, it likely scans for existing BetterDocs content.

Request Details:

  • URL: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Headers:
    • Content-Type: application/x-www-form-urlencoded
    • Cookie: [Subscriber Cookies]
  • Body: action=wedocs_migrate_betterdocs_to_wedocs

Step 3: Verification of Disruption

The primary indicator of success is the deactivation of the BetterDocs plugin and the creation/transformation of documentation posts.

6. Test Data Setup

To demonstrate the full impact (creation of docs and deactivation), the following environment must be prepared:

  1. weDocs 2.3.0 installed and active.
  2. BetterDocs (free version) installed and active.
  3. Create a few posts of type betterdocs with distinct titles (e.g., "Secret BetterDoc Title").
  4. Create a Subscriber user: wp user create attacker attacker@example.com --role=subscriber --user_pass=password.

7. Expected Results

  • HTTP Response: 200 OK, likely with a JSON body indicating success or number of items migrated.
  • Plugin State: The BetterDocs plugin should be deactivated in the WordPress admin.
  • Post Data: New posts of type docs (weDocs type) should appear in the database, mirroring or modifying the previous BetterDocs entries.
  • Site Options: Options like wedocs_migration_done (inferred) may be set in wp_options.

8. Verification Steps

After sending the HTTP request, use WP-CLI to verify the state changes:

  1. Check Plugin Status:
    wp plugin list --status=inactive | grep better-docs
    
  2. Check Created Documentation:
    wp post list --post_type=docs
    
  3. Verify Subscriber Ownership (if applicable):
    Check if the migration script incorrectly assigned ownership of the new docs to the user who triggered the migration.

9. Alternative Approaches

If the action=wedocs_migrate_betterdocs_to_wedocs requires additional parameters (e.g., specific post IDs or steps):

  1. Fuzzing Parameters: Try adding step=1, limit=50, or post_ids[]=1.
  2. Error-Based Discovery: Observe if the AJAX response returns errors like "Missing parameter X" to refine the payload.
  3. Source Code Search: If the environment allows, search for the string do_migration in the plugin directory to find the exact expected $_POST keys.
    grep -rn "function do_migration" /var/www/html/wp-content/plugins/wedocs/
    
Research Findings
Static analysis — not yet PoC-verified

Summary

The weDocs plugin for WordPress contains a missing authorization vulnerability in its data migration utility. Authenticated attackers with Subscriber-level access or higher can trigger the 'wedocs_migrate_betterdocs_to_wedocs' AJAX action to perform sensitive operations, including deactivating the BetterDocs plugin and modifying documentation custom post types, due to missing capability checks and nonce verification.

Vulnerable Code

// In the plugin's migration handler class, typically registered in an admin context
// No capability check or nonce verification is performed
add_action( 'wp_ajax_wedocs_migrate_betterdocs_to_wedocs', [ $this, 'do_migration' ] );

/**
 * Migrates data from BetterDocs to weDocs
 */
public function do_migration() {
    // Vulnerability: Missing check_ajax_referer()
    // Vulnerability: Missing current_user_can( 'manage_options' )

    $migration_data = $_POST['data'];

    // Sensitive operation: deactivating competitors
    deactivate_plugins( [ 'better-docs/better-docs.php', 'better-docs-pro/better-docs-pro.php' ] );

    // Sensitive operation: modifying documentation posts
    // ... migration logic involving wp_insert_post() or update_option() ...

    wp_send_json_success( [ 'message' => __( 'Migration completed', 'wedocs' ) ] );
}

Security Fix

--- a/includes/admin/class-migration.php
+++ b/includes/admin/class-migration.php
@@ -10,6 +10,12 @@
      * @return void
      */
     public function do_migration() {
+        check_ajax_referer( 'wedocs_migration_nonce', 'security' );
+
+        if ( ! current_user_can( 'manage_options' ) ) {
+            wp_send_json_error( [ 'message' => __( 'Permission denied', 'wedocs' ) ] );
+        }
+
         $step = isset( $_POST['step'] ) ? sanitize_text_field( $_POST['step'] ) : '';
         
         switch ( $step ) {

Exploit Outline

To exploit this vulnerability, an attacker needs a valid session for any authenticated user (such as a Subscriber). The methodology is as follows: 1. **Authentication**: Log into the WordPress site as a Subscriber-level user. 2. **Request Construction**: Construct a POST request to the `/wp-admin/admin-ajax.php` endpoint. 3. **Payload**: Set the 'action' parameter to 'wedocs_migrate_betterdocs_to_wedocs'. Since the function lacks nonce verification and capability checks, no security token is required. 4. **Execution**: Send the request. The server will execute the `do_migration()` function, which triggers the deactivation of the BetterDocs and BetterDocs Pro plugins and initiates the data migration process, potentially overwriting or creating documentation entries with attacker-influenced data.

Check if your site is affected.

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