Media PHP Intermediate

Force SVG Support in the WordPress Media Uploader

Last updated: May 6, 2026

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.

functions.php
// 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;
} );

Built by Nahnu Plugins

Need something more powerful than a snippet?

Our commercial plugins go further, built for serious WordPress sites with full support, updates, and documentation included.

Browse All Plugins →

This website uses cookies to enhance your browsing experience and ensure the site functions properly. By continuing to use this site, you acknowledge and accept our use of cookies.

Accept All Accept Required Only