Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is Javascript/jQuery DOM creation safe until it's added to the document?

Please read this statement carefully: let's assume before ANY elements are added to the document all unsafe elements in $dom have been removed. But they were initially created. Ok let's continue....


If a piece of user text is processed and can possiblity be loaded like so:

var comment = 'I\'m a naughty person!!' +               '<script src="http://blah.com/some_naughty_javascript.js">'; var $dom = $('<div>' + comment + '</div>'); 

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

For example:

var $dom = $('<script>alert("hi");</script>'); 

Obviously the message hi does not pop up until it's added to the document. But:

  • Can any tag or anything created in this manner be dangerous?
  • Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

Bounty Edit

So as outlined in the answers below, it seems this method isn't very safe, particularly for one reason:

  • var $dom = $('<img src="blah.jpg"/>') -- this will request for the image straight away, regardless of if the object was added to the document.

This creates a major problem for dealing with HTML ajax requests. For example if we wanted to get the values from the inputs of the form:

$.ajax({   url: 'test.php',   success: function(responseHTML) {     var inputs = $(responseHTML).find('form input');   } }); 

This will involuntarily cause all images to be requested for by the browser.

Bounty is awarded to anyone:

  • Who can provide a nice, safe way of dealing with ajax requests without the above issue.
  • Ideally doesn't provide a regex answer... i.e. what if we wanted to do $(responseHTML).find('img') -- removing image tags with regex can't be an option, so an unobtrusive way would be needed to stop the src from loading, but still have the same attributes, structure, etc.
like image 326
Gary Green Avatar asked Apr 08 '11 11:04

Gary Green


People also ask

Which is better DOM or jQuery?

Pure JavaScript can be faster for DOM selection/manipulation than jQuery as JavaScript is directly processed by the browser. jQuery has to be converted into JavaScript to make it run in a browser. All these can be done in JavaScript but we may have to write many lines of code.

Does jQuery manipulate the DOM?

Projects In JavaScript & JQueryjQuery provides a number of methods to manipulate DOM in efficient way. You do not need to write big and complex code to set or get the content of any HTML element.

Why do we need to use jQuery document ready event?

jQuery ready() Method The ready event occurs when the DOM (document object model) has been loaded. Because this event occurs after the document is ready, it is a good place to have all other jQuery events and functions. Like in the example above. The ready() method specifies what happens when a ready event occurs.

What is DOM and jQuery?

One of the most important aspects of JavaScript and thereby jQuery, is manipulation of the DOM. DOM stands for Document Object Model and is a mechanism for representing and interacting with your HTML, XHTML or XML documents.


1 Answers

Is this by itself dangerous in any way? My point being, can just the simple act of creating a DOM somehow inject anything, or is it just simply processed and the structure is created?

Simply creating an element without appending it to the dom will not cause any script to run since it is purely an object at this point (HtmlScriptElement). When it is actually appended to the dom the script element will be evaluated and ran by the browser. With that being said I suppose it is possible that an extremely crafty person could exploit a bug that is present in some framework or browser you might be using to cause an undesired outcome.

Consider this example:

<p>     <input type="button" value="Store 'The Script' In Variable" id="store"/>     <input type="button" value="Append 'The Script' To Dom" id="append"/> </p> <br/> <p>     <input type="button" value="Does nothing"/> </p> <h1>The Script</h1> <pre id="script">     $(function(){         function clickIt(){             $(this).clone().click(clickIt).appendTo("body");         }         $("input[type='button']").val("Now Does Something").click(clickIt);     }); </pre>  var theScript;  $("#store").click(function() {     theScript = document.createElement('script');     var scriptText = document.createTextNode($("#script").text());     theScript.appendChild(scriptText); });  $("#append").click(function() {     var head = document.getElementsByTagName('head')[0];     head.appendChild(theScript); }); 

When you click on store it will create the HtmlScriptElement and store it into a variable. You will notice that nothing is ran even though the object is created. As soon as you click append the script is appended to the dom and immediately evaluated and the buttons do something different.

Code Example on jsfiddle


Can any functions in javascript/jquery "watch" for elements being created in this manner and act on it BEFORE it's been stripped of bad elements and put on document?

jQuery sort of does that for you already as it does some internal script eval


From Karl Swedberg post on .append()

All of jQuery's insertion methods use a domManip function internally to clean/process elements before and after they are inserted into the DOM. One of the things the domManip function does is pull out any script elements about to be inserted and run them through an "evalScript routine" rather than inject them with the rest of the DOM fragment. It inserts the scripts separately, evaluates them, and then removes them from the DOM. ...

You could alter the behavior of jQuery to remove all <script/> and sanitize other elements with inline javascript onclick, mouseover, etc when calling append() however that will only affect jQuery as someone could easily use vanilla javascript to append the <script/> element.

Dom Mutation Events

Dom Level 2 does defined some Dom mutation events to capture elements that are added to the dom one would look towards the event, DOMNodeInserted. However it is fired after the element has already been added. note, per Raynos these are currently deprecated.

DOMNodeInserted Fired when a node has been added as a child of another node. This event is dispatched after the insertion has taken place. The target of this event is the node being inserted. Bubbles: Yes Cancelable: No Context Info: relatedNode holds the parent node

In the end it appears there is no totally stop a <script/> being appended to the dom via some other javascript. (at least not that I can find).

The best way I can suggest is to never ever trust user input as all user input is evil. When you do dom manipulation double check to make sure there are no forbidden tags, be it <script/> or even plain <p/> elements and sanitize all input before it is persisted.

Also as John points out you need to worry about any element that can attach a onclick event or any inline javascript event handler.

like image 54
Mark Coleman Avatar answered Sep 18 '22 19:09

Mark Coleman