1

Is it possible to use the built in HTML escaping from angular outside of a binding?

The functionality (that angular uses that i wish to use elsewhere) is illustrated below

//in controller
$scope.blah = '<script>alert(1)</script>';
<!-- template -->
<p>{{blah}}</p>

This will render the text with HTML escaped. I want to use the same functionality to escape html, is there a way this can be exposed?

EDIT

I think my question might have been particularly unclear. I want to replicate the built-in functionality that escapes HTML automatically when binding to a scope variable in a template, but I am not using an angular template. The code runs in a controller, but I am injecting mixed content.

The following is a better example of what I'm trying to do. This is in a controller:

$http.get('/endpoint.json').success(function(data) {
  someLib.setHTML('<a href="foo">' + data.name + '</a>');
});

I need to use HTML but I want to escape data.name, can I access the same functionality that angular itself uses?

8
  • Hmm, someone just suggested $sanitize, but answer got deleted. Anyway, I would prefer not to have to use $sanitize, and given that the functionality is already in angular it would be nice to not have to load additional modules. Commented Mar 24, 2015 at 12:16
  • why do you want to store<script> tags within scope variables, and what is the functionality you think you want to achieve from this Commented Mar 24, 2015 at 13:03
  • that was just an example, i want to get data from the server (which may be user editable) and put it into a html context, outside of an angular binding Commented Mar 24, 2015 at 13:05
  • you mean to say like from the server you are getting some html content which it will receive within a scope variable and you want that to be displayed in html Commented Mar 24, 2015 at 13:07
  • Take a look at my answer Commented Mar 24, 2015 at 13:19

4 Answers 4

2

Disclaimer

There's a very good reason they started sanitizing stuff back in 0.9, it's a security risk. I don't recommend doing this.

You can make a custom directive, I think that's the shortest way of doing this without messing with Angular internals.

Code

angular.module('app', [])
.controller('Ctrl', function($scope) {
  $scope.html = '<script>alert(1)</script><script>alert(2)</script><p>Please dont do this</p>'
})
.directive('myUnsafeDirective', function() {
  return {
    restrict: 'A',
    scope: {
      'html': '=myUnsafeDirective'
    },
    link: function(scope, element, attrs) {
      var toInsert = angular.element(scope.html);
      element.append(toInsert);
      var scripts = element[0].getElementsByTagName('script');
      for (var i = 0, l = scripts.length; i < l; i++) {
        eval(scripts[i].text)
      }
    }
  }
})

HTML

<body ng-controller="Ctrl">
  <p my-unsafe-directive="html"></p>
</body>

DEMO

I strongly recommend you don't do this, and I don't think even sanitize will let you eval random snippets of code like this. At the very least strip away the eval part and just insert the element, but honestly, the sanitize module is around 6kb before compression and it really is better to include it.

If this usecase originates from the need of some kind of CMS functionality on the server, then also make sure to have strict rules around what kind of markup is allowed. There are tons of ways to trick browsers into executing random code that are way more devillish than a script tag, and if you use sanitize you will be protected from most of them.

Sign up to request clarification or add additional context in comments.

1 Comment

And keep in mind, even the newest release of 1.4 includes a security fix to $sanitize, they're still finding holes in it.
1

using $santize would be your best bet as you are injecting a html tag into the DOM.

you can use:

<p ng-bind-html="blah"></p>

...remembering to add the sanitize script...

<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular-sanitize.js"></script>

...but this isn't really how angular is meant to work as the controller should, where possible, be ignorant of the DOM.

If you are setting it in your controller, why can't you just call an alert from there?

Comments

1

You can use ngBindHtml feature provided by angularjs

ngBindHtml

Evaluates the expression and inserts the resulting HTML into the element in a secure way. By default, the resulting HTML content will be sanitized using the $sanitize service. To utilize this functionality, ensure that $sanitize is available, for example, by including ngSanitize in your module's dependencies (not in core Angular). In order to use ngSanitize in your module's dependencies, you need to include "angular-sanitize.js" in your application.

Take a look at this working Demo

var app = angular.module('myApp', ['ngSanitize']);
app.controller('Controller', function ($scope) {
  
    var data = {};
    data.name = "Click Me";
    $scope.html = '<a href="foo">' + data.name + '</a>';
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.min.js"></script>
<script src="https://code.angularjs.org/1.2.16/angular-sanitize.js"></script>

<div ng-app='myApp' ng-controller="Controller">
   <div ng-bind-html="html"></div>
</div>

1 Comment

This does not escape HTML.
1

After some more research, it seems that this is not possible (or is extremely awkward). Angular does not expose its HTML escaping code. A bit of googling turned up the following succinct method of escaping HTML in javascript:

orig.replace(/&/g, "&amp;").replace(/</g, "&lt;").
  replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;")

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.