Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* Fix - Improved security of permission checks for MCP-based form and entry access.
* Fix - Improved security of admin notification message rendering.
* Fix - Improved security of WYSIWYG field values shown in the Entries list.
* Fix - Improved security of file deletion when processing uploaded file submissions.

= 3.6.1 - 07-09-2026
* Fix - Date/Time dropdown fields showed today's date instead of the saved value, and Smart Phone fields lost their country code, when editing an existing entry.
Expand Down
44 changes: 19 additions & 25 deletions includes/abstracts/class-evf-form-fields-upload.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ abstract class EVF_Form_Fields_Upload extends EVF_Form_Fields {
*/
protected $protected_files = array( 'index.html', 'index.php', '.htaccess', '.htpasswd' );

/**
* Real paths of files moved into the form uploads folder during this request.
*
* @var array
*/
protected $request_files = array();

/**
* Hook in tabs.
*/
Expand Down Expand Up @@ -1376,6 +1383,12 @@ static function ( $file ) {
$this->create_dir( dirname( $file['path'] ) );
@rename( $file['tmp_path'], $file['path'] ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
$this->set_file_fs_permissions( $file['path'] );

$real_path = realpath( $file['path'] );

if ( false !== $real_path ) {
$this->request_files[] = wp_normalize_path( $real_path );
}
}

$data[] = $this->generate_file_data( $file );
Expand Down Expand Up @@ -1659,31 +1672,12 @@ public function send_csv_file_as_email_attachment( $attachment, $entry, $form_da
public function remove_csv_file_after_email_send( $attachment, $entry, $form_data, $context, $connection_id, $entry_id ) {

if ( isset( $form_data['settings']['disabled_entries'] ) && '1' === $form_data['settings']['disabled_entries'] ) {
if ( ! empty( $entry ) && is_array( $entry ) ) {
foreach ( $entry as $meta_key => $meta_value ) {
if ( empty( $meta_value ) ) {
continue;
}

if ( preg_match( '/signature_/', $meta_key ) && file_exists( $meta_value ) ) {
unlink( $meta_value );
}

if ( isset( $meta_value['type'] ) && ( 'file-upload' === $meta_value['type'] && ! empty( $meta_value['value_raw'] ) || 'image-upload' === $meta_value['type'] && isset( $meta_value['value_raw'] ) ) ) {

foreach ( $meta_value['value_raw'] as $file_data ) {
if ( isset( $file_data['value'] ) ) {
$file_url = $file_data['value'];

$uploaded_file = ABSPATH . preg_replace( '/.*wp-content/', 'wp-content', wp_parse_url( $file_url, PHP_URL_PATH ) );
if ( file_exists( $uploaded_file ) ) {
unlink( $uploaded_file );
}
}
}
}
}
// File URLs in the entry can come from the request (old_files), so only delete what this request uploaded.
foreach ( $this->request_files as $file_path ) {
wp_delete_file( $file_path );
}

$this->request_files = array();
}

if ( ! $entry_id ) {
Expand Down Expand Up @@ -1756,7 +1750,7 @@ public function attach_entry_files_upload( $entry ) {
}

if ( preg_match( '/signature_/', $meta_key ) ) {
if ( file_exists( $meta_value ) ) {
if ( is_string( $meta_value ) && file_exists( $meta_value ) ) {
$entry_files[] = $meta_value;
}
} elseif ( isset( $meta_value['type'] ) && ( 'file-upload' === $meta_value['type'] && ! empty( $meta_value['value_raw'] ) || 'image-upload' === $meta_value['type'] && isset( $meta_value['value_raw'] ) ) ) {
Expand Down
Loading