Upload blocked medium
WordPress "Sorry, this file type is not permitted for security reasons"
WordPress rejects an upload because its extension or sniffed MIME type isn't in the allowed-uploads whitelist.
What you see
Sorry, this file type is not permitted for security reasons.
What’s actually happening
You drag a file into the Media Library and it bounces instantly with this red text. No file lands in wp-content/uploads. Images usually go through fine; it's the SVGs, fonts, DOCX, and zips that get stopped. The same file sometimes uploads on one site and fails on another with identical WordPress versions, which is the tell that this is a MIME-sniffing disagreement, not a broken file.
Common causes
- The extension simply isn't in get_allowed_mime_types() — WordPress ships no SVG, AVIF (pre-6.5), or .woff2 support out of the box.
- wp_check_filetype_and_ext() runs finfo_file() and getimagesize() against the actual bytes, and the real MIME disagrees with what the extension implies (the classic post-4.7.1 break for .docx, .pptx, .xlsm, .ai).
- The server's fileinfo database (/usr/share/misc/magic) is old or missing, so PHP sniffs a generic application/octet-stream and WordPress refuses it.
- A security plugin (Wordfence, Solid Security) or a host-level hardening rule has tightened the allowed list further than core.
- Multisite — network admins can restrict the upload file-type list under Network Admin > Settings independently of the per-site config.
How to fix it
- Confirm what WordPress thinks the type isDrop define('WP_DEBUG', true); and add a one-off mu-plugin that var_dumps wp_check_filetype_and_ext( $file, basename($file) ) for the file, or just check the host's PHP error log. If 'type' and 'ext' come back empty, it's a sniff mismatch, not a missing-extension problem — that changes which fix below you use.
- Whitelist a genuinely-missing extension with upload_mimesIn a small mu-plugin (wp-content/mu-plugins/allow-uploads.php), add: add_filter('upload_mimes', function($m){ $m['svg']='image/svg+xml'; $m['webp']='image/webp'; return $m; }); This is enough when the extension was never registered. It does NOT help when finfo is overruling you.
- Override the real-MIME check when sniffing is wrongFor the docx/xlsm/ai family the size check passes but finfo returns the wrong type. Hook wp_check_filetype_and_ext and force ext/type back when the filename matches: add_filter('wp_check_filetype_and_ext', function($data,$file,$fn,$mimes){ $ext=pathinfo($fn,PATHINFO_EXTENSION); if($ext==='docx'){$data['ext']='docx';$data['type']='application/vnd.openxmlformats-officedocument.wordprocessingml.document';} return $data; },10,4);
- For SVG, sanitize — don't just allowRaw SVG can carry inline <script>. Use the Safe SVG plugin (it runs enshrined/svg-sanitizer on upload) instead of a bare upload_mimes filter, or you've opened a stored-XSS hole for any author-level user.
- Last resort: ALLOW_UNFILTERED_UPLOADSdefine('ALLOW_UNFILTERED_UPLOADS', true); in wp-config.php lets super-admins upload anything. Treat it as a temporary diagnostic flag — leaving it on means a compromised admin account can upload a .php shell straight into uploads/.
Stop it recurring
Register custom types in a versioned mu-plugin instead of clicking around in a one-off plugin, so the rule survives plugin cleanups and theme swaps.
Related errors