Comments (12)
Oh, that sounds bad, I'll have a look right away!
from dompurify.
I can reproduce the issue.
I think the problem here is the following: MSIE seems to recurse over this operation, because it appears to create a new textNode
each time the text of the existing textNode
is set.
That means, that upon setting the text, a new node appears that needs to be sanitized, then text is being set, creating a new textNode
... and so on. Edge by the way has the same problem. I am looking into how to fix this now...
This example hangs:
DOMPurify.addHook('afterSanitizeElements', function(node) {
if (node.nodeType && node.nodeType === document.TEXT_NODE) {
node.textContent = 'foo';
}
return node;
});
This example does not:
DOMPurify.addHook('afterSanitizeElements', function(node) {
if (node.nodeType && node.nodeType === document.TEXT_NODE) {
node.innerText = 'foo';
}
return node;
});
from dompurify.
Okay, I came up with a first possible fix:
https://github.com/cure53/DOMPurify/compare/Experimental_Fix_for_89?expand=1
This fix stores a copy of the currently processed mode as oldNode
, then compares the new incoming node (then currentNode
) to the old node. If the new node and the old node are identical, the node iterator is told to step ahead one call and continue from there. This fixes the problem of IE and doesn't seem to affect other browsers. The tests are still running as expected.
This could be a security critical change so I'd kindly ask for review, @fhemberger and @neilj. I also think the fix is ugly but I cannot come up with something better right now.
from dompurify.
A few thoughts:
- I'm not convinced that the IE behaviour is wrong. The spec is slightly ambiguous, but I could certainly interpret it as saying you should replace the whole text node. The rules of the NodeIterator means the new node then comes after the cursor, so is returned next. As such, I don't see anything wrong that necessarily needs to change with the current code in DOMPurify: this should be fixed by the code using it (my recommendation is to simply replace
textContent
withdata
, since this then sets the data of the text node itself, which is what was originally intended). You could just as easily create an infinite loop by inserting a new element after the current element in a hook; this doesn't meant the library itself is broken. - If you still do want to patch this particular case in the library, I don't think your fix will work (although I haven't actually checked, as I don't have IE handy). From the description above, the problem is that the text node is replaced. Therefore
currentNode === oldNode
would always be false, because they are different nodes, so you would still infinite loop. Also, the code formatting is completely inconsistent with the rest of the library:
if(currentNode === oldNode){
nodeIterator.nextNode()
}
There should be a space after the if
and before the {
, and the next line is indented too much.
from dompurify.
@neilj The hang also happens with data
and other properties/methods on Text
. It seems only innerHTML
and innerText
are fine and I would not recommend using them here. IE appears to be "empirically" wrong as all other user agents don't cause a recursion and honestly, the code doesn't look like it should. Yet it still does because we use the node iterator internally. So it is at least partly our fault.
The fix surprisingly works, because in this situation, the result is indeed true
. I didn't believe it myself at first but it is the case. So factually, the fix does tackle the problem, just not in a nice or logical way. But that's IE.
About the coding inconsistencies: True, you are 100% right. But at this stage of the fix (merely experimenting in an experimental branch) I don't care too much. Cosmetics when cosmetics are due. Now I want to find a working and reasonable fix.
from dompurify.
Fine. So actually IE is doing something very weird, not simply replacing the text node then. In that case, I have one small change I think. Instead of:
if (currentNode === oldNode) {
nodeIterator.nextNode()
}
I think you want:
if (currentNode === oldNode) {
continue;
}
We've already processed the old node, yes? So we don't want to process it again. The current code (if I understand the IE bug correctly now) skips the first node after the text node that's replaced, which is potentially a security hole.
from dompurify.
That makes much more sense, thanks! I'll add a test-case and then will post the diff here again for review.
from dompurify.
Okay, ready for review again:
https://github.com/cure53/DOMPurify/compare/Experimental_Fix_for_89?expand=1
from dompurify.
That looks good to me.
from dompurify.
Thanks, merging...
from dompurify.
@luhmann From what I can see we are good to close this issue. Any thoughts?
from dompurify.
Fix works perfectly for me. Thank you very much for the quick help.
from dompurify.
Related Issues (20)
- Uncertain how to handle 'non-standard' HTML HOT 3
- Need to block external calls, e.g. all HTTP requests HOT 7
- Why does name="name" on an input field get purified? HOT 1
- Exception when passing 0 or "" or null to Dompurify.Sanitize Method #947 HOT 3
- Latest versions of DOMPurify 2.5.x block custom SVG elements when they are set via ADD_TAGS config. HOT 6
- release 3.1.3 assets are the same as 3.1.2 HOT 1
- Number.isNaN is not supported in MSIE HOT 15
- Bower issues : DOMPurify is not defined HOT 5
- HTML and BODY tags are being regardless of `ALLOWED_TAGS` settings HOT 2
- MAX_NESTING_DEPTH remove contents issue HOT 5
- Escape unsafe characters instead of removing them HOT 3
- The MAX_NESTING_DEPTH remove contents issue has not been resolved. HOT 3
- A code comment containing a tag name structure leads to removal of the entire block HOT 2
- Issue secure [email protected] Apache-2.0 + Fair + MPL-2.0 HOT 1
- KEEP_CONTENT remove contents of all ALLOWED_TAGS HOT 2
- <img> xss vulnerability
- MathML Content Markup Removed HOT 2
- Policy creator HOT 2
- name='lang' Attribute Removed During Sanitization HOT 1
- DOM Purify Allows onfocus events HOT 1
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.