-
-
Notifications
You must be signed in to change notification settings - Fork 751
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow arbitrary attributes and their values for configured custom elements #602
Conversation
Did I mention I hate prettier? 🗡️ |
…lements * added basic custom element tagname test so we don't open the floodgates with `ALLOWED_CUSTOM_ELEMENTS: /script/` adjusted tests added comments explaining what is going on new build fixed broken test
Good morning, just quick FYI, I removed the conflicts, no other PRs expected from my end today, so things should stay conflict-free :) |
test/test-suite.js
Outdated
@@ -593,15 +593,15 @@ module.exports = function (DOMPurify, window, tests, xssTests) { | |||
); | |||
assert.equal( | |||
DOMPurify.sanitize( | |||
'<foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div', | |||
{ ALLOWED_CUSTOM_ELEMENTS: (tagName) => tagName.startsWith('foo-') } | |||
'<foo-bar bas="foobar"></foo-bar><div is="foo-baz"></div>', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bas
should be baz
test/test-suite.js
Outdated
), | ||
'<foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>' | ||
); | ||
assert.equal( | ||
DOMPurify.sanitize( | ||
'<foo-bar baz="foobar"></foo-bar><div is="foo-baz"></div>', | ||
{ ALLOWED_CUSTOM_ELEMENTS: (tagName) => tagName.endsWith('-bar') } | ||
'<foo-bar bas="foobar"></foo-bar><div is="foo-baz"></div>', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bas
should be baz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I fix real quick?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please. I'd be happy not to have to do another fork and PR for this.
Thank you for that, but some changes you introduced make two tests fail, see my review comments above. |
I still have the conflicted version on my hard drive, not sure how to test without fixing that first. |
Just tested that agains our "components onepager", looking fine to me. To make this config option a little more secure, I think we need to make a better check if it's a custom element in the future, without introducing a massive performance drop with the option enabled. |
What risks do you presently see here - i.e. how would the existing check be bypassable? |
I'm not a security person, and thus, I have no idea. But I know there's alot of very creative ways to bypass security measures implemented by people whose main concern isn't security. |
So, what I think will bite us in the ass right now is this: https://w3c.github.io/mathml-core/#dfn-annotation-xml Because, this would be falsely detected as a custom element, no? |
The basic check would let that pass, because it only detects the presence of a |
Not sure yet, but it's not a custom element but it will be detected as one. And Firefox fully supports it via MathML. Further, are we sure we want to really allow any attribute name for custom elements? Like, why do we allow |
Probably we ideally wouldn't, but remember all this only happens if a user decides they need/want that. Also, if the attribute is in the forbid list, isn't it still eradicated? Need to walk the dog now, back in 20 minutes. |
Correct, but the user has likely no idea that this exists. Also, will the user be aware that this will work? DOMPurify.sanitize(
'<annotation-xml><x-y onclick=alert(1)></x-y></annotation-xml>',
{ALLOWED_CUSTOM_ELEMENTS: /\w+-\w+/ }
) |
There is no forbid-list. We only have an allow-list. |
It should be quite obvious to everyone that this will open the floodgates: |
I am talking about the attributes, mostly. Like, same thing here: DOMPurify.sanitize('<x-y onclick=alert(1)>AAA</x-y>', {ALLOWED_CUSTOM_ELEMENTS: /-y$/ }) I am fairly fine with the element checks, we might have to add a case for |
A regex or predicate for that imo would only serve one purpose: It would make it clearer to the user what they are allowing. It is practically impossible to whitelist those attributes. On the other hand it would also slow down the purification process, and it would make the whole feature harder to use. It's you library, so it's up to you to decide. I just need a solution that allows me to a) use DOMPurify with custom elements, and through this, allows me b) to enable Trusted Types. If that helps, we could check if |
So, right now we allow any attribute in case an element passes a certain check. This cannot stay as is. We must that it is not possible too use custom elements to smuggle in risky attribute, there is no way around that.
This is a terrible idea and we cannot do that. |
I see only one way here: Re-enforce the attribute allow-list for custom elements and give a developer the chance to allow-list more (we have that already) and potentially define a wider pattern (i.e. via regex or alike). |
If you want to discuss the issue on the phone, feel free to give me a call. Find my contact details on https://connexo.de/kontakt.php |
Thanks for the good call, proposal currently is:
|
Bundling related config options in an object would be what I would do: CUSTOM_ELEMENT_HANDLING: Object.seal(Object.create(null, {
tagNameCheck: { writable: true, configurable: false, enumerable: true, value: null },
attributeNameCheck: { writable: true, configurable: false, enumerable: true, value: null },
allowCustomizedBuiltInElements: { writable: true, configurable: false, enumerable: true, value: false },
})) |
Hmmm, this looks reasonable.Works for me! As long as the defaults are strict and prohibitive, this should be good. |
Just out of curiosity, why is prohibiting |
a) Block-lists are by design dysfunctional in security |
I assume I can't make use of |
Yes, I kicked MSIE10 out last night but MSIE11 we cannot give up on yet. |
Does DOMPurify in certain cases change the order of attributes? Getting this test fail:
this being the input |
It is possible that browsers to that in several situations. |
Can I rely on that order and adjust |
I would say so, yes - but sometimes, we sadly need to add several expectations to cover that. Ugly but necessary. |
If DOMPurify output would not be deterministic in all cases, I guess we'd have bigger problems. |
Well, we are a sanitizer, not a markup manager. And sometimes, browsers mess with the order of things, attribute names, etc. etc. - nothing much we can do about that. Check this for example: https://github.com/cure53/DOMPurify/blob/main/test/fixtures/expect.js#L6 Many different ways how an SVG can end up. |
How are browsers involved in this? I was assuming DOMPurify parses and processes Strings, and outputs Strings. |
Completely faulty assumption, we utilize the browser to create a document which we sanitize. Then we return the sanitized document as string, node, fragment or whatever people like :) |
Interesting, how is that document creation not unsafe in and of itself? Just curious. |
https://developer.mozilla.org/en-US/docs/Web/API/DOMParser Both allow creating documents that don't execute scripts. |
Very interesting, since afaik |
Nope :) This way is safe: https://github.com/cure53/DOMPurify/blob/main/src/purify.js#L726 |
Ah, it's just Domparser.parseFromString that is an XSS sink. Which is what you're using! |
It's not an XSS sink :D Unless you use what comes out on a live document. |
Well Google says so in that article. |
We're going off-topic here. The way we use DOMParser is safe and needs no review at the moment. |
I've raised an issue on web.dev. GoogleChrome/web.dev#6890 Feel free to comment there. |
Back to our original topic, tests are all green now and expected results fit. Creating a PR now. |
PR is ready and good to go. One build job fails because |
ALLOWED_CUSTOM_ELEMENTS: /script/
This pull request fixes #601, which is a followup for #596.
Dependencies
If there are any dependencies on PRs or API work then list them here.