Comments (16)
In its current state: no.
We would need two things for that:
a) A CSS parser in JS that matches what browsers do individually
b) A threat model to be able to spec what it should prevent and what's legitimate
Unfortunately, there's no unified DOM API yet (afaik) that allows us to get there - or something that allows to easily and safely get all rules from a certains tylesheet and iterate over them. If there was one, we could actually consider.
from dompurify.
@joelabair So, I did some research and found out that we can indeed handle CSS sanitation in a clean and cross-browser compatible way.
Now, what I would like to know before starting an implementation: What kind of sanitation would you need? How do you imagine config and purpose?
from dompurify.
There's a multitude of stuff I wouldn't want to allow on user provided styles. The least would be to disallow URIs and calc
usages I guess. You'll probably know heaps of other properties or values that should be restricted as their usage can support certain kinds of attacks. Preferably I would want to have a whitelist of selectors and properties (plus allowed values!) instead of sanitizing things as there are so many CSS hacks out there that influence the interpretation of styles in browsers (see http://browserhacks.com/ and more).
Incomplete list of interesting things:
- certain properties like
list-style-image
,background-image
,border-image
,content
,cursor
,filter
and their respective shorthand notations if applicable - certain property values like
url()
,image()
,calc()
,"progid:…(…)"
with or without whitespaces, quotes etc. - certain selectors so people can only affect certain parts of a page and aren't easily able to hide
iframe
,object
or similar elements - allow/disallow absolute/relative URIs for
url()
andimage()
and perhaps more? -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
or similarprogid
stuffopacity: 0.01
to make transparent buttons clickable in IE ;)- css at rules like e.g. targeting FF via
@-moz-document url-prefix() { … }
, the obvious@import
and whatever else there's available via such rules - the whole
@font-face { font-family { src: … } }
stuff plusunicode-range
,font-feature-settings
and whatnot - DOS relevant stuff like animations and advanced filters or new features that may not only render browsers unresponsive but may also be used to trigger crashes when there are bugs in hardware rendering support or whatever user agents do nowadays when they get creative
- probably lots of other stuff I can't think of atm. :-)
Thanks for DOMPurify!
from dompurify.
@graste Thanks! So, here's what I think is possible. Let's assume the following files:
//test.html
<link rel="stylesheet" href="test.css">
<p>blafasel</p>
/* test.css */
* {
color: blue;
background: red;
}
What we can do to find out about CSS property-value details is the following (very ugly code, demo only):
for(var i in styles = document.styleSheets) {
for(var j in styles[i].cssRules) {
for(var k in rules = styles[i].cssRules[j]) {
if(rules[k] instanceof CSS2Properties){
for(var l in rule = rules[k]) {
if(isNaN(l) && rule[l] && typeof rule[l] === 'string') {
console.log(l + ':' + rule[l])
}
}
}
}
}
};
So, as you can see we can go over all CSS property-values and decide if we like them or not - by whatever criteria we choose. After that we simply assemble a new style sheet and throw it into the sanitized document. Done. No risk for browser weirdness, no massive overhead.
So we don't have to parse, use regex or anything to get hands on the important data.
Now the tricky question is: What do we validate against? A white-list of properties? A conformity pattern for values? A conformity pattern for selectors? Depending on the context, different requirements might exist. And once we have them - how do we allow users to configure them?
Technically, CSS sanitation is possible in the DOM. But what API do we offer to do it?
from dompurify.
No fast answers here. The obvious thing would be a whitelist of properties. I'm not sure about sanitizing property values as I'm not sure if browsers skip weird values already (I'd guess so, though). Allowing only certain values for certain properties would be cool, but I'm not sure if that's worth the effort or if devs even want to configure something like that.
How about some sensible defaults or config options like this:
allow_external_resources
(default:false
) to disallowurl
,src
,image
etc. by default. For finer grained access one could support something likeallow_url
,allow_external_resources_on: ['cursor', 'background', 'background-image'…]
.- when allowing external resources it would be nice to allow only certain URI schemes or disallow absolute URIs altogether (use case would probably be theming with external resources from the current domain or self uploaded stuff from a specific asset subdomain) - e.g.
allow_absolute_uris
orallowed_uri_prefixes: ['https://assets.foo.com', 'https://flickr.com/']
- people allowing this are obviously still vulnerable to open redirects etc. and it may not be advisable to even allow such a feature… ;-) allowed_at_rules: ['@font-face']
ordisallow_at_rules
altogether?allow_calc
,allow_progid
etc.allowed_selectors: ['.foo', '#bar > baz'…]
to be very strict about what parts of a page may be usd for styling purposes.selector_prefix
to add to every rule with some selector like#special > area
to limit the ease of defacing or abusing certain parts of a page via linked/embedded stylesheets. A simple mitigation for such a prefix to still render a page unusable would obviously be something like:.foo.foo.foo.foo.foo { position:fixed;width:100%;height:100%;top:0;left:0;pointer-events:none;z-index:999999; }
, so I'm not sure if that would be worth the hassle. :-)
tl;dr: I'm really not sure. Except for disallowing calc
and all usages of external resources as a sensible default.
PS: What about Data-URIs? I don't know where they can be a special problem in CSS.
from dompurify.
I am tempted to think we need a new project for this - CSSPurify :)
from dompurify.
:-)
from dompurify.
So, after having a bit of a look at how browsers use the CSSOM some new problems arose. I was hoping that upon accessing the CSSOM's properties, the user agent would normalize so a benefit of a potential CSSPurify would be not to be forced to deal with obfuscated CSS. I was wrong.
Here's an example:
<!-- test.html -->
<style>
* {
color: red;
background: blue;
border: /**/C\41lc(10px + 10px) solid green;
}
</style>
<p>000</P>
console.log(document.styleSheets[0].cssRules[0].style.border)
- In Firefox we get this as a result:
calc(10px + 10px) solid green
- This is what we expect. We could work with this.
- In MSIE 11 we get this:
empty string
- NOTE:
border
is empty - butborderBottom
is not and yieldsCAlc(10px + 10px) solid green
. I have no words.
- NOTE:
- In Chrome nothing happens, no
calc()
in this obfuscated form
So you can see, browser implementations don't seem to be ready for a CSSPurifer yet. Alas we are talking about a very strict whitelist. Thoughts on this are very welcome ;)
from dompurify.
It gets better. Chrome cannot deal with the CSS escape inside the property name.
It works with this code though (no \41
): border: /**/Calc(10px + 10px) solid green;
The result of the JavaScript call? Watch closely:
calc(20px) solid green
« We actually get the calculated value as a result, still wrapped by calc()
.
from dompurify.
I am tempted to think we need a new project for this - CSSPurify :)
Yes, please do so, we could add a hook to get this into DOMPurify later on. I'd love to keep the focus on this project. ;)
from dompurify.
Awesome examples with calc. I would've guessed (hoped) there are better parsers in browsers nowadays. :-)
from dompurify.
Locking down position to static would also be desirable, as restricting width and height to maximum values. These enable attackers to create overlays, which hijack clicks and redirect users to phishing pages.
from dompurify.
Please file bugs for the browser bugs you find. Thx
from dompurify.
I decided to close this: DOMPurify will not support sanitizing CSS. I am however open to contribute to a CSSPurify project is anyone is interested to set one up. I believe there is a need and we have enough knowledge here to be able to do it.
from dompurify.
@cure53 is there any place where current state of CSS sanitation mentioned? Am I not safe by default, doing DOMPurify.sanitize() on, say <div style="some possibly malicious CSS">
? Do I need to use hooks and manually remove stuff I consider malicious?
from dompurify.
Yes, CSS-based attacks are not part of our threat model. We prevent XSS and DOM Clobbering.
from dompurify.
Related Issues (20)
- content of style tag gets removed HOT 3
- Question to understand how to remove an attribute but keep the tag HOT 2
- Use DOMPurify with `<!DOCTYPE NETSCAPE-Bookmark-file-1>` files? HOT 3
- DOMPurify stripping valid html in xhtml mode HOT 5
- Grunt build fails while building with the latest version of purify.min.js HOT 5
- Trying to use in Angular 16, getting "CommonJS or AMD dependencies can cause optimization bailouts." HOT 1
- JavaScript errors in purify.js HOT 5
- XSS injection vulnerability HOT 3
- User controlled markup vs programatic markup generation HOT 11
- Consider supporting happy-dom HOT 7
- How to keep !important for a css attribute? HOT 6
- Question regarding USE_PROFILES config option HOT 5
- Question regarding local hooks HOT 1
- Add hook on element/attribute removal HOT 8
- Unknown element should never be considered as void HOT 11
- `>` as text node should not be escaped HOT 4
- Return removed elements after sanitize call HOT 10
- Why attitudes are resorted after purified HOT 11
- How to allow all tags except <script> HOT 6
- Using DOMPurify to render unicode values properly HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dompurify.