WordPress does not allow SVG file uploads by default. The restriction exists for a legitimate reason: SVG files are XML documents that can contain embedded JavaScript, and a maliciously crafted SVG served from your domain can execute scripts in a visitor’s browser, a stored XSS vulnerability. However, for many sites, particularly those where developers, designers, or trusted administrators handle uploads, SVG support is a genuine need for logos, icons, and illustrations that need to scale without quality loss.
This snippet enables SVG uploads with basic server-side sanitisation applied at upload time. It is appropriate for sites where upload access is restricted to trusted users. It is not recommended for sites with public or untrusted file upload functionality.
The Code
Add this to your functions.php or a site-specific plugin. Three filters work together: one adds SVG to the allowed MIME types, one fixes WordPress’s MIME type detection (which misidentifies SVGs on some server configurations), and one sanitises the SVG content before it’s saved to disk.
The upload_mimes Filter
upload_mimes is the list of file extensions and their corresponding MIME types that WordPress permits through the uploader. Adding svg and svgz (the gzip-compressed variant) with the image/svg+xml MIME type unlocks the upload dialogue for those file types.
The MIME Type Fix
WordPress uses the server’s finfo or mime_content_type functions to verify that the MIME type of an uploaded file matches its extension. On many server configurations these functions incorrectly identify SVG files as text/html or text/plain rather than image/svg+xml, causing WordPress to reject the upload even after the MIME type is added to the allowed list. The wp_check_filetype_and_ext filter patches this by manually setting the correct type when the extension matches and the type check fails.
The Sanitisation Step
The sanitisation filter in this snippet uses regex to strip <script> tags and inline event handler attributes (like onload, onclick, onerror) from the SVG content before it’s written to disk. This removes the most common XSS vectors in SVG files. It is a basic defence, not a comprehensive SVG sanitiser. For production sites that need robust SVG sanitisation, consider using a dedicated library like enshrined/svg-sanitize via Composer, which handles a broader range of attack vectors including foreignObject, use element abuse, and data URI exploits.
Display Considerations
Even with SVG uploads enabled, WordPress won’t generate thumbnail previews for SVG files in the Media Library because it can’t process SVGs through its image editing pipeline. The file will upload and be usable in posts and pages, but its thumbnail in the Media Library grid will show a generic file icon. This is a cosmetic limitation and doesn’t affect how the SVG renders on the front end.
// Allow SVG uploads
add_filter( 'upload_mimes', function( $mimes ) {
$mimes['svg'] = 'image/svg+xml';
$mimes['svgz'] = 'image/svg+xml';
return $mimes;
} );
// Fix the mime type check for SVGs (WordPress misidentifies them)
add_filter( 'wp_check_filetype_and_ext', function( $data, $file, $filename, $mimes ) {
if ( ! $data['type'] ) {
$ext = pathinfo( $filename, PATHINFO_EXTENSION );
if ( $ext === 'svg' || $ext === 'svgz' ) {
$data['type'] = 'image/svg+xml';
$data['ext'] = $ext;
}
}
return $data;
}, 10, 4 );
// Sanitise SVG files on upload to strip script tags and event handlers
add_filter( 'wp_handle_upload_prefilter', function( $file ) {
if ( $file['type'] !== 'image/svg+xml' ) return $file;
$content = file_get_contents( $file['tmp_name'] );
// Strip script tags
$content = preg_replace( '/<script[\s\S]*?<\/script>/i', '', $content );
// Strip on* event handlers
$content = preg_replace( '/\s+on\w+=["\'][^"\']*["\']/', '', $content );
file_put_contents( $file['tmp_name'], $content );
return $file;
} );
