Jon Freynik
Jon Freynik

Reputation: 369

How does angularjs prevent inline script tags from executing?

I was interested to know how AngularJS prevents inline <script> tags from executing when they are included via the ng-include directive.

After a template is included and the DOM is inspected, the script tags certainly exist, but they have not been executed. How are they being disarmed?

I have begun reviewing the source code but any attempt I have made to include a script tag into the DOM myself (appendChild, innerHTML, innerText, document.write, etc.) always results in it being executed.

Thank You.

Upvotes: 4

Views: 1148

Answers (2)

georgeawg
georgeawg

Reputation: 48968

That is an artifact of the way jqLite is implemented.

To make script tags work, simply ensure that the jQuery library is loaded before the angular.js file.

  <head>
    <script src="//unpkg.com/jquery"></script>
    <script src="//unpkg.com/angular/angular.js"></script>
    <link rel="stylesheet" href="style.css">
    <script src="script.js"></script>
  </head>

The DEMO on PLNKR.


if you explain more that innerHTML is enough to prevent the script tags from executing I will select your answer as correct

HTML5 specifies that a <script> tag inserted with innerHTML should not execute.

However, there are ways to execute JavaScript without using <script> elements, so there is still a security risk whenever you use innerHTML to set strings over which you have no control. For example:

const name = "<img src='x' onerror='alert(1)'>";
el.innerHTML = name; // shows the alert

For that reason, it is recommended you not use innerHTML when inserting plain text; instead, use Node.textContent. This doesn't parse the passed content as HTML, but instead inserts it as raw text.

For more information, see MDN Web API Reference - Element.innerHTML.

Upvotes: 2

Jon Freynik
Jon Freynik

Reputation: 369

It looks like ng-include calls $element.html(ctrl.template); See source on GitHub

The html function of jqLite then uses element.innerHTML = value; to insert the content. See source on GitHub

And after testing - it looks like that is enough to not execute <script> tags.

I've created a jsFiddle here. - #3 is the equivalent of what AngularJS is doing and it does not execute the script tags.

Upvotes: 0

Related Questions