How to resolve var(--...) style attribute with HtmlPurifier?
I tried with this config:
<?php
return [
'encoding' => 'UTF-8',
'finalize' => true,
'ignoreNonStrings' => false,
'cachePath' => storage_path('app/purifier'),
'cacheFileMode' => 0755,
'settings' => [
'default' => [
'HTML.Doctype' => 'HTML 4.01 Transitional',
'HTML.Allowed' => 'div,b,strong,i,em,s,u,a[class|href|title],ul,ol,li,p[style],br,span[style],img[width|height|alt|src]',
'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,var,background-color,text-align',
'AutoFormat.AutoParagraph' => true,
'AutoFormat.RemoveEmpty' => true,
],
],
];
$string = '<span style="color: var(--myvar);">text</span>';
$string = Purifier::clean($string);
echo $string;
But I got the result without style attribute:
<span>text</span>
Expected result:
<span style="color: var(--myvar);">text</span>
Any ideas, thanks!
Why is this happening?
Fundamentally, HTML Purifier works by understanding how HTML and CSS function and are interpreted by browsers. It doesn't just let you whitelist tags or CSS, but also has knobs to define maximum image sizes to prevent imagecrash attacks and blocks attempts to put unsupported child elements into a particular place (e.g.
<div>into<ul>without a<li>), which may have undefined behaviours that could, in any one browser, be an actual exploit.To be able to do these things, it needs to understand all the elements you try to whitelist. It comes with an extensive CSS and HTML definition out of the box, but (1) even back when it was written, HTML Purifier intentionally didn't bother implementing knowledge about certain parts of HTML and CSS that the author considered inherently unsafe, (2) HTML5 has happened since HTML Purifier was written, and there have been advances in CSS.
So it can absolutely happen that you have some benign input that HTML Purifier won't allow even if it's whitelisted, because it doesn't understand the input.
What you can do.
But! You can teach it. Sadly the Customize! documentation I just linked to is for HTML elements and not for CSS, but it introduces some concepts that are valuable to understanding how HTML Purifier works under the hood. I won't paste them here because they're orthogonal to your question.
CSS doesn't have a nice corresponding doc at the moment. The
add new css propertythread on the HTML Purifier forum (archive.org link) had some information on how to do this. This is an example that Oliver Schonrock posted that added a CSS attribute (not a value), which might nonetheless get you started on the right track:In your case, you will want to write a custom
AttrDefdecorator (similar to theHTMLPurifier_AttrDef_CSS_ImportantDecoratorone you can see in this example code) and assign it to all the CSS attributes that you want to supportvar()for.But also, you may not want to do this. If you want to add it properly, it'll probably be hard - you'll want to make sure that no one can use
var()s to bypass value checks that HTML Purifier is doing, for example! (e.g. someone may be able to bypass the imagecrash defenses this way, just as a salient example).