CVE-2025-14866

Melapress Role Editor <= 1.1.1 - Improper Authorization to Authenticated (Subscriber+) Privilege Escalation via Secondary Role Assignment

highIncorrect Authorization
8.8
CVSS Score
8.8
CVSS Score
high
Severity
1.2.0
Patched in
2d
Time to patch

Description

The Melapress Role Editor plugin for WordPress is vulnerable to Privilege Escalation in all versions up to, and including, 1.1.1. This is due to a misconfigured capability check on the 'save_secondary_roles_field' function. This makes it possible for authenticated attackers, with Subscriber-level access and above, to assign themselves additional roles including Administrator.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=1.1.1
PublishedJanuary 22, 2026
Last updatedJanuary 23, 2026
Affected pluginmelapress-role-editor

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan outlines the steps required to analyze and exploit **CVE-2025-14866**, a privilege escalation vulnerability in the **Melapress Role Editor** plugin. --- ### 1. Vulnerability Summary The **Melapress Role Editor** plugin (<= 1.1.1) is vulnerable to privilege escalation because it …

Show full research plan

This research plan outlines the steps required to analyze and exploit CVE-2025-14866, a privilege escalation vulnerability in the Melapress Role Editor plugin.


1. Vulnerability Summary

The Melapress Role Editor plugin (<= 1.1.1) is vulnerable to privilege escalation because it fails to properly restrict which roles a user can assign as "secondary roles" during a profile update. The function save_secondary_roles_field (inferred name from vulnerability description) is likely hooked to profile_update or personal_options_update. While it may contain a capability check like current_user_can( 'edit_user', $user_id ), this check passes when a Subscriber edits their own profile. The logic fails to verify if the user has the promote_users capability or if the roles being assigned exceed the user's current authority, allowing a Subscriber to assign themselves the administrator role as a secondary role.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/profile.php
  • Action: POST request to update the user profile.
  • Vulnerable Hook: Likely personal_options_update and edit_user_profile_update.
  • Payload Parameter: Inferred as mre_secondary_roles[] or melapress_role_editor_secondary_roles[].
  • Authentication: Authenticated (Subscriber or higher).
  • Precondition: The plugin must be active. The attacker needs a valid login for a Subscriber account.

3. Code Flow (Inferred)

  1. Entry Point: The user submits the profile update form at /wp-admin/profile.php.
  2. Hook Trigger: WordPress triggers the personal_options_update hook for the current user.
  3. Plugin Callback: Melapress Role Editor's callback (e.g., Melapress\RoleEditor\Admin\User_Profile::save_secondary_roles_field) is executed.
  4. Inadequate Check:
    // Potential Vulnerable Logic
    public function save_secondary_roles_field( $user_id ) {
        if ( ! current_user_can( 'edit_user', $user_id ) ) {
            return;
        }
        if ( isset( $_POST['mre_secondary_roles'] ) ) {
            $roles = (array) $_POST['mre_secondary_roles'];
            // VULNERABILITY: No check if the current user is allowed 
            // to assign these specific roles (like 'administrator').
            update_user_meta( $user_id, '_mre_secondary_roles', $roles );
        }
    }
    
  5. Sink: update_user_meta or the plugin's internal role management logic persists the high-privilege secondary role to the database.

4. Nonce Acquisition Strategy

The profile update form in WordPress is protected by the standard core nonce.

  1. Login: Use the http_request tool to log in as a Subscriber.
  2. Navigate: Navigate to /wp-admin/profile.php using browser_navigate.
  3. Extract Nonce: Use browser_eval to extract the _wpnonce from the form.
    • browser_eval("document.querySelector('#_wpnonce').value")
  4. Identify Field Name: Use browser_eval to inspect the HTML and find the exact name of the secondary roles input field. Look for checkboxes or a multi-select field related to "Secondary Roles".
    • Search pattern: document.querySelectorAll('input[name*="role"]') or document.querySelectorAll('select[name*="role"]').

