I have read in several places that scripts are not executed when we use React dangerouslySetInnerHTML
to insert a html fragment.
However I just tried to insert this:
<img src= "img.png" onload="alert('picture loaded')" alt="script test">
And the alert was triggered.
That doesn't really surprise me (that's why I did the test in the first place), but I'd like to better understand what we mean by "scripts don't execute".
My questions:
- apart from my example above, are there other types of scripts that will execute?
- is there a way to fully prevent script execution, including those embedded in html event handlers like in my example?
- if a script tag defines a function, will that function still be loaded and be callable later?
- any other behavior I should be aware of?
[Edit] I am using dangerouslySetInnerHTML
in a function component:
const htmlString = '<img src="img.png" onload="alert('picture loaded')" alt="script test">'
In the return statement (JSX):
return <div dangerouslySetInnerHTML={{__html: htmlString}} />
The scripts that "will not execute" are script tags, like
<script>
. See here for an example:Inline handlers, not being
<script>
tags, can run, if the event they're attached to fires. (Above, an<img>
tag with asrc
property but no valid path throws an error, so itsonerror
inline handler runs)There are no other categories of scripts that will run in combination with
dangerouslySetInnerHTML
(unless an inline handler itself injects a<script>
by other means, like withdocument.createElement('script')
).You'll need to remove the
on-
attributes. If allon-
attributes are removed, no events which may be fired will ever result in unexpected scripts running. You could sanitize the input by sending it through DOMParser first:No, because the
<script>
tag will not have run at all, so nothing that goes on inside of it will do anything; functions defined inside will not become visible. For such a thing to occur, you'd have to deliberately reload the newly injected<script>
tag somehow, in a manner that gets it to run.