The following binding will render the <b> tags as HTML to be interpreted by the browser:

<p ng-bind-html-unsafe="msg"></p>

Sanitizing HTML

angularjs has one more directive that will selectively sanitize certain HTML tags, while allowing others to be interpreted by a browser, which is ng-bind-html. Its usage is similar to the unsafe equivalent:

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

In terms of escaping, the ng-bind-html directive is a compromise between behavior of ng-bind-html-unsafe (allow all HTML tags) and ng-bind (allow no HTML tags at all). It might be a good option for cases where we want to allow some HTML tags to be entered by users.

Note

The sanitization uses a whitelist of safe HTML tags, which is quite extensive. The main tags that will be sanitized include the <script> and <style> elements, as well as attributes that take URLs such as href, src, and usemap.

The ng-bind-html directive resides in a separate module (ngSanitize), and requires inclusion of an additional source file: angular-sanitize.js. You must declare a dependency on the ngSanitize module if you plan to use the ng-bind-html directive, as shown in the following code:

angular.module('expressionsEscaping', ['ngSanitize'])
  .controller('ExpressionsEscapingCtrl', function ($scope) {
    $scope.msg = 'Hello, <b>World</b>!';
  });

The ng-bind-html directive uses the $sanitize service, which is also found inside the ngSanitize module. This service is a function that takes a string, and then returns a sanitized version of the string, as described in the following code:

var safeDescription = $sanitize(description);

Note

Unless you are working with any existing legacy systems (For example CMS, back-ends sending HTML, and so on), markup in the model should be avoided. Such markup can’t contain angularjs directives and requires the ng-bind-html-unsafe or ng-bind-html directive to obtain the desired results.

Preventing cross-site request forgery

In any application where the server must trust who the user is, that is, they are logged in, and allows them access to actions on the server based on that trust, there is the potential for other sites to pretend to be you, and then get access to those actions themselves. This is called cross-site request forgery (XSRF). If you visit an evil site when you are already logged into a secure site, the evil site’s web page could post to your secure site, since it trusts that you are currently authenticated.

This attack is often in the form of a fraudulent src attribute on an <img> tag, which the user inadvertently loads by browsing to an evil page, while still logged into a secure site. When the browser tries to load the image, it actually makes a request to the secure site.

<img src="http://my.securesite.com/createAdminUser?username=badguy">

The solution is for the server to provide a secret to the browser, which can only be accessed by JavaScript running on the browser, and so would not be available in the src attribute. Any request to the server should include this secret in its headers to prove it is authentic.

The $http service has this solution built-in, in order to protect against such an attack. You must arrange for the server to set a token in the session cookie called XSRF-TOKEN, on the first GET request by the application. This token must be unique for this session.

In the client application, the $http service will extract this token from the cookie, and then attach it as a header (called X-XSRF-TOKEN) to every HTTP request it makes. The server must check the token on each request, and then block access if it is not valid. The angularjs team recommends that the token is a digest of your site’s authentication cookie with salt for added security.

Preventing the JSON injection vulnerability

There is a JSON injection vulnerability that allows evil third party websites to access your secure JSON resources, if they return JSON arrays. This is done by effectively loading the JSON as a script in a web page, and then executing it.

The $http service has a built-in solution to protect against this. To prevent the browser from being able to execute the JSON returned from the secure resource, you can arrange for your server to prefix all the JSON requests with the ")]}',\n" string, which is not legal JavaScript, and so cannot be executed. The $http service automatically strips this prefix string, if it appears from any JSON response. For example, if your JSON resource returns the following array:

['a,'b','c']

This is vulnerable to the JSON injection attack. Instead, the server should return:

)]}',
['a','b','c']

This is not valid JavaScript. It cannot be executed by the browser, and so is no longer vulnerable to attack. The $http service will automatically strip off this invalid prefix, if found, before returning the valid JSON in its response object.