If go a bit deeper in jQuery source code, we can find html method.
In this method exist next line
this.empty().append( value );
If now go to append, we can find next
append: function() {
return domManip( this, arguments, function( elem ) {
if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
var target = manipulationTarget( this, elem );
target.appendChild( elem );
}
} );
}
So, now find domManip. Inside this function from html-string builded fragmen, and if fragment have script tag execute next code
DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
Where DOMEval
function DOMEval( code, doc ) {
doc = doc || document;
var script = doc.createElement( "script" );
script.text = code;
doc.head.appendChild( script ).parentNode.removeChild( script );
}
So, at least, we find place where execute scripts.
So, why in some case html run script and otherwise not?
This depends on input string and what return buildFragment function.
Inside buildFragment we can found next line
tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
where elem is input string, and jQuery.htmlPrefilter is next function
htmlPrefilter: function( html ) {
return html.replace( rxhtmlTag, "<$1></$2>" );
}
so, input string just replaced with some regular exporession rxhtmlTag.
rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
So, just try this for checking string:
console.log(jQuery.htmlPrefilter("<iframe><iframe //><script>alert(1)</" + "script>"));
console.log(jQuery.htmlPrefilter("<iframe><iframe> // <script>alert(1)</" + "script>"));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
So, in first case as result was
<iframe><iframe /></iframe><script>alert(1)</script>
And after insert it as innerHTML in tmp div, inside div create two elements: iframe and script. So after this script available for finding and executing
In second case:
<iframe><iframe> // <script>alert(1)</script>
String not changed, and after insert it as innerHTML in tmp div, inside div create just one iframe element with encoded content. That's why in this case script not execute.
//is not an html comment...they look like<!-- -->bandcdoesn't execute with .html()?