5. Exploitation Strategy

  1. Identify Target User ID: The attacker targets their own ID (usually available in the URL of profile.php).
  2. Identify the Role Parameter: Based on the UI inspection, determine if the plugin uses a specific parameter name. We will assume mre_secondary_roles[] for this plan.
  3. Craft the Request: Send a POST request to /wp-admin/profile.php mimicking a profile update.
    • URL: https://<target>/wp-admin/profile.php
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body Parameters:
      • _wpnonce: [Extracted Nonce]
      • _wp_http_referer: /wp-admin/profile.php
      • from: profile
      • checkuser_id: [User ID]
      • user_id: [User ID]
      • mre_secondary_roles[]: administrator
      • submit: Update Profile (or equivalent)
      • Note: Include other mandatory profile fields (nickname, email) to ensure the request is processed by core.

6. Test Data Setup

  1. Plugin Installation: Install Melapress Role Editor v1.1.1.
  2. User Creation:
    • wp user create attacker attacker@example.com --role=subscriber --user_pass=password123
  3. Environment Check: Ensure the plugin settings allow secondary roles (usually enabled by default upon installation).

7. Expected Results

  • The HTTP response should be a 302 Redirect back to profile.php?updated=1.
  • The attacker user, previously a Subscriber, should now possess the capabilities of an Administrator via the secondary role assignment.

8. Verification Steps

  1. Database Check (WP-CLI):
    • wp user get attacker --fields=roles
    • Check user meta for secondary roles: wp user meta get attacker _mre_secondary_roles (or the specific meta key used by the plugin).
  2. Functional Check:
    • Use the attacker session to attempt an administrator-only action, such as listing all users: wp user list.
    • Navigate to /wp-admin/plugins.php in the browser session to see if the menu is now accessible.

9. Alternative Approaches

  • AJAX Endpoint: Check if the plugin registers a wp_ajax_ action for saving roles that might bypass the standard profile page entirely. Search for wp_ajax_ in the plugin code.
  • Parameter Variation: If mre_secondary_roles[] fails, try different naming conventions found in the source: melapress_role_editor_secondary_roles, secondary_roles, or mre_roles.
  • Profile Update via user-edit.php: If profile.php is restricted, try targeting another user's profile if the capability check is even weaker (though the CVE suggests Escalation, which usually implies self-escalation).
Research Findings
Static analysis — not yet PoC-verified

Summary

The Melapress Role Editor plugin for WordPress is vulnerable to privilege escalation because it fails to properly restrict which roles a user can assign as secondary roles during a profile update. An authenticated attacker with Subscriber-level access can exploit a misconfigured capability check to assign themselves the Administrator role via their own profile settings.

Vulnerable Code

// Inferred from plugin structure and vulnerability description
// Path: classes/Admin/UserProfile.php or similar

public function save_secondary_roles_field( $user_id ) {
    // VULNERABILITY: 'edit_user' capability is granted to users editing their own profile,
    // allowing Subscribers to pass this check when updating themselves.
    if ( ! current_user_can( 'edit_user', $user_id ) ) {
        return;
    }

    if ( isset( $_POST['mre_secondary_roles'] ) ) {
        $roles = (array) $_POST['mre_secondary_roles'];
        // No further check to verify if the current user has 'promote_users' 
        // or authority to grant the specific roles in $roles.
        update_user_meta( $user_id, '_mre_secondary_roles', $roles );
    }
}

Security Fix

--- classes/Admin/UserProfile.php
+++ classes/Admin/UserProfile.php
@@ -10,7 +10,7 @@
-    if ( ! current_user_can( 'edit_user', $user_id ) ) {
+    if ( ! current_user_can( 'promote_users' ) ) {
         return;
     }
 
     if ( isset( $_POST['mre_secondary_roles'] ) ) {

Exploit Outline

The exploit targets the WordPress profile update process. 1. Authenticate to the target WordPress site as a Subscriber-level user. 2. Navigate to the user profile page (/wp-admin/profile.php) and extract the security nonce (_wpnonce) from the HTML form. 3. Identify the input name used by the plugin for secondary roles (inferred as 'mre_secondary_roles[]'). 4. Craft a POST request to /wp-admin/profile.php containing the standard profile update fields (user_id, email, etc.) and include the 'mre_secondary_roles[]' parameter set to 'administrator'. 5. The plugin's save_secondary_roles_field function incorrectly validates the request using 'edit_user', which is true for self-edits, and saves the secondary 'administrator' role to the user's metadata. 6. The attacker effectively gains administrative privileges on the next request or login session.

Check if your site is affected.

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