Sorry, This File Type Is Not Permitted for Security Reasons
Current WordPress prints "Sorry, you are not allowed to upload this file type"; the older wording still fills tutorials and old installs. Both come from the same check, and the fix depends on whether the type is disallowed or the file is not what its extension says.
WordPress refused the upload because the file's type is not on the allowed list — and on a current site the message says so in different words. "Sorry, this file type is not permitted for security reasons." is the wording of older releases such as 5.8. Current WordPress says "Sorry, you are not allowed to upload this file type.", and the block editor prefixes the file name: "photo.svg: Sorry, you are not allowed to upload this file type." The newest releases' Media Library uploader may stop a disallowed extension in the browser with "This file cannot be processed by the web server." — same cause. A related block editor message, "Sorry, this file type is not supported here.", means the block itself does not take that kind of file — a PDF dropped on an Image block — and is not a permissions problem at all. The server-side refusals come from the upload handler after wp_check_filetype_and_ext() has worked out what the file really is. Before changing anything, find out which of two situations you are in: a type WordPress does not accept, or a file whose contents do not match a type it does.
What the check does with a mislabelled file
For images, WordPress inspects the file's contents and trusts them over the extension. A PNG renamed to .jpg is detected as a PNG, and because PNG is an allowed type, it is accepted and renamed to .png on the way in. The same happens for a WebP saved with a .png extension. Mislabelled images are not the cause of this error; they upload with a corrected name.
The error appears when the real type is one WordPress does not allow for your user:
| What the file really is | Extension on it | Result |
|---|---|---|
| PNG, JPEG, GIF, WebP | Any image extension | Accepted, renamed to match |
| SVG | .png, .jpg, .svg |
Rejected — SVG is never allowed by default |
| HTML or JavaScript | .html, .htm, .js |
Rejected unless the user has unfiltered_html |
| HEIC from a phone | .jpg, .heic |
Version-dependent; older releases cannot identify it and reject it |
PDF renamed to .docx |
.docx |
Rejected — contents and extension disagree on a non-image type |
| Executable, Flash | Anything | Rejected for everyone |
So the first question is what the file actually is. On a command line, file photo.jpg prints the detected type. On a desktop, the file's properties show it. If the real type is in the allowed set, the problem is elsewhere; if it is not, decide whether it should be.
Common requests in current WordPress
| Type | Allowed by default? |
|---|---|
| JPEG, PNG, GIF, WebP, AVIF | Yes |
| HEIC | Yes; converted to JPEG when the server's image library supports it |
| PDF, DOCX, XLSX, ZIP, MP3, MP4 | Yes |
| CSV, TXT, VTT | Yes |
| SVG, JSON | No |
| HTML, JS | Only for users with unfiltered_html |
| EXE, SWF | No, for anyone |
Allowing a type that is not on the list
The allowed list is filterable through upload_mimes, covered in depth in upload_mimes. Put the snippet in a small must-use plugin or a child theme's functions.php, not the parent theme, where an update would remove it:
add_filter( 'upload_mimes', 'ti_allow_json' );
function ti_allow_json( $mimes ) {
$mimes['json'] = 'application/json';
return $mimes;
}
The value is the MIME type WordPress will store for the attachment, and for non-image types it must match what PHP's fileinfo detects in the file. Some servers detect JSON as application/json and the filter is enough; others report text/plain, and the upload still fails, because WordPress forgives text/plain only for a short list of text types such as CSV and VTT. That mismatch is handled through the wp_check_filetype_and_ext filter — a sign the type is one WordPress treats with suspicion for a reason.
The same rule explains a puzzling case: a CSV, which is allowed, rejected anyway. Some spreadsheet exports with unusual encodings or stray binary bytes are detected as a generic type such as application/octet-stream, and WordPress accepts that generic answer only for application, audio and video types, not for text. Re-saving the file as UTF-8 CSV fixes it without any code.
SVG is the special case
SVG is the most requested type and the one WordPress will not allow by default, because an SVG is XML and can carry scripts that run when the image is viewed. Allowing it through upload_mimes alone makes the error go away and makes every uploader a potential source of stored scripts. A plugin that sanitises SVG on upload, restricted to administrators, is the acceptable form of allowing it. A stored script in uploads is one of the entry points behind a hacked site, and the honest trade-off is that logos usually survive conversion to PNG at the sizes a site uses.
HTML, JavaScript and the capability
.htm, .html and .js are in the allowed list only for users who hold unfiltered_html. On a single site that is administrators and editors; on multisite only super admins. That is why the same file uploads for one account and fails for another. If authors genuinely need to upload HTML — a downloadable template, say — zip it; a .zip is allowed for every uploader and sidesteps the question of executing it.
Multisite
On a network, Network Admin › Settings › Upload Settings has an "Upload file types" list, and core trims the default set down to it. A type that is normally allowed, such as PDF, is rejected on every site until it appears there. A snippet added at the default priority runs after that trimming, so its additions usually survive; if a filtered type still fails on a network, add it to the list as well.
The constant that should stay off
define( 'ALLOW_UNFILTERED_UPLOADS', true ) disables the type and content checks for users with unfiltered_upload — administrators by default, super admins on multisite. It is the quickest way to make the error disappear and the quickest way to let a compromised administrator account place a web shell in wp-content/uploads. If it is set on a site you inherited, remove it and allow the specific types the site needs. The uploads folder is served directly by the web server, and a file placed there is reachable by URL without WordPress in between.
Verify
- Upload a correctly exported file of an allowed type: it succeeds and shows in the media library.
- Rename a PNG to
.jpgand upload it: it succeeds and the stored file ends in.png— confirming the content check corrects rather than rejects images. - After adding a type through the filter, upload a genuine file of that type as an editor: it succeeds for the roles you intended and not for others, if you gated it.
- On a network, confirm the extension is in the network's "Upload file types" list.
Frequently asked
- Because that is the current wording. Older releases such as 5.8 printed 'Sorry, this file type is not permitted for security reasons'; current ones print 'Sorry, you are not allowed to upload this file type.', and the block editor adds the file name in front. Same check, same causes, same fixes.
- No. It switches off the type check for every account with the unfiltered_upload capability, which by default means administrators (super admins on multisite), so one stolen admin password is enough to store an executable or a scripted HTML file in your uploads folder. Allow the single type you need through the upload_mimes filter instead.
- HTML and JavaScript files are allowed only for users with the unfiltered_html capability: administrators and editors on a single site, only super admins on multisite. Many SVG and font plugins also gate their allowance by role. If the file is safe for editors to upload, that role condition is what to change.