<script> created by innerHTML setter on element not in the document, followed by adding the element to the document, executes the script, unlike html5 spec

RESOLVED FIXED

Status

()

Core
DOM
RESOLVED FIXED
11 years ago
8 years ago

People

(Reporter: Savu Andrei, Unassigned)

Tracking

({testcase})

Firefox Tracking Flags

(Not tracked)

Details

(Whiteboard: [fixed by the HTML5 parser])

(Reporter)

Description

11 years ago
User-Agent:       Opera/9.23 (X11; Linux i686; U; en)
Build Identifier: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.6) Gecko/20061201 

When trying to insert javascript code by using innerHTML in an already existing element the browser will not interpretate it but if you use document.createElement and insert the unescaped javascript in the new element and the append it somewhere the browser will interpretate the javascript code. This works only on Firefox, Opera and Internet Explorer will not interpretate the code.

Sample code : 

<html>
<head>
	<script type="text/javascript">
	<!--
	window.onload = function() {
		var btt = document.getElementById('put_message');
		btt.onclick = function() {
			var txt = document.getElementById('message');
			var mesaj = 'text<script type="text/javascript">';
			mesaj += "alert('xss');";
			mesaj += '</script>';
			cld = document.createElement('div');
			cld.innerHTML = mesaj;
			txt.appendChild( cld );
		}
	}
	-->
	</script>
</head>
<body>
	<div id="message">
		Standard message.
	</div>
	<button id="put_message">Do action</button>
</body>
</html>


Reproducible: Always

Steps to Reproduce:
1. Use the code submited
2.
3.
Actual Results:  
An alert box.

Expected Results:  
Should not interpretate javascript.
Why is this a security issue? You need to already be running script on the site to dynamically insert a <script> element, and if the site is blindly inserting HTML into itself without sanitizing it then that's the site's problem, as things currently stand.

You can create a <script> object using createElement and dynamically set it's src, that's just expected behavior. This is just another way of achieving the same goal. I say this is INVALID.
Component: General → DOM
Product: Firefox → Core
QA Contact: general → general
(Reporter)

Comment 2

11 years ago
I think this is unsafe. If the user wants to run some javascript it should explicity call eval on it ( get it using an ajax call ). Is there any standard for this kind of behaviour? I have tested and it seems that Opera and IE6 don't have this "feature".
(Reporter)

Comment 3

11 years ago
Anyway this inconsistent behaviour.

Comment 4

11 years ago
For background, see:
* Bug 214874
* Bug 147581
* Bug 127016
* http://www.whatwg.org/specs/web-apps/current-work/#innerhtml0, which says "Note: script elements inserted using innerHTML do not execute when they are inserted."
* http://www.whatwg.org/specs/web-apps/current-work/#script0, which talks about an "already executed" flag.

I don't know whether HTML5 specifies this either way.  I'll ask Hixie.
Blocks: 301375
Severity: critical → normal
Keywords: testcase
Summary: XSS : append child with javascript will automatically call eval → <script> created by innerHTML setter on element not in the document, followed by adding the element to the document, executes the script

Comment 5

11 years ago
Not a security hole.  If a site is sticking untrusted markup into a document using innerHTML, it's screwed even if Firefox's <script> behavior changes.  For example, an attacker could use <img onload> instead.

Use "document.createTextNode(s)" or ".textContent=s" if you're just trying to insert text.
Group: security

Comment 6

11 years ago
<Hixie> the spec does cover it
<Hixie> jruderman: search for "If the parser was originally created for the HTML fragment parsing algorithm, then mark the script element as "already executed""

http://www.whatwg.org/specs/web-apps/current-work/#scriptTag

So this is a bug in Gecko, assuming our goal is to comply with HTML5.
Or a bug in HTML5.

In any case, what we do right now is disable script execution during innerHTML setting.  But scripts not in the DOM never try to execute, so never discover this and never flag themselves as "tried to execute".  We could change that if that's really what we want, but is it really what we want?

In any case, is this really related to bug 301375?

If our goal is to comply with HTML5, by the way, at some point we will need to go though the (CR) spec with a fine-toothed comb and file bugs on all the places where we deviate from it.  Do we have a tracker?
Status: UNCONFIRMED → NEW
Ever confirmed: true
Summary: <script> created by innerHTML setter on element not in the document, followed by adding the element to the document, executes the script → <script> created by innerHTML setter on element not in the document, followed by adding the element to the document, executes the script, unlike html5 spec
HTML5 can change to whatever you need to achieve compat with the Web. Just let me know.
Does anything on the web depend on the Opera/IE behavior?  Or just on the behavior of not running script during the innerHTML set?

Updated

11 years ago
Duplicate of this bug: 425197

Comment 11

11 years ago
In my version of this bugreport, Bug 425197, I attached two examples, one which executes the JavaScript and one which doesn't. The only difference between them is the order in which .innerHTML is assigned and the element is added to the DOM tree.

The behaviour is clearly inconsistent. You either want to execute the JavaScript or you don't. Either way, one of the two behaviours need to change.

Now, personally I think it should *not* execute, judging from what it says in the spec.

Comment 12

10 years ago
Maybe a better question to ask is what is the rational behind the HTML5 WG's "no excuting script tags in innerHTML tree inserts"?

Comment 13

8 years ago
sample code is (no longer) interpreted in Mozilla/5.0 (X11; Linux x86_64; rv:2.0b6pre) Gecko/20100909 Firefox/4.0b6pre

Comment 14

8 years ago
Is this (the fact that Gecko ignores "innerHTML tree inserts") the reason why the script on http://www.oele.net/innerhtmljs.html won't execute in FF4? 

It works on Opera 11, Chrome 8 & FF 3.6. 

This is the reason why the "now playing" list on http://www.radioparadise.com/ won't load. 

Just wanted to make sure that this is indeed considered the "desired behaviour". It does seem to break at least one website that works in other browsers.
Hmm.  That looks like a regression from the HTML5 parser (effectively due to it fixing this bug).  Could you please file a separate bug on that?
This bug has been fixed.

Comment 14 asks for part of the fix to be reversed.

http://www.oele.net/innerhtmljs.html doesn't run the alert in IE9, either, so I think Firefox 4 and HTML5 are doing OK as far as interop goes.
Status: NEW → RESOLVED
Last Resolved: 8 years ago
Resolution: --- → FIXED
Whiteboard: [fixed by the HTML5 parser]
You need to log in before you can comment on or make changes to this bug.