CVE-2026-12430

Blocksy Companion <= 2.1.45 - Authenticated (Editor+) Stored Cross-Site Scripting via 'product_description' Parameter

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

Description

The Blocksy Companion plugin for WordPress is vulnerable to Stored Cross-Site Scripting via admin settings in all versions up to, and including, 2.1.45 due to insufficient input sanitization and output escaping. This makes it possible for authenticated attackers, with editor-level permissions 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<=2.1.45
PublishedJune 18, 2026
Last updatedJune 19, 2026
Affected pluginblocksy-companion

What Changed in the Fix

Changes introduced in v2.1.46

Loading patch diff...

Source Code

WordPress.org SVN
Research Plan
Unverified

This research plan targets **CVE-2026-12430**, a Stored Cross-Site Scripting (XSS) vulnerability in the **Blocksy Companion** plugin. The vulnerability is located in the plugin's settings, specifically within the "White Label" extension's `product_description` parameter. ### 1. Vulnerability Summar…

Show full research plan

This research plan targets CVE-2026-12430, a Stored Cross-Site Scripting (XSS) vulnerability in the Blocksy Companion plugin. The vulnerability is located in the plugin's settings, specifically within the "White Label" extension's product_description parameter.

1. Vulnerability Summary

The Blocksy Companion plugin (<= 2.1.45) fails to adequately sanitize and escape the product_description parameter within its admin settings. While the plugin utilizes wp_kses_post() for some fields, this filter is insufficient to prevent XSS when unfiltered_html is disabled (e.g., for Editors on a Multisite or restricted environments), as it allows tags and attributes (like <a> or style) that can be used to execute JavaScript in specific contexts, or it may be omitted entirely during rendering in the admin dashboard.

2. Attack Vector Analysis

  • Endpoint: /wp-admin/admin-ajax.php?action=customize_save
  • Method: POST
  • Vulnerable Parameter: customized (JSON payload)
  • Setting ID: blocksy_ext_white_label_settings[product_description] (inferred from blocksy-companion.php line 51 and CVE description)
  • Authentication: Authenticated, Editor or higher (requires edit_theme_options capability).
  • Precondition: The "White Label" extension must be active and the site must have unfiltered_html disabled for the attacker's role.

3. Code Flow

  1. Persistence: An Editor uses the WordPress Customizer or the Blocksy Dashboard to update the "Product Description". The request is sent to admin-ajax.php with the customize_save action.
  2. Storage: The values are processed by the Customizer API and stored in the wp_options table under the option name blocksy_ext_white_label_settings.
  3. Retrieval: In blocksy-companion.php, the settings are retrieved:
    // line 51
    $blocksy_wl_settings = apply_filters( 'blocksy:ext:white-label:settings', get_option( 'blocksy_ext_white_label_settings', [] ) );
    
  4. Sink: The product_description is rendered in the Blocksy Dashboard (/wp-admin/admin.php?page=ct-dashboard) to identify the plugin. If the output is rendered using a raw echo or insufficient escaping, the XSS payload executes in the context of any user (including Administrators) viewing the dashboard.

4. Nonce Acquisition Strategy

This exploit requires the customize_save nonce. Since the attacker is authenticated as an Editor, they can extract this from the Customizer interface.

  1. Navigate to the WordPress Customizer: /wp-admin/customize.php.
  2. The nonce is stored in the global JavaScript object _wpCustomizeSettings.
  3. Use the browser_eval tool to extract the nonce:
    • Variable: window._wpCustomizeSettings.nonce.save

5. Exploitation Strategy

  1. Preparation: Log in as an Editor. Ensure the "White Label" extension is active (see Test Data Setup).
  2. Nonce Extraction: Navigate to /wp-admin/customize.php and run browser_eval("window._wpCustomizeSettings.nonce.save").
  3. Craft Payload: Create a JSON object for the customized parameter.
    {
      "blocksy_ext_white_label_settings": {
        "product_description": "Custom Description<script>alert(document.domain)</script>"
      }
    }
    
  4. Execute Injection: Send the following request via the http_request tool:
    • URL: [TARGET_URL]/wp-admin/admin-ajax.php?action=customize_save
    • Method: POST
    • Headers: Content-Type: application/x-www-form-urlencoded
    • Body:
      wp_customize=on&
      nonce=[EXTRACTED_NONCE]&
      
Research Findings
Static analysis — not yet PoC-verified

Summary

The Blocksy Companion plugin for WordPress is vulnerable to Stored Cross-Site Scripting via the 'product_description' parameter in the 'White Label' extension settings. Authenticated attackers with Editor-level permissions and above can inject arbitrary web scripts into this field, which then execute when an administrator accesses the Blocksy Dashboard.

Vulnerable Code

// blocksy-companion.php line 51
if ( in_array( 'white-label', $blocksy_active_extensions ) && ($blocksy_fs_instance->is_plan( 'agency' ) || $blocksy_fs_instance->is_plan( 'agency_v2' )) ) {
    $blocksy_wl_settings = apply_filters( 'blocksy:ext:white-label:settings', get_option( 'blocksy_ext_white_label_settings', [] ) );
    if ( $blocksy_wl_settings && isset( $blocksy_wl_settings['hide_billing_account'] ) && $blocksy_wl_settings['hide_billing_account'] && !is_multisite() ) {
        $blocksy_has_account = false;
    }
}

Security Fix

diff -ru /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.45/blocksy-companion.php /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.46/blocksy-companion.php
--- /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.45/blocksy-companion.php	2026-06-11 17:00:34.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.46/blocksy-companion.php	2026-06-17 15:39:34.000000000 +0000
@@ -3,14 +3,14 @@
 /*
 Plugin Name: Blocksy Companion
 Description: This plugin is the companion for the Blocksy theme, it runs and adds its enhacements only if the Blocksy theme is installed and active.
-Version: 2.1.45
+Version: 2.1.46
 Author: CreativeThemes
 Author URI: https://creativethemes.com
 Text Domain: blocksy-companion
 Domain Path: /languages/
 License: GPLv2 or later
 License URI: http://www.gnu.org/licenses/gpl-2.0.html
-Requires at least: 6.5
+Requires at least: 6.7
 Requires PHP: 7.0
 */
 if ( !defined( 'ABSPATH' ) ) {
diff -ru /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.45/framework/extensions/cookies-consent/helpers.php /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.46/framework/extensions/cookies-consent/helpers.php
--- /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.45/framework/extensions/cookies-consent/helpers.php	2026-03-26 17:22:18.000000000 +0000
+++ /home/deploy/wp-safety.org/data/plugin-versions/blocksy-companion/2.1.46/framework/extensions/cookies-consent/helpers.php	2026-06-17 15:39:34.000000000 +0000
@@ -45,13 +45,17 @@
 	return ob_get_clean();
 }
 
-function blocksy_ext_cookies_checkbox($prefix = '') {
+function blocksy_ext_cookies_checkbox($prefix = '', $unique_suffix = '') {
 	ob_start();
 
 	if (! empty($prefix)) {
 		$prefix = '_' . $prefix;
 	}
 
+	$input_id = ! empty($unique_suffix)
+		? 'gdprconfirm_newsletter-' . sanitize_html_class($unique_suffix)
+		: 'gdprconfirm' . $prefix;
+
 	$message = blocksy_companion_theme_functions()->blocksy_get_theme_mod(
 		'forms_cookie_consent_content',
 		blocksy_companion_safe_sprintf(
@@ -70,14 +74,14 @@
 			blocksy_html_tag_e(
 				'input',
 				[
-					'id' => 'gdprconfirm' . $prefix,
+					'id' => $input_id,
 					'class' => 'ct-checkbox',
 					'name' => 'gdprconfirm',
 					'type' => 'checkbox',
 					'required' => true
 				]
 			);
-		?><label for="gdprconfirm<?php echo esc_attr($prefix) ?>"><?php echo wp_kses_post($message) ?></label>
+		?><label for="<?php echo esc_attr($input_id) ?>"><?php echo wp_kses_post($message) ?></label>
 	</p>

Exploit Outline

The exploit is achieved by an authenticated user with Editor or higher permissions (specifically those with 'edit_theme_options' capabilities). 1. The attacker navigates to the WordPress Customizer ('/wp-admin/customize.php') and extracts the 'customize_save' nonce from the 'window._wpCustomizeSettings.nonce.save' object. 2. A POST request is sent to '/wp-admin/admin-ajax.php?action=customize_save' with 'wp_customize=on', the extracted nonce, and a 'customized' JSON payload. 3. The payload contains an entry for 'blocksy_ext_white_label_settings' with a 'product_description' attribute containing a malicious script, such as '<script>alert(document.domain)</script>'. 4. The script is stored in the site's options and will execute in the session of any administrator who views the plugin's dashboard.

Check if your site is affected.

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