1,000,000+
September 22, 2026
July 3, 2015
Safe SVG is the best way to Allow SVG Uploads in WordPress!
It gives you the ability to allow SVG uploads whilst making sure that they’re sanitized to stop SVG/XML vulnerabilities affecting your site. It also gives you the ability to preview your uploaded SVGs in the media library in all views.
add_filter( 'safe_svg_optimizer_enabled', '__return_true' );Initially a proof of concept for #24251.
SVG Sanitization is done through the following library: https://github.com/darylldoyle/svg-sanitizer.
SVG Optimization is done through the following library: https://github.com/svg/svgo.
WordPress’s _wp_handle_upload( $file, $action ) function allows any $action value, which determines the filter hook name: {$action}_prefilter. Safe SVG hooks common actions like wp_handle_upload and wp_handle_sideload, but cannot hook arbitrary custom actions defined by third-party code. Since upload actions are unbounded and MIME allowances are global, we cannot guarantee sanitization coverage across all possible upload paths.
Install through the WordPress directory or download, unzip and upload the files to your /wp-content/plugins/ directory
Yes, this can be done using the svg_allowed_attributes and svg_allowed_tags filters.
They take one argument that must be returned. See below for examples:
add_filter( 'svg_allowed_attributes', function ( $attributes ) {
// Do what you want here...
// This should return an array so add your attributes to
// to the $attributes array before returning it. E.G.
$attributes[] = 'target'; // This would allow the target="" attribute.
return $attributes;
} );
add_filter( 'svg_allowed_tags', function ( $tags ) {
// Do what you want here...
// This should return an array so add your tags to
// to the $tags array before returning it. E.G.
$tags[] = 'use'; // This would allow the <use> element.
return $tags;
} );
Mostly, yes. The Inline SVG block renders an SVG that carries its own <style> element inside a shadow root, because CSS inside an inline SVG is otherwise applied to the whole page rather than just the SVG. Stylesheets cannot reach into a shadow root, so theme CSS such as .entry-content svg { fill: red; } will not apply to those SVGs.
Inherited properties still cross the boundary, so setting color on an ancestor and using currentColor inside the SVG works, as do CSS custom properties. SVGs that do not contain a <style> element are rendered without the shadow root and can be styled by theme stylesheets.
To turn isolation off, at the cost of allowing an SVG’s CSS to affect the rest of the page:
add_filter( 'safe_svg_inline_use_shadow_dom', '__return_false' );
Safe SVG only allows SVGs through upload paths it can actively sanitize. While most WordPress uploads use standard functions like wp_handle_upload() (which Safe SVG hooks), plugins and themes can create custom upload paths by calling WordPress’s underlying _wp_handle_upload() function with arbitrary action parameters.
Globally enabling the image/svg+xml MIME type would allow SVGs through all upload paths—including custom ones Safe SVG cannot intercept and sanitize. This would create security vulnerabilities where unsanitized SVGs containing malicious scripts could be uploaded.
This is a deliberate design decision: Safe SVG prioritizes guaranteed sanitization over broad compatibility. SVGs are only allowed when we can ensure they’re safe.
Please report security bugs found in the source code of the Safe SVG plugin through the Patchstack Vulnerability Disclosure Program. The Patchstack team will assist you with verification, CVE assignment, and notify the developers of this plugin.
/safe-svg/v1/svg/ATTACHMENT-ID, that can be passed an attachment ID for an SVG and will return sanitized markup (props @dkotter, @peterwilsoncc via GHSA-3hhm-5qc9-q4xf).$sanitizer property from the safe_svg class. If you directly use the safe_svg class in order to access the $sanitizer property, you’ll need to update your code to instead use the new Svg_Sanitizer class (props @dkotter, @peterwilsoncc via GHSA-3hhm-5qc9-q4xf).<style> element inside a shadow root, so their CSS is scoped to the block instead of applying to the whole page (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328).enshrined/svg-sanitize from ^0.22.0 to ^1.0.0 to pull in security fixes (props @dkotter, @jeffpaul, @peterwilsoncc via #327).safe_svg_inline_use_shadow_dom filter to control which inline SVGs are isolated in a shadow root, and new safe_svg_inline_shadow_styles filter to adjust the CSS injected alongside them (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328).safe_svg_remove_remote_references filter to strip remote url(), @import and image-set() references, along with remote href targets, from uploaded SVGs. Off by default, because legitimate SVGs reference remote fonts and images but use this filter to turn it on (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328).<style> element, because stylesheets cannot reach into a shadow root. Style those SVGs from within the SVG itself, or opt out with the safe_svg_inline_use_shadow_dom filter. Inherited properties, including color/currentColor and custom properties, still apply as before, and SVGs without a <style> element are unaffected (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328).svgo from 3.2.0 to 3.3.5 (props @dependabot[bot], @jeffpaul, @peterwilsoncc, @dependabot via #309).$attachment_id argument to filters safe_svg_use_width_height_attributes and safe_svg_dimensions (props @roborourke, @dkotter via #278).$svg argument in the filters safe_svg_use_width_height_attributes and safe_svg_dimensions (props @roborourke, @dkotter via #278).| Version | Download | Type |
|---|---|---|
| 2.5.1 | Download | Stable |
| 2.5.0 | Download | Stable |
| 2.4.0 | Download | Stable |
| 2.3.3 | Download | Stable |
| 2.3.2 | Download | Stable |
| 2.3.1 | Download | Stable |
| 2.3.0 | Download | Stable |
| 2.2.6 | Download | Stable |
| 2.2.5 | Download | Stable |
| 2.2.4 | Download | Stable |
| 2.2.3 | Download | Stable |
| 2.2.2 | Download | Stable |
| 2.2.1 | Download | Stable |
| 2.2.0 | Download | Stable |
| 2.1.1 | Download | Stable |
| 2.1.0 | Download | Stable |
| 2.0.3 | Download | Stable |
| 2.0.2 | Download | Stable |
| 2.0.1 | Download | Stable |
| 2.0.0 | Download | Stable |
| 1.9.10 | Download | Stable |
| 1.9.9 | Download | Stable |
| 1.9.8 | Download | Stable |
| 1.9.7 | Download | Stable |
| 1.9.6 | Download | Stable |
| 1.9.5 | Download | Stable |
| 1.9.4 | Download | Stable |
| 1.9.3 | Download | Stable |
| 1.9.2 | Download | Stable |
| 1.9.1 | Download | Stable |
| 1.9.0 | Download | Stable |
| 1.8.1 | Download | Stable |
| 1.8.0 | Download | Stable |
| 1.7.1 | Download | Stable |
| 1.6.1 | Download | Stable |
| 1.6.0 | Download | Stable |
| 1.5.3 | Download | Stable |
| 1.5.2 | Download | Stable |
| 1.5.1 | Download | Stable |
| 1.5.0 | Download | Stable |
| 1.4.5 | Download | Stable |
| 1.4.4 | Download | Stable |
| 1.4.3 | Download | Stable |
| 1.4.2 | Download | Stable |
| 1.4.1 | Download | Stable |
| 1.4.0 | Download | Stable |
| 1.3.4 | Download | Stable |
| 1.3.3 | Download | Stable |
| 1.3.2 | Download | Stable |
| 1.3.1 | Download | Stable |
| 1.3.0 | Download | Stable |
| 1.2.0 | Download | Stable |
| 1.1.1 | Download | Stable |
| 1.1.0 | Download | Stable |
| 1.0.0 | Download | Stable |
| Development | Download | Trunk |