Use WordPress’s upload_mimes filter to add a narrowly defined extension-to-MIME mapping in a plugin or site-specific functionality file. Then test a real upload, inspect the active allowlist, and—on Multisite—have a Super Admin permit the extension under Network Admin → Settings → Upload file types. If WordPress still rejects the file, validate its contents and check any form plugin, security layer, web server, or host policy that may apply a second allowlist.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
What a MIME type controls in WordPress
A MIME type is the media-type label that describes a file format, such as application/json for JSON or text/csv for comma-separated values. WordPress pairs that label with a filename extension in an internal map. During an upload, the map helps WordPress decide whether the extension is permitted and what type should be stored in the Media Library.
As an Amazon Associate I earn from qualifying purchases.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →The extension is only a hint. For images, WordPress can also inspect the file itself and compare the detected format with the filename. That distinction matters when a file has been renamed, has malformed metadata, or contains content that does not match its extension.
The maps involved
wp_get_mime_types()returns the general extension-to-MIME map. Core’s map includes common image, audio, video, document, archive, and OpenDocument formats, and the exact map can change between WordPress releases.get_allowed_mime_types()returns the types currently allowed for uploads after WordPress applies its restrictions.wp_check_filetype( $filename, $mimes = null )matches a filename against a map and returnsextandtype. If no match exists, those values are false.wp_check_filetype_and_ext( $file, $filename, $mimes = null )performs the basic match and, for images, attempts to determine the real MIME type. Its result includesext,type, andproper_filename.
These functions are useful for debugging and for custom upload handlers, but changing the upload allowlist normally belongs on upload_mimes.
#1 Best Overall
Choose the correct WordPress hook
| Hook or function | What it changes | Best use | Important limitation |
|---|---|---|---|
upload_mimes |
The extensions users may upload | Adding, restricting, or removing upload types for a site | It does not replace validation of the file’s actual contents |
mime_types |
The general extension-to-MIME map | Adding a type to WordPress’s broad MIME map | The WordPress reference says to use this filter to add, not remove, types |
wp_get_mime_types() |
Reads the current general map | Inspecting what WordPress knows about | It is a lookup function, not an upload permission switch |
get_allowed_mime_types() |
Reads the effective upload allowlist | Checking whether a filter is active | Multisite network restrictions can narrow the result |
For the usual question—“How do I let users upload this additional format?”—use upload_mimes. Keep the change in a plugin or a site-specific functionality location rather than a theme’s functions.php; a theme switch should not silently remove an upload capability.
Add one MIME type with a small plugin
Create a site-specific plugin in wp-content/plugins/, give it a plugin header, and add a narrow filter. This JSON example permits only files ending in .json whose declared type is application/json:
Recommended Free Tools
<?php
/**
* Plugin Name: Site Upload MIME Rules
*/
add_filter( 'upload_mimes', function ( $mimes ) {
$mimes['json'] = 'application/json';
return $mimes;
} );
Activate the plugin from Plugins → Installed Plugins. The array key is the extension without a dot; the value is the MIME string. Do not add a wildcard or a list of unrelated executable formats when one exact pair is all the site needs.
Common examples
Use the same pattern for other formats, checking that the value describes the actual format:
<?php
add_filter( 'upload_mimes', function ( $mimes ) {
$mimes['csv'] = 'text/csv';
$mimes['webp'] = 'image/webp';
$mimes['woff'] = 'font/woff';
$mimes['woff2'] = 'font/woff2';
return $mimes;
} );
WordPress’s official upload_mimes reference demonstrates this style for SVG, SVGZ, DOC, JSON, CSV, fonts, and WebP. The correct MIME value can vary by format and by the software that produced it, so confirm the format’s documented media type before adding it.
SVG requires a security decision
SVG is XML and can carry active markup, references, or scripts. Allowing the image/svg+xml pair does not sanitize an SVG. Only permit it for trusted users, sanitize the content with a dedicated SVG sanitizer, and control where the resulting files can be served. If untrusted visitors can upload SVG, simply adding the MIME mapping is not a safe implementation.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →<?php
add_filter( 'upload_mimes', function ( $mimes ) {
$mimes['svg'] = 'image/svg+xml';
return $mimes;
} );
Apply the same caution to HTML, XML, and any format that can contain code or external references. A successful upload is not proof that the file is safe to display.
Use a must-use plugin when the rule must survive changes
A must-use plugin in wp-content/mu-plugins/ loads automatically and is not deactivated from the normal Plugins screen. It is suitable for a managed site that requires the MIME rule on every request, provided your team documents who owns it and how to remove it.
<?php
/**
* Plugin Name: Organization Upload MIME Policy
*/
add_filter( 'upload_mimes', function ( $mimes ) {
$mimes['json'] = 'application/json';
return $mimes;
} );
Use a regular plugin when administrators need an obvious on/off switch. Use a must-use plugin only when the policy is intentionally central and your deployment process tracks the file.
When to use the mime_types filter
The mime_types filter changes the general map returned by WordPress. The developer reference explicitly describes it as a filter for adding types, not removing them; removal belongs on upload_mimes.
<?php
add_filter( 'mime_types', function ( $mimes ) {
$mimes['json'] = 'application/json';
return $mimes;
} );
Choose this hook only when another part of the site needs the type in the broad map as well as in upload handling. If your requirement is simply “allow this extension in the Media Library,” upload_mimes communicates the intent more precisely.
Confirm that WordPress loaded your rule
Before changing more code, inspect the effective map. A temporary diagnostic in a controlled environment can print the entries WordPress sees:
Rank #3
<?php
add_action( 'admin_init', function () {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
error_log( print_r( get_allowed_mime_types(), true ) );
} );
Remove the diagnostic after testing; do not expose the complete map to ordinary visitors. Look for the extension key and its MIME value. If it is absent, check that the plugin is active, the PHP file has no syntax error, and the filter is registered before the upload request runs.
Test the real upload path
- Log in as the same role that will upload the file.
- Open Media → Add New and select a representative file, not an empty file renamed with a new extension.
- Record the exact error, including punctuation and capitalization.
- Repeat with a known-good file of the same format to separate a mapping problem from a damaged-file problem.
- After a successful upload, download the stored file and verify that it opens as the intended format and is served with an appropriate content type.
Testing as an administrator can hide a permissions or network-policy issue that affects ordinary authors, so test with the least-privileged role that needs the capability.
Fix “Sorry, this file type is not permitted for security reasons”
The message means that at least one upload layer did not accept the extension/type combination. Work through these checks in order.
1. Check the pair you intended to allow
Confirm the filename really ends in the extension you added and that the MIME string is exact. For example, a .json entry should not be paired with an image MIME, and an extension with a trailing space will never match. Remember that the array key has no leading dot.
2. Check the effective allowlist
Use get_allowed_mime_types() in a protected diagnostic or a temporary administrator-only tool. If the entry is missing, the filter is not loaded, another callback removed it, or a different site is receiving the request.
3. Check Multisite network policy
On Multisite, a site-level filter can be narrowed by the network’s upload_filetypes option. A Super Admin should open Network Admin → Settings → Upload file types and add the extension there. The default network list is jpg jpeg png gif. WordPress’s check_upload_mimes() intersects the core map with that network option, so a site-level upload_mimes entry alone may not be enough.
Rank #4
- Keep track of everything from attendance to test scores
- Spiral bound
- Measures 8-1/2" x 11"
4. Check the file’s actual contents
wp_check_filetype_and_ext() checks the filename mapping and, for images, attempts to identify the real MIME type. If the extension and bytes disagree, WordPress can reject the upload or return a corrected image filename in proper_filename. Try an unmodified file exported by the format’s normal application. Renaming a file is not conversion.
5. Check other upload layers
A form plugin, security plugin, reverse proxy, web server, or hosting policy can impose its own allowlist. Temporarily isolate those layers in a staging environment, then re-enable them one at a time. A WordPress filter cannot override a server rule that blocks the request before WordPress receives it.
Validate files in custom upload code
If you are building a front-end uploader, REST endpoint, or AJAX handler, do not rely only on the filename or on the Media Library’s UI. Wordfence’s security guidance recommends sanitizing the filename before checking its extension and using wp_check_filetype_and_ext() or, at minimum, wp_check_filetype(). Keep an allowlist of the formats that feature actually needs.
<?php
$filename = sanitize_file_name( $_FILES['asset']['name'] );
$allowed = get_allowed_mime_types();
$checked = wp_check_filetype_and_ext(
$_FILES['asset']['tmp_name'],
$filename,
$allowed
);
if ( empty( $checked['ext'] ) || empty( $checked['type'] ) ) {
return new WP_Error(
'invalid_file_type',
'The uploaded file type is not allowed.'
);
}
When calling wp_check_filetype_and_ext() from a plugin or theme, load wp-admin/includes/file.php first if the function is undefined in that execution context:
<?php
if ( ! function_exists( 'wp_check_filetype_and_ext' ) ) {
require_once ABSPATH . 'wp-admin/includes/file.php';
}
Validation is only one control. Enforce upload permissions, limit file size, store files with WordPress’s upload APIs, prevent executable files from being served as code, and apply format-specific sanitization where needed.
Why broad fixes are dangerous
ALLOW_UNFILTERED_UPLOADS and “allow everything” rules remove the narrow boundary that protects an ordinary WordPress installation. They can let users place scripts or other active content in a publicly reachable directory. A routine JSON or WebP requirement does not justify that trade-off.
Best Value
- Allow only the exact extension and MIME pair required by the feature.
- Limit the capability to trusted roles whenever the format can contain markup, scripts, macros, or external references.
- Sanitize filenames before validation and reject mismatches between names and file contents.
- Keep uploads outside executable paths and configure the web server so uploaded content cannot run as server-side code.
- Log policy changes and review them after WordPress core, plugin, PHP, or hosting updates.
Remove, restrict, or audit a MIME rule
Remove an entry with upload_mimes
When you need to withdraw a type, unset it from the upload allowlist rather than trying to remove it through mime_types:
<?php
add_filter( 'upload_mimes', function ( $mimes ) {
unset( $mimes['json'] );
return $mimes;
} );
If both an adding callback and a removing callback exist, their priority and load order determine the final result. Search all plugins, must-use plugins, themes, and deployment snippets for the extension before deciding which rule to keep.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteRestrict a type by user capability
You can return different allowlists for trusted and untrusted roles. The capability check should reflect your site’s policy; do not assume that every administrator role has the same capabilities on a customized installation.
<?php
add_filter( 'upload_mimes', function ( $mimes ) {
if ( ! current_user_can( 'manage_options' ) ) {
unset( $mimes['svg'], $mimes['html'] );
}
return $mimes;
} );
This controls the WordPress upload list, not files already stored in the uploads directory. Removing a MIME entry does not delete existing files, rewrite server rules, or sanitize content that was previously uploaded.
Compare the main ways to manage MIME types
| Approach | Scope | Map or allowlist | Content validation | Who can change it | Removal and auditing |
|---|---|---|---|---|---|
Site plugin using upload_mimes |
One WordPress site | Upload allowlist | Must be handled separately with WordPress validation functions | Users with plugin or deployment access | Deactivate or remove one documented plugin rule |
| Must-use plugin | One installation, loaded automatically | Upload allowlist | Separate validation still required | Server or deployment administrators | Remove the file through deployment; record the policy centrally |
mime_types filter |
Where WordPress reads the general map | General MIME map | Does not itself inspect bytes | Code maintainers | Revert the callback; use upload_mimes for removals |
| Multisite Network Admin setting | All sites under a network policy | Network-level extension restriction | Does not replace file validation | Super Admin | Edit Network Admin → Settings → Upload file types and document the change |
| Form, security, server, or host control | That product or infrastructure layer | Its own allowlist or request policy | Varies by implementation | Product or infrastructure administrators | Audit the layer’s configuration and logs |
Troubleshooting symptoms and fixes
- The filter works in a theme but disappears after a redesign: move the callback to a plugin or site-specific functionality location.
- The extension appears in the map but the upload is denied on Multisite: ask a Super Admin to review the network upload-file-types list.
- One image uploads and another with the same extension fails: inspect the failing file’s actual bytes and metadata; extension matching alone is not sufficient for images.
- The Media Library accepts the file but a front-end form rejects it: inspect the form plugin’s own extension and MIME settings and its server-side validation.
- The upload succeeds but the browser displays an error: check the stored file, response headers, web-server MIME configuration, and whether the format requires sanitization or special handling.
- A callback seems to have no effect: confirm the PHP file loads on the upload request, check for syntax or fatal errors, and search for later callbacks that unset or replace the same extension.
Deployment checklist
- Write down the business need and the one exact extension/MIME pair required.
- Add the pair through a version-controlled plugin or approved site-specific code location.
- Use
get_allowed_mime_types()in a protected test to verify the effective map. - On Multisite, confirm the network setting permits the extension.
- Test with a known-good file as the role that will upload it.
- For custom upload endpoints, sanitize the filename and call
wp_check_filetype_and_ext()orwp_check_filetype(). - Apply format-specific controls for SVG, HTML, XML, and other code-bearing formats.
- Record the owner, date, reason, and rollback method for the rule.
- Re-test after WordPress core, plugin, PHP, web-server, or hosting changes.
Bottom line
For an ordinary WordPress site, add the required extension and MIME pair with upload_mimes in a plugin or site-specific code location. Use mime_types only when you need to extend the general map, and use upload_mimes when restricting or removing upload types. Verify the effective allowlist, account for Multisite’s network setting, and validate the file’s contents—especially for images and code-bearing formats—before treating the upload as safe.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




