Safe SVG
Safe SVG
Description
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.
Current Features
- Sanitised SVGs – Don’t open up security holes in your WordPress site by allowing uploads of unsanitised files.
- SVGO Optimisation – Runs your SVGs through the SVGO tool on upload to save you space. This feature is disabled by default but can be enabled by adding the following code:
add_filter( 'safe_svg_optimizer_enabled', '__return_true' ); - View SVGs in the Media Library – Gone are the days of guessing which SVG is the correct one, we’ll enable SVG previews in the WordPress media library.
- Choose Who Can Upload – Restrict SVG uploads to certain users on your WordPress site or allow anyone to upload.
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.
Technical: Upload Path Security
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.
Installation
Install through the WordPress directory or download, unzip and upload the files to your /wp-content/plugins/ directory
Faq
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.
Reviews
Great plugin, updated!
By Karolina Vyskocilova (vyskoczilova) on August 6, 2026
Must use plugin, well maintained, installing almost every time and just now I've realized, that I didn't review it. Keep it up and thanks!
Very helpful plugin
By jeeni on April 22, 2026
Very helpful plugin, thanks!
Works Well
By devlin1 on March 11, 2026
Needed SVG upload support, and this plugin did the job. Very lightweight and easy to use. No issues so far. Some additional settings would be nice, but overall, it's quite solid.
Nice And Easy
By Reza Asadi (asadister) on November 19, 2025
Nice And Easy plugin for using SVG files
Good plugin, but missing ...
By rrvoigt on June 21, 2025
Would have given a 5 star, but it seems support is missing for the taxonomy / terms section (like in categories) upload for SVG images. Keep getting an error that the upload isn't supported. Hopefully this will be fixed in a future update. Will update once this is added. Cheers!
Wonderful + fetaure request
By Stefano (stefacchio) on April 30, 2025
Great plugin! very usefull, but please can you add the possibility to add an inline SVG on the block pasting svg code?
Thanks!
ELEMENTOR+Safe SVG=It works
By bandgamin on March 25, 2025
Thanks to the plugin developers. The plugin helped me solve my issue.
Effortless
By Jimmy Lee (shirtguy72) on November 14, 2024
Thanks for creating this plugin!
Caused very long loading times in homepage translations (wpml)
By headfalcon on July 31, 2024
I didn't look into it but this plugin caused my homepage in translations to take about 30 seconds to load, instead of 1-2. We use WPML. It was back to normal the moment I deleted the plugin.
Quick and easy!
By iz4atkal on July 30, 2024
Does what it says. 👍
Changelog
2.5.0 – 2026-09-07
- Security: Prevented direct access of PHP files (props @mehrazmorshed, @dkotter via #300).
- Security: The Inline SVG block now renders SVGs that carry their own
<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). - Security: Bump
enshrined/svg-sanitizefrom^0.22.0to^1.0.0to pull in security fixes (props @dkotter, @jeffpaul, @peterwilsoncc via #327). - Added: Link support for the SVG Inline block, including URL input, new tab toggle, and nofollow/sponsored rel options (props @vegetable-bits, @mgiannopoulos24, @jeffpaul, @thrijith, @peterwilsoncc, @dkotter, @pbiron via #315).
- Added: New
safe_svg_inline_use_shadow_domfilter to control which inline SVGs are isolated in a shadow root, and newsafe_svg_inline_shadow_stylesfilter to adjust the CSS injected alongside them (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328). - Added: New
safe_svg_remove_remote_referencesfilter to strip remoteurl(),@importandimage-set()references, along with remotehreftargets, 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). - Added: Added support for Enable Media Replace plugin (props @gthayer, @jeffpaul, @peterwilsoncc via #285).
- Changed: Bump WordPress minimum supported version to 6.9 (props @zamanq, @peterwilsoncc via #320).
- Changed: Bump “tested up to header” to indicate WordPress 7.1 support (props @navi151, @peterwilsoncc, @dkotter, @jeffpaul, @zamanq via #290, #311, #320).
- Changed: Theme CSS can no longer target an inline SVG that carries its own
<style>element, because stylesheets cannot reach into a shadow root. Style those SVGs from within the SVG itself, or opt out with thesafe_svg_inline_use_shadow_domfilter. Inherited properties, includingcolor/currentColorand custom properties, still apply as before, and SVGs without a<style>element are unaffected (props @darylldoyle, @dkotter, @jeffpaul, @peterwilsoncc via #328). - Changed: Updated blueprint file for WordPress.org live previews (props @fellyph, @jeffpaul, @peterwilsoncc via #287).
- Changed: Bump
svgofrom 3.2.0 to 3.3.5 (props @dependabot[bot], @jeffpaul, @peterwilsoncc, @dependabot via #309).
2.4.0 – 2025-09-22
- Added: Ability to upload SVGs from more admin locations (props @stormrockwell, @darylldoyle, @wpexplorer, @smerriman, @jeffpaul, @dkotter via #279).
- Changed: Added
$attachment_idargument to filterssafe_svg_use_width_height_attributesandsafe_svg_dimensions(props @roborourke, @dkotter via #278). - Fixed: Inconsistent or incorrect data type for
$svgargument in the filterssafe_svg_use_width_height_attributesandsafe_svg_dimensions(props @roborourke, @dkotter via #278).
2.3.3 – 2025-08-13
- Security: Update the
enshrined/svg-sanitizepackage from0.19.0to0.22.0to fix an issue with case-insensitive attributes slipping through the sanitiser and address PHP 8.4 deprecation warnings (props @darylldoyle, @sudar, @georgestephanis, @dkotter, @realazizk via #268, #272). - Security: Bump
form-datafrom 4.0.0 to 4.0.4 (props @dependabot, @faisal-alvi via #270). - Security: Bump
tmpfrom 0.2.3 to 0.2.5 and@inquirer/editorfrom 4.2.9 to 4.2.16 (props @dependabot, @dkotter via #271).
2.3.2 – 2025-07-21
- Fixed: Visual parity between the front end and the block editor (props @s3rgiosan, @dkotter via #261, #266).
- Changed: Bump WordPress “tested up to” version 6.8 (props @godleman, @jeffpaul, @dkotter via #251, #254).
- Changed: Bump WordPress minimum supported version to 6.6 (props @godleman, @jeffpaul, @dkotter via #254).
- Security: Bump
wsfrom 7.5.10 to 8.18.0,@wordpress/scriptsfrom 27.9.0 to 30.6.0,nanoidfrom 3.3.7 to 3.3.8 andmochafrom 10.2.0 to 11.0.1 (props @dependabot, @peterwilsoncc via #245). - Security: Bump
@babel/runtimefrom 7.23.9 to 7.27.0,axiosfrom 1.7.4 to 1.8.4,cookiefrom 0.4.2 to 0.7.1,expressfrom 4.21.0 to 4.21.2 and@wordpress/e2e-test-utils-playwrightfrom 0.26.0 to 1.20.0 (props @dependabot, @dkotter via #250). - Security: Bump
http-proxy-middlewarefrom 2.0.6 to 2.0.9 (props @dependabot, @iamdharmesh via #253). - Security: Bump
tar-fsfrom 3.0.8 to 3.0.9 (props @dependabot, @dkotter via #258). - Security: Bump
bytesfrom 3.0.0 to 3.1.2 andcompressionfrom 1.7.4 to 1.8.1 (props @dependabot, @dkotter via #265).
2.3.1 – 2024-12-05
- Fixed: Revert changes made to how we determine custom dimensions for SVGs (props @dkotter, @martinpl, @subfighter3, @smerriman, @gigatyrant, @jeffpaul, @iamdharmesh via #238).
2.3.0 – 2024-11-25
- Added: New setting that allows large SVG files (roughly 10MB or greater) to be uploaded and sanitized properly (props @kirtangajjar, @faisal-alvi, @darylldoyle, @manojsiddoji, @dkotter via #201).
- Added: New
get_svg_dimensionsfunction in order to reduce code duplication (props @gabriel-glo, @jeremymoore, @darylldoyle, @iamdharmesh, @dkotter via #216). - Changed: Updated the
enshrined/svg-sanitizepackage from 0.16.0 to 0.19.0 to fix a PHP 8.3 compatibility issue (props @sksaju, @TylerB24890, @darylldoyle, @rolf-yoast, @faisal-alvi via #214). - Changed: Update how image dimensions are passed in
get_image_tag_overrideandone_pixel_fixmethods (props @gabriel-glo, @jeremymoore, @darylldoyle, @iamdharmesh, @dkotter via #216). - Changed: Bump WordPress “tested up to” version to 6.7 (props @colinswinney, @jeffpaul via #232, #233).
- Changed: Bump WordPress minimum from 6.4 to 6.5 (props @colinswinney, @jeffpaul via #232, #233).
- Changed: Remove composer dev dependencies from archived project (props @TylerB24890, @szepeviktor, @peterwilsoncc via #220).
- Fixed: Use proper block category for the Safe SVG Icon block (props @kirtangajjar, @fabiankaegy via #226).
- Security: Only allow SVG file types to be uploaded if our sanitizer is able to run on those files (props @darylldoyle, @xknown, @dkotter via #228).
- Security: Bump
webpackfrom 5.90.1 to 5.94.0 (props @dependabot, @peterwilsoncc via #222). - Security: Bump
wsfrom 7.5.10 to 8.18.0,serve-staticfrom 1.15.0 to 1.16.2 andexpressfrom 4.19.2 to 4.21.0 (props @dependabot, @Sidsector9, @faisal-alvi via #227, #230, #234).
2.2.6 – 2024-08-28
- Changed: Bump WordPress “tested up to” version to 6.6 (props @sudip-md, @ankitguptaindia, @jeffpaul via #212, #213).
- Changed: Bump WordPress minimum from 5.7 to 6.4 (props @sudip-md, @ankitguptaindia, @jeffpaul via #212, #213).
- Security: Add svg sanitization on the
wp_handle_sideload_prefilterfilter (props @dkotter, @xknown, @iamdharmesh via GHSA-3vr7-86pg-hf4g). - Security: Bump
bracesfrom 3.0.2 to 3.0.3,pac-resolverfrom 7.0.0 to 7.0.1,socksfrom 2.7.1 to 2.8.3,wsfrom 7.5.9 to 7.5.10 and removeip(props @dependabot, @Sidsector9 via #206). - Security: Bump
axiosfrom 1.6.7 to 1.7.4 (props @dependabot, @faisal-alvi via #218).