feat($sce): New $sce service for Strict Contextual Escaping.

$sce is a service that provides Strict Contextual Escaping services to
AngularJS.

Strict Contextual Escaping (SCE) is a mode in which AngularJS requires
bindings in certain contexts to result in a value that is marked as safe
to use for that context One example of such a context is binding
arbitrary html controlled by the user via ng-bind-html-unsafe.  We refer
to these contexts as priviliged or SCE contexts.

As of version 1.1.6/1.2, Angular ships with SCE enabled by default.

Note:  When enabled (the default), IE8 in quirks mode is not supported.
In this mode, IE8 allows one to execute arbitrary javascript by the use
of the expression() syntax.  Refer
http://blogs.msdn.com/b/ie/archive/2008/10/16/ending-expressions.aspx to
learn more about them.  You can ensure your document is in standards
mode and not quirks mode by adding <!doctype html> to the top of your
HTML document.

SCE assists in writing code in way that (a) is secure by default and (b)
makes auditing for security vulnerabilities such as XSS, clickjacking,
etc. a lot easier.

Here's an example of a binding in a priviliged context:

<pre class="prettyprint">
    <input ng-model="userHtml">
    <div ng-bind-html-unsafe="{{userHtml}}">
</pre>

Notice that ng-bind-html-unsafe is bound to {{userHtml}} controlled by
the user.  With SCE disabled, this application allows the user render
arbitrary HTML into the DIV.  In a more realistic example, one may be
rendering user comments, blog articles, etc. via bindings.  (HTML is
just one example of a context where rendering user controlled input
creates security vulnerabilities.)

For the case of HTML, you might use a library, either on the client
side, or on the server side, to sanitize unsafe HTML before binding to
the value and rendering it in the document.

How would you ensure that every place that used these types of bindings
was bound to a value that was sanitized by your library (or returned as
safe for rendering by your server?)  How can you ensure that you didn't
accidentally delete the line that sanitized the value, or renamed some
properties/fields and forgot to update the binding to the sanitized
value?

To be secure by default, you want to ensure that any such bindings are
disallowed unless you can determine that something explicitly says it's
safe to use a value for binding in that context.  You can then audit
your code (a simple grep would do) to ensure that this is only done for
those values that you can easily tell are safe - because they were
received from your server, sanitized by your library, etc.  You can
organize your codebase to help with this - perhaps allowing only the
files in a specific directory to do this.  Ensuring that the internal
API exposed by that code doesn't markup arbitrary values as safe then
becomes a more manageable task.

In the case of AngularJS' SCE service, one uses $sce.trust (and
shorthand methods such as $sce.trustHtml, etc.) to obtain values that
will be accepted by SCE / priviliged contexts.

In priviliged contexts, directives and code will bind to the result of
$sce.getTrusted(value) rather than to the value directly.  Directives
use $sce.parse rather than $parse to watch attribute bindings, which
performs the $sce.getTrusted behind the scenes on non-constant literals.

As an example, ngBindHtmlUnsafe uses $sce.parseHtml(binding expression).
Here's the actual code (slightly simplified):

  var ngBindHtmlUnsafeDirective = ['$sce', function($sce) {
    return function(scope, element, attr) {
      scope.$watch($sce.parseHtml(attr.ngBindHtmlUnsafe), function(value) {
        element.html(value || '');
      });
    };
  }];

It's important to remember that SCE only applies to interpolation
expressions.

If your expressions are constant literals, they're automatically trusted
and you don't need to $sce.trust them.  (e.g. <div
ng-html-bind-unsafe="'<b>implicitly trusted</b>'"></div>) just works.

Additionally, a[href] and img[src] automatically sanitize their URLs and
do not pass them through $sce.getTrusted.  SCE doesn't play a role here.

The included $sceDelegate comes with sane defaults to allow you to load
templates in ng-include from your application's domain without having to
even know about SCE.  It blocks loading templates from other domains or
loading templates over http from an https served document.  You can
change these by setting your own custom whitelists and blacklists for
matching such URLs.

This significantly reduces the overhead.  It is far easier to pay the
small overhead and have an application that's secure and can be audited
to verify that with much more ease than bolting security onto an
application later.