CVE-2026-56009

Bricksable for Bricks Builder <= 1.6.83 - Authenticated (Author+) Stored Cross-Site Scripting

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

Description

The Bricksable for Bricks Builder plugin for WordPress is vulnerable to Stored Cross-Site Scripting in versions up to, and including, 1.6.83 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with author-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:L/PR:L/UI:N/S:C/C:L/I:L/A:N
Attack Vector
Network
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Changed
Low
Confidentiality
Low
Integrity
None
Availability

Technical Details

Affected versions<=1.6.83
PublishedJune 18, 2026
Last updatedJune 23, 2026
Affected pluginbricksable

What Changed in the Fix

Changes introduced in v1.6.84

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

# Research Plan: CVE-2026-56009 - Bricksable for Bricks Builder Stored XSS ## 1. Vulnerability Summary The **Bricksable for Bricks Builder** plugin (<= 1.6.83) is vulnerable to **Authenticated Stored Cross-Site Scripting (XSS)**. The plugin registers several custom elements for the Bricks Page Buil…

Show full research plan

Research Plan: CVE-2026-56009 - Bricksable for Bricks Builder Stored XSS

1. Vulnerability Summary

The Bricksable for Bricks Builder plugin (<= 1.6.83) is vulnerable to Authenticated Stored Cross-Site Scripting (XSS). The plugin registers several custom elements for the Bricks Page Builder. These elements (e.g., Multi Heading, Icon List, Card, Back To Top) define various input controls (text, textarea, etc.) in their set_controls() methods.

The vulnerability exists because the plugin fails to sanitize these inputs when they are saved via the Bricks Builder and, more importantly, fails to escape the values when they are rendered in the render() method of the element classes. An attacker with Author level access or higher can use the Bricks Builder to insert a Bricksable element and inject malicious JavaScript into one of the element's settings. This script is then stored in the post's metadata and executes in the context of any user (including Administrators) who views the affected page or opens it in the builder.

2. Attack Vector Analysis

  • Target Endpoint: WordPress AJAX handler admin-ajax.php.
  • Action: bricks_save_post (The standard Bricks Builder save action).
  • Vulnerable Parameters: The elements JSON object within the POST body, specifically within the settings of Bricksable elements.
  • Authentication: Required. Role: Author or higher (any role capable of using the Bricks Builder to edit a post).
  • Preconditions:
    • Bricks Builder plugin must be active.
    • Bricksable for Bricks Builder plugin must be active.
    • The attacker must have permissions to edit a post/page using the Bricks Builder.

3. Code Flow

  1. Definition: Elements like Bricksable_Multi_Heading (in includes/elements/multi-heading/element-multi-heading.php) register controls. For example, the multi_heading_item repeater contains a text field:
    'text' => array(
        'type'           => 'text',
        'hasDynamicData' => 'text',
    ),
    
  2. Storage: When a user saves a page in Bricks, the element's settings (including the text field) are sent via the bricks_save_post AJAX action and stored as JSON in the _bricks_page_content post meta.
  3. Rendering (The Sink): When the page is viewed, Bricks calls the render() method of the element class. Although the render() methods are truncated in the provided source, the vulnerability description confirms that these settings are output without proper escaping (e.g., using esc_html() or wp_kses()).
  4. Execution: The stored script is rendered directly into the HTML of the page and executed by the victim's browser.

4. Nonce Acquisition Strategy

To exploit bricks_save_post, a valid bricks-nonce is required. This nonce is tied to the Bricks Builder session.

  1. Setup: The PoC agent should create a post and ensure it is "Bricks-enabled".
  2. Navigate: Use the browser_navigate tool to go to the Bricks Builder interface for that post:
    http://<wp-url>/wp-admin/post.php?post=<POST_ID>&bricks=run
  3. Extract: Use the browser_eval tool to extract the nonce and current page data from the global bricksData object:
    // The nonce is typically stored here
    const nonce = window.bricksData?.nonce;
    // We also need the current elements structure to ensure a valid save request
    const pageData = window.bricksData?.pageData;
    return { nonce, pageData };
    

5. Exploitation Strategy

The goal is to update a post's content with a malicious ba-multi-heading element.

Step-by-Step Plan:

  1. Login: Authenticate as an Author user.
  2. Find Post: Identify a post ID owned by the Author or create a new one.
  3. Get Nonce: Navigate to the Bricks Builder page for that ID and extract bricksData.nonce.
  4. Construct Payload: Create a JSON structure for a ba-multi-heading element where the text field contains the XSS payload.
    [
      {
        "name": "ba-multi-heading",
        "settings": {
          "multi_heading_item": [
            {
              "text": "Normal Title <script>alert(document.domain)</script>"
            }
          ]
        }
      }
    ]
    
  5. Execute Injection: Send a POST request to admin-ajax.php.
    • URL: http://<wp-url>/wp-admin/admin-ajax.php
    • Content-Type: application/x-www-form-urlencoded
    • Body:
      action=bricks_save_post
      postId=<POST_ID>
      nonce=<EXTRACTED_NONCE>
      elements=<URL_ENCODED_JSON_PAYLOAD>
      
  6. Verify: Navigate to the frontend URL of the post and check if the alert triggers.

6. Test Data Setup

  1. User: Create a user with the author role.
  2. Post: Create a post (e.g., ID 123) and set its post_status to publish.
  3. Bricks Initialization: Ensure the post is set to use Bricks. This can be done by editing it once in the builder or setting post meta _bricks_editor_mode to true.

7. Expected Results

  • The bricks_save_post request should return a success status (usually {"success": true}).
  • When viewing the post frontend, the HTML source should contain the raw <script>alert(document.domain)</script> tag within the ba-multi-heading element container.
  • The browser should execute the script.

8. Verification Steps

  1. HTTP Verification: Observe the response from the frontend request to ensure the payload is present in the HTML.
  2. Database Verification (CLI):
    wp post meta get <POST_ID> _bricks_page_content
    
    Check if the JSON in the metadata contains the injected script.

9. Alternative Approaches

If Multi Heading is patched or difficult to target, try other Bricksable elements identified in the source:

  • Icon List (ba-icon-list): Inject into items -> title.
  • Card (ba-card): Inject into the badge control.
  • Content Toggle (ba-content-toggle): Inject into contentToggleItem -> label or content.
  • Back To Top (ba-back-to-top): Inject into the text control.

The exploitation mechanism (Bricks AJAX save) remains the same for all these elements.

Research Findings
Static analysis — not yet PoC-verified

Summary

The Bricksable for Bricks Builder plugin for WordPress is vulnerable to Authenticated Stored Cross-Site Scripting (XSS) due to a lack of output escaping in multiple element rendering methods. An attacker with Author-level permissions or higher can inject malicious scripts into element settings like "Multi Heading," "Card," or "Icon List," which then execute in the context of any user viewing the page or editing it in the builder.

Vulnerable Code

// includes/elements/back-to-top/element-back-to-top.php line 518
if ( isset( $settings['text'] ) ) {
    $output .= "<span {$this->render_attributes( 'text' )}>";
    $output .= $settings['text'];
    $output .= '</span>';
}

---

// includes/elements/multi-heading/element-multi-heading.php line 337
// Heading.
if ( isset( $item['use_background_text_mask'] ) ) {
    $output .= '<' . $this->render_attributes( "multi-heading-item-$index" ) . '><' . $this->render_attributes( "multi-heading-item-text-mask-$index" ) . '>' . $item['text'] . '</span></span>';
} else {
    $output .= '<' . $this->render_attributes( "multi-heading-item-$index" ) . '>' . $item['text'] . '</span>';
}

---

// includes/elements/icon-list/element-icon-list.php line 1029
if ( isset( $list_item['link'] ) ) {
    $this->set_link_attributes( "a-$index", $list_item['link'] );
    $output .= '<a ' . $this->render_attributes( "a-$index" ) . '><' . $this->render_attributes( "title-$index" ) . '>' . $list_item['title'] . '</' . $title_tag . '></a>';
} else {
    $output .= '<' . $this->render_attributes( "title-$index" ) . '>' . $list_item['title'] . '</' . $title_tag . '>';
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/bricksable/1.6.83/includes/elements/back-to-top/element-back-to-top.php /home/deploy/wp-safety.org/data/plugin-versions/bricksable/1.6.84/includes/elements/back-to-top/element-back-to-top.php
--- /home/deploy/wp-safety.org/data/plugin-versions/bricksable/1.6.83/includes/elements/back-to-top/element-back-to-top.php	2026-03-03 08:08:26.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/bricksable/1.6.84/includes/elements/back-to-top/element-back-to-top.php	2026-06-12 12:29:04.000000000 +0000
@@ -515,7 +515,7 @@
 			$this->set_attribute( 'text', 'class', 'ba-back-to-top-text' );
 			if ( isset( $settings['text'] ) ) {
 				$output .= "<span {$this->render_attributes( 'text' )}>";
-				$output .= $settings['text'];
+				$output .= esc_html( $settings['text'] );
 				$output .= '</span>';
 			}
 		} elseif ( method_exists( '\Bricks\Frontend', 'render_children' ) ) {

Exploit Outline

To exploit this vulnerability, an authenticated user with Author-level access (capable of using the Bricks Builder) needs to perform the following steps: 1. Login and navigate to the Bricks Builder editor for a post the user is authorized to edit. 2. Obtain the valid 'bricks-nonce' by inspecting the global 'bricksData' object in the browser console. 3. Construct a malicious JSON payload representing a Bricksable element (e.g., 'ba-multi-heading') where a text field like 'text' contains a Cross-Site Scripting payload such as <script>alert(document.domain)</script>. 4. Send an AJAX POST request to 'wp-admin/admin-ajax.php' with the action set to 'bricks_save_post', providing the 'postId', the 'nonce', and the 'elements' JSON payload. 5. Once the post is saved, any user who views the post on the frontend will trigger the execution of the injected script because the plugin renders the stored setting without proper HTML escaping.

Check if your site is affected.

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