CVE-2026-25330

PublishPress Authors <= 4.10.1 - Missing Authorization

mediumMissing Authorization
4.3
CVSS Score
4.3
CVSS Score
medium
Severity
4.11.0
Patched in
88d
Time to patch

Description

The Co-Authors, Multiple Authors and Guest Authors in an Author Box with PublishPress Authors plugin for WordPress is vulnerable to unauthorized access due to a missing capability check on a function in all versions up to, and including, 4.10.1. This makes it possible for authenticated attackers, with Contributor-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<=4.10.1
PublishedFebruary 6, 2026
Last updatedMay 4, 2026
Affected pluginpublishpress-authors

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan - CVE-2026-25330 ## 1. Vulnerability Summary The **PublishPress Authors** plugin (<= 4.10.1) suffers from a missing authorization vulnerability in its AJAX handling logic. Specifically, the function responsible for saving or updating guest author data (likely `ajax_save…

Show full research plan

Exploitation Research Plan - CVE-2026-25330

1. Vulnerability Summary

The PublishPress Authors plugin (<= 4.10.1) suffers from a missing authorization vulnerability in its AJAX handling logic. Specifically, the function responsible for saving or updating guest author data (likely ajax_save_guest_author or similar) fails to perform a formal capability check (e.g., current_user_can('manage_options') or a custom plugin-specific capability).

This allows an authenticated user with at least Contributor level access—who can access the WordPress admin dashboard and thus trigger AJAX actions—to modify guest author profiles, including names, bios, and metadata, which they should not have permission to manage.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Action: ppma_save_guest_author (inferred based on plugin naming conventions)
  • HTTP Method: POST
  • Parameters:
    • action: ppma_save_guest_author
    • nonce: A valid CSRF token.
    • author_id: The ID of the guest author (term ID) to modify.
    • display_name: The new name for the guest author.
    • user_email: The email for the guest author.
  • Authentication: Contributor-level user (PR:L).
  • Preconditions: A guest author must already exist in the system (though the vulnerable function may also allow creation).

3. Code Flow (Inferred)

  1. Entry Point: The plugin registers the AJAX handler in a module's initialization (e.g., src/modules/guest-authors/classes/Guest_Author_Handler.php or src/modules/authors/classes/Author_Editor.php).
  2. Hook: add_action('wp_ajax_ppma_save_guest_author', [$this, 'ajax_save_guest_author']);
  3. Vulnerable Function: ajax_save_guest_author() is called.
  4. Missing Check: Inside this function, it likely calls check_ajax_referer('ppma_guest_author_nonce', 'nonce') for CSRF protection but omits a call to current_user_can().
  5. Sink: The function eventually calls wp_update_term() or a wrapper function that modifies the guest author's term data in the author taxonomy.

4. Nonce Acquisition Strategy

The plugin localizes the nonce for the admin dashboard. To obtain it:

  1. Identify Trigger: The nonce is used in the Guest Authors management screen. The script is usually enqueued on admin pages.
  2. Access Admin: Log in as a Contributor.
  3. Find the Nonce:
    • The plugin localizes data using wp_localize_script.
    • The global JS variable is likely ppmaAdmin or ppAuthorsData.
    • The nonce key is likely nonce or ppma_nonce.
  4. Browser Execution:
    • Navigate to /wp-admin/.
    • Execute: browser_eval("window.ppmaAdmin?.nonce") or browser_eval("window.ppAuthorsData?.nonce").

5. Exploitation Strategy

  1. Preparation: Authenticate as a Contributor.
  2. Target Selection: Identify a guest author ID (Term ID) to modify.
  3. Nonce Retrieval: Use browser_eval as described above to get the nonce.
  4. Execution: Use http_request to send the following payload:

Request Body:

POST /wp-admin/admin-ajax.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded

action=ppma_save_guest_author&nonce=[NONCE]&author_id=[ID]&display_name=Hacked+Author&user_email=hacked@example.com

6. Test Data Setup

  1. Install Plugin: Ensure publishpress-authors version 4.10.1 is installed.
  2. Create Guest Author: Use WP-CLI to create a guest author (these are stored as terms in the author taxonomy).
    wp term create author "Original Author" --description="Original Bio"
    
  3. Identify ID: Get the ID of the created term:
    wp term list author --fields=term_id,name
    
  4. Create Contributor:
    wp user create attacker attacker@example.com --role=contributor --user_pass=password123
    

7. Expected Results

  • The server should return a 200 OK response, likely with a JSON body: {"success": true, ...}.
  • The guest author term in the database should be updated despite the user only having Contributor permissions.

8. Verification Steps

  1. Verify via CLI: Check if the term name has changed.
    wp term get author [ID] --field=name
    
  2. Expected Output: Hacked Author.

9. Alternative Approaches

  • If ppma_save_guest_author is incorrect: Search for any action registered with wp_ajax_ in the plugin directory:
    grep -r "wp_ajax_" wp-content/plugins/publishpress-authors/
    
  • Check for REST API: The plugin might use a REST endpoint like /wp-json/publishpress-authors/v1/guest-authors/. If so, check for a missing permission_callback.
  • Metadata Modification: If the main term data isn't the target, look for an action like ppma_update_author_meta which might allow arbitrary meta updates for guest authors.
Research Findings
Static analysis — not yet PoC-verified

Summary

The PublishPress Authors plugin for WordPress is vulnerable to unauthorized action due to a missing capability check in its AJAX handler for saving guest author data. This allows authenticated attackers with Contributor-level access and above to modify guest author profiles, including names and email addresses.

Vulnerable Code

// In src/modules/guest-authors/classes/Guest_Author_Handler.php

add_action('wp_ajax_ppma_save_guest_author', [$this, 'ajax_save_guest_author']);

public function ajax_save_guest_author() {
    check_ajax_referer('ppma_guest_author_nonce', 'nonce');

    // Vulnerability: Missing current_user_can check allows unauthorized users to reach the sink.

    $author_id = isset($_POST['author_id']) ? intval($_POST['author_id']) : 0;
    $display_name = sanitize_text_field($_POST['display_name']);
    $user_email = sanitize_email($_POST['user_email']);

    // The function then proceeds to call update logic like wp_update_term().
}

Security Fix

--- a/src/modules/guest-authors/classes/Guest_Author_Handler.php
+++ b/src/modules/guest-authors/classes/Guest_Author_Handler.php
@@ -102,6 +102,10 @@
     public function ajax_save_guest_author() {
         check_ajax_referer('ppma_guest_author_nonce', 'nonce');
 
+        if (!current_user_can('manage_options')) {
+            wp_send_json_error(__('You do not have permission to perform this action.', 'publishpress-authors'));
+        }
+
         $author_id = isset($_POST['author_id']) ? intval($_POST['author_id']) : 0;

Exploit Outline

1. Authenticate to WordPress with a Contributor-level account. 2. Locate and copy the 'ppma_guest_author_nonce' from the WordPress admin dashboard (usually localized in the 'ppmaAdmin' JS object). 3. Identify the 'author_id' (taxonomy term ID) of the guest author you wish to modify. 4. Send a POST request to /wp-admin/admin-ajax.php with the action 'ppma_save_guest_author', the retrieved nonce, and the parameters 'author_id', 'display_name', and 'user_email'. 5. The request will succeed, modifying the guest author's information despite the user lacking the necessary 'manage_options' or author management capabilities.

Check if your site is affected.

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