41. File Upload Security | Form Forge - Build Forms with AI in Seconds
Download Log in

41. File Upload Security

Developer Guide

Detailed security measures for the file upload system. PRO feature.

MIME Validation

Server-side validation checks the actual file MIME type, not just the extension:

php
$allowed_types = [
    'image/jpeg', 'image/png', 'image/gif', 'image/webp',
    'application/pdf', 'application/msword',
    'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
    'text/plain', 'text/csv',
];

$file_type = wp_check_filetype_and_ext( $file['tmp_name'], $file['name'] );
if ( ! in_array( $file_type['type'], $allowed_types, true ) ) {
    wp_send_json_error( [ 'message' => 'This file type is not allowed.' ] );
}

Size Limit

Maximum file size is 10 MB per file:

php
$max_size = 10 * 1024 * 1024;
if ( $file['size'] > $max_size ) {
    wp_send_json_error( [ 'message' => 'File size exceeds the 10MB limit.' ] );
}

Upload Processing Flow

php
// 1. Validate MIME type
// 2. Check file size
// 3. Move the file into uploads/formforge-private/YYYY/MM/
// 4. Store private metadata in submission data
$stored_file = [
    'token'         => 'random-download-token',
    'name'          => 'resume.pdf',
    'stored_name'   => 'uuid.pdf',
    'relative_path' => 'formforge-private/2026/05/uuid.pdf',
    'mime'          => 'application/pdf',
    'size'          => 12345,
    'field_id'      => 'resume',
];

Preventing PHP File Execution

WordPress’s wp_check_filetype_and_ext() prevents .php files renamed to .jpg from being accepted. The MIME type check catches the mismatch between extension and actual content.

Accessing Uploaded Files

php
$data = json_decode( $sub->data, true );
$file = $data['field_resume']['file'] ?? null;

if ( $file ) {
    echo esc_html( $file['name'] );
    // Admin downloads go through:
    // admin-ajax.php?action=formforge_download_file&submission_id=...&field=...&token=...&_wpnonce=...
}

Do not build public wp-content/uploads/... URLs for Form Forge file uploads. The stored relative_path is intentionally private and should only be served through the admin download handler.

Forge AI Assistant Online

Hi! I'm the Form Forge AI assistant. Ask me anything about the plugin — setup, features, troubleshooting, or development.

Just now
Powered by Forge AI · Browse docs