CVE-2025-12027

Mesmerize Companion <= 1.6.158 - Missing Authorization Authenticated (Subscriber+) Settings Update

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

Description

The Mesmerize Companion plugin for WordPress is vulnerable to unauthorized access and modification of data due to a missing capability check on the "openPageInCustomizer" and "openPageInDefaultEditor" functions in all versions up to, and including, 1.6.158. This makes it possible for authenticated attackers - with subscriber level access and above, on websites with the Mesmerize theme activated - to mark arbitrary pages as maintainable, wrap their content in custom sections, change page template metadata, and toggle the default editor flag without proper authorization.

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<=1.6.158
PublishedFebruary 18, 2026
Last updatedFebruary 19, 2026
Affected pluginmesmerize-companion
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-12027 - Mesmerize Companion Missing Authorization ## 1. Vulnerability Summary The **Mesmerize Companion** plugin (<= 1.6.158) contains a missing authorization vulnerability in its AJAX handlers. Specifically, the functions `openPageInCustomizer` and `openPageI…

Show full research plan

Exploitation Research Plan: CVE-2025-12027 - Mesmerize Companion Missing Authorization

1. Vulnerability Summary

The Mesmerize Companion plugin (<= 1.6.158) contains a missing authorization vulnerability in its AJAX handlers. Specifically, the functions openPageInCustomizer and openPageInDefaultEditor (likely mapped to AJAX actions) do not perform sufficient capability checks (e.g., current_user_can('edit_pages')). This allows any authenticated user, including those with Subscriber privileges, to modify post metadata and state for arbitrary pages, provided the Mesmerize theme is active.

The impact includes marking pages as "maintainable" by the plugin's builder, changing templates, and toggling the editor mode, which can disrupt site layout or prepare pages for further manipulation.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php
  • Actions (Inferred):
    • mesmerize_open_page_in_customizer (likely maps to openPageInCustomizer)
    • mesmerize_open_page_in_default_editor (likely maps to openPageInDefaultEditor)
  • Parameters:
    • post_id or id: The ID of the target page to modify.
    • _nonce: A WordPress nonce for verification (security by obscurity if not properly restricted).
  • Authentication: Subscriber level (PR:L).
  • Precondition: The Mesmerize theme must be the active theme.

3. Code Flow (Inferred)

  1. Registration: The plugin registers AJAX handlers during init or admin_init.
    • add_action('wp_ajax_mesmerize_open_page_in_customizer', array($this, 'openPageInCustomizer'));
  2. Execution: When the AJAX action is called:
    • The function retrieves the post_id from $_REQUEST.
    • It performs a wp_verify_nonce check.
    • The Vulnerability: It fails to call current_user_can('edit_page', $post_id).
  3. Sink:
    • update_post_meta($post_id, 'mesmerize_managed_page', '1') (inferred meta key).
    • update_post_meta($post_id, '_wp_page_template', ...)
    • Changes the post status or content wrapper to make it compatible with the Mesmerize builder.

4. Nonce Acquisition Strategy

The Mesmerize Companion plugin typically localizes its configuration data for the WordPress admin dashboard or the customizer.

  1. Shortcode/Page Requirement: The plugin's admin scripts load on standard admin pages. Since a Subscriber can access /wp-admin/profile.php, we can extract the nonce from there if the script is enqueued globally for authenticated users.
  2. Identification: Look for wp_localize_script calls in the plugin source (e.g., in src/Companion.php or similar).
    • Likely JS Variable: mesmerize_companion_common or MesmerizeCompanion.
    • Likely Nonce Key: nonce.
  3. Extraction Steps:
    • Log in as a Subscriber.
    • Navigate to /wp-admin/index.php.
    • Execute JS: browser_eval("window.mesmerize_companion_common?.nonce || window.MesmerizeCompanion?.nonce").

5. Exploitation Strategy

We will attempt to mark a high-value page (e.g., the Home page or a "Privacy Policy" page) as "Maintainable" in the Mesmerize Customizer, which triggers metadata changes.

Step 1: Target Identification

  • Find the ID of a page owned by the administrator.

Step 2: Request Construction

  • Action: mesmerize_open_page_in_customizer
  • Method: POST
  • URL: http://<target>/wp-admin/admin-ajax.php
  • Payload:
    action=mesmerize_open_page_in_customizer&id=<TARGET_PAGE_ID>&_nonce=<EXTRACTED_NONCE>
    

Step 3: Execution via http_request

// Example Payload for the automated agent
await http_request({
  url: "http://localhost:8080/wp-admin/admin-ajax.php",
  method: "POST",
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
  body: "action=mesmerize_open_page_in_customizer&id=2&_nonce=a1b2c3d4e5"
});

6. Test Data Setup

  1. Theme: Install and activate the mesmerize theme.
  2. Plugin: Install mesmerize-companion version 1.6.158.
  3. User: Create a user attacker with the subscriber role.
  4. Target Content: Ensure a page with ID 2 (default for "Sample Page") exists and is NOT currently "maintained" by Mesmerize.

7. Expected Results

  • HTTP Response: A success JSON response (e.g., {"success": true}) or a 302 redirect to the Customizer URL.
  • State Change: The target page's metadata will be updated to reflect it is now managed by the Mesmerize Companion.

8. Verification Steps

After the exploit request, verify using wp-cli:

  1. Check Post Meta:
    wp post meta get 2 mesmerize_managed_page
    (Expected: 1)
  2. Check Template:
    wp post meta get 2 _wp_page_template
    (Expected: A template specific to Mesmerize, e.g., templates/full-width-page.php)

9. Alternative Approaches

If mesmerize_open_page_in_customizer is not the exact action name:

  1. Grep for AJAX registration:
    grep -r "wp_ajax_" wp-content/plugins/mesmerize-companion/
  2. Search for function definitions:
    grep -r "function openPageInCustomizer" wp-content/plugins/mesmerize-companion/
  3. Alternative Action: Try mesmerize_open_page_in_default_editor to toggle the editor flag.
    • Payload: action=mesmerize_open_page_in_default_editor&id=<ID>&_nonce=<NONCE>
    • Verification: Check if mesmerize_managed_page meta is deleted or set to 0.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Mesmerize Companion plugin (<= 1.6.158) fails to perform authorization checks in its AJAX handlers `openPageInCustomizer` and `openPageInDefaultEditor`. This allows authenticated attackers with Subscriber-level privileges to modify post metadata and state for arbitrary pages, such as marking them as managed by the plugin's custom builder or changing page templates, provided the Mesmerize theme is active.

Vulnerable Code

// Inferred from Research Plan - likely in src/Companion.php or similar

public function openPageInCustomizer() {
    $post_id = $_REQUEST['id'];
    // Missing capability check like current_user_can('edit_post', $post_id)
    if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'mesmerize_companion_nonce' ) ) {
        return;
    }

    update_post_meta($post_id, 'mesmerize_managed_page', '1');
    // ... (logic to redirect to customizer or return success response)
}

---

public function openPageInDefaultEditor() {
    $post_id = $_REQUEST['id'];
    // Missing capability check like current_user_can('edit_post', $post_id)
    if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'mesmerize_companion_nonce' ) ) {
        return;
    }

    update_post_meta($post_id, 'mesmerize_managed_page', '0');
    // ... (logic to return success response)
}

Security Fix

--- a/src/Companion.php
+++ b/src/Companion.php
@@ -100,6 +100,10 @@
     public function openPageInCustomizer() {
         $post_id = $_REQUEST['id'];
+
+        if ( ! current_user_can( 'edit_post', $post_id ) ) {
+            wp_die( __( 'You do not have permission to edit this post.' ) );
+        }
+
         if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'mesmerize_companion_nonce' ) ) {
             return;
         }
@@ -120,6 +124,10 @@
     public function openPageInDefaultEditor() {
         $post_id = $_REQUEST['id'];
+
+        if ( ! current_user_can( 'edit_post', $post_id ) ) {
+            wp_die( __( 'You do not have permission to edit this post.' ) );
+        }
+
         if ( ! wp_verify_nonce( $_REQUEST['_nonce'], 'mesmerize_companion_nonce' ) ) {
             return;
         }

Exploit Outline

1. Authentication: Log in to the target WordPress site with a Subscriber-level account. 2. Nonce Acquisition: Access a standard admin page (e.g., `/wp-admin/profile.php`) and extract the security nonce from the `mesmerize_companion_common` or `MesmerizeCompanion` JavaScript object localized on the page. 3. Identify Target: Choose a target Page ID (e.g., ID 2 for the default Sample Page). 4. Execute Modification: Send a POST request to `/wp-admin/admin-ajax.php` using the action `mesmerize_open_page_in_customizer` (to enable builder mode) or `mesmerize_open_page_in_default_editor` (to disable it), including the `id` of the target page and the extracted `_nonce`. 5. Verification: Confirm the metadata change by checking the `mesmerize_managed_page` key via the database or observing layout changes on the frontend.

Check if your site is affected.

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