Sanitizeresw_svg_allowed_attributes

esw_svg_allowed_attributes

Filter the attribute names Easy SVG keeps on SVG elements: allow a presentation attribute your exports need, or remove ones your site never wants.

Filter · Easy SVG · Status: Stable

When Easy SVG cleans an SVG, every attribute whose name is not on an allow-list is removed from its element. This filter gives you that list. Add an attribute a design tool writes and your files keep it, take one out and it is stripped from every SVG the site stores from then on.

Usage

apply_filters( 'esw_svg_allowed_attributes', array $attributes )
add_filter( 'esw_svg_allowed_attributes', 'myplugin_svg_attributes' );

When to use it

  • An exporter writes a presentation attribute the library does not know yet, such as transform-origin or mask-type, and the drawing looks different after upload.
  • You need an accessibility attribute that is not covered by the built-in aria-* rule, for example focusable.
  • Your policy is stricter than the default and you want HTML-only attributes such as src or srcset gone from every SVG.

Do not use it:

  • For event handlers. Nothing that starts with on belongs on this list.
  • To keep or remove aria-* or data-* attributes. The library keeps those on its own, whatever the list says.
  • To keep editor metadata such as inkscape:label. It is safe to lose and only makes files bigger.

Parameters

body
$attributesstring[]
Required

A flat, numerically indexed array of attribute names, for example array( 'about', 'accept', 'action', ... ). Without other callbacks it is the default list of the bundled enshrined/svg-sanitize library: 328 entries in version 1.0.0, covering HTML, SVG, MathML and a few XML names such as xlink:href and xml:space. Names are matched case-insensitively against the attribute name as written, prefix included (xlink:href, inkscape:label).

Return value

returnstring[]

The attribute names the sanitizer may keep. It must be an array. Returning anything else makes the library throw a TypeError while the sanitizer is built, and the upload ends with a fatal error.

Default

The AllowedAttributes list of enshrined/svg-sanitize 1.0.0, unchanged. Useful to know:

  • Already on it: id, class, style, role, tabindex, href, xlink:href, viewbox, preserveaspectratio, transform, every common presentation attribute (fill, stroke, stroke-width, opacity, clip-path, mask, filter, font attributes) and the animation timing attributes (attributename, values, begin, dur).
  • Not on it, so removed: every on* handler, focusable, transform-origin, mask-type, from, to, xml:lang, and editor namespaces such as inkscape:* and sodipodi:*.
  • Always kept, independent of the list: every name that starts with aria- or data-.

Examples

Keep focusable for older screen readers

This is the example from the plugin readme.

/**
 * Keep focusable="false" on inline SVG icons.
 *
 * @param string[] $attributes Allowed attribute names.
 * @return string[]
 */
function myplugin_allow_focusable( $attributes ) {
	$attributes[] = 'focusable';
	return $attributes;
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_allow_focusable' );

Keep newer presentation attributes from your exporter

/**
 * Keep presentation attributes that newer design tools write.
 *
 * @param string[] $attributes Allowed attribute names.
 * @return string[]
 */
function myplugin_allow_svg2_presentation( $attributes ) {
	return array_merge( $attributes, array( 'transform-origin', 'mask-type' ) );
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_allow_svg2_presentation' );

Without this, mask-type="alpha" is dropped and a mask falls back to luminance, so the shape can come out lighter or invisible.

Strip HTML attributes that carry URLs

/**
 * Remove HTML-only URL attributes from every stored SVG.
 *
 * @param string[] $attributes Allowed attribute names.
 * @return string[]
 */
function myplugin_strict_svg_attributes( $attributes ) {
	if ( ! is_array( $attributes ) ) {
		return array();
	}

	$blocked = array( 'src', 'srcset', 'poster', 'background', 'action' );

	return array_values(
		array_filter(
			$attributes,
			static function ( $name ) use ( $blocked ) {
				return ! in_array( strtolower( $name ), $blocked, true );
			}
		)
	);
}
add_filter( 'esw_svg_allowed_attributes', 'myplugin_strict_svg_attributes' );

The is_array() guard keeps the return value an array even if another callback before yours broke the list. Returning an empty array is safe in the sense that it cannot let anything through, but it strips every attribute from every file, so log it if you ever hit that branch.

The sanitizer only checks the value of attributes whose name contains href: there it allows fragments, relative paths, http(s) and a few image data: types and removes javascript:. Every other attribute you add is kept with whatever value the file gives it. Adding onload, onclick or any other on* name lets an uploaded file run script in the browser of everyone who opens it, including your administrators in the media library. Add only names that describe how a drawing looks.

How it works

The filter runs inside esw_svg_attributes::getAttributes() (easy-svg.php, line 91). Every call to easy_svg_sanitizer() builds a new sanitizer and calls setAllowedAttrs( new esw_svg_attributes() ), which applies the filter and lower-cases the result. Uploads, sideloads, the wp_upload_bits check, the new-attachment check, the icon library and add-ons all go through that function, so they all see the same list.

Elements are checked first (see esw_svg_allowed_tags); attributes are only looked at on elements that survive. Mixed-case spellings such as xlink:HrEf are rewritten to lower case when the lower-case name is on the list.

For icons there is one more fixed step: easy_svg_harden_icon_markup() removes every on* attribute and every href that does not start with #, whatever this list allows, because icons are inlined into pages.

Pitfalls

  • You cannot strip aria-* or data-* here. Removing aria-hidden from the list has no effect, the library keeps those prefixes unconditionally.
  • Values are not validated. Only href-like names get a value check. A new attribute keeps any value, javascript: included.
  • Return an array. null or a string from your callback is a fatal error during the upload.
  • Compare in lower case when removing. The defaults contain mixed spellings such as filterUnits. Use strtolower() instead of a plain array_diff().
  • Prefixes are part of the name. xlink:title and title are separate entries.
  • Removing common names breaks drawings. Take out style or class and files that colour their shapes through CSS lose their colours.
  • The XML-RPC path refuses, it does not clean. Files written through wp_upload_bits() are refused when the sanitizer would change them, so a stricter list means more refused uploads there.
  • The legacy global cannot change the list. setAllowedAttrs() on the old global $sanitizer is overwritten on every copy. Use the filter.