diff options
| author | Chirayu Krishnappa | 2013-07-19 16:04:51 -0700 | 
|---|---|---|
| committer | Chirayu Krishnappa | 2013-07-25 14:29:56 -0700 | 
| commit | dae694739b9581bea5dbc53522ec00d87b26ae55 (patch) | |
| tree | 00d55fd867916df991f699cfe398243205f03ffc | |
| parent | bea9422ebfc8e80ee28ad81afc62d2e432c85cbb (diff) | |
| download | angular.js-dae694739b9581bea5dbc53522ec00d87b26ae55.tar.bz2 | |
feat(ngBindHtml, sce): combine ng-bind-html and ng-bind-html-unsafe
Changes:
- remove ng-bind-html-unsafe
- ng-bind-html is now in core
- ng-bind-html is secure
  - supports SCE - so you can bind to an arbitrary trusted string
  - automatic sanitization if $sanitize is available
BREAKING CHANGE:
  ng-html-bind-unsafe has been removed and replaced by ng-html-bind
  (which has been removed from ngSanitize.)  ng-bind-html provides
  ng-html-bind-unsafe like behavior (innerHTML's the result without
  sanitization) when bound to the result of $sce.trustAsHtml(string).
  When bound to a plain string, the string is sanitized via $sanitize
  before being innerHTML'd.  If $sanitize isn't available, it's logs an
  exception.
| -rw-r--r-- | Gruntfile.js | 1 | ||||
| -rwxr-xr-x | angularFiles.js | 1 | ||||
| -rwxr-xr-x | src/AngularPublic.js | 2 | ||||
| -rw-r--r-- | src/ng/directive/ngBind.js | 22 | ||||
| -rw-r--r-- | src/ng/sce.js | 111 | ||||
| -rw-r--r-- | src/ngSanitize/directive/ngBindHtml.js | 25 | ||||
| -rw-r--r-- | src/ngSanitize/sanitize.js | 65 | ||||
| -rw-r--r-- | test/ng/directive/ngBindSpec.js | 41 | ||||
| -rw-r--r-- | test/ng/sceSpecs.js | 15 | 
9 files changed, 134 insertions, 149 deletions
| diff --git a/Gruntfile.js b/Gruntfile.js index de0d6c72..264fe874 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -153,7 +153,6 @@ module.exports = function(grunt) {          dest: 'build/angular-sanitize.js',          src: util.wrap([            'src/ngSanitize/sanitize.js', -          'src/ngSanitize/directive/ngBindHtml.js',            'src/ngSanitize/filter/linky.js'          ], 'module')        }, diff --git a/angularFiles.js b/angularFiles.js index 694bde47..dc98bcc1 100755 --- a/angularFiles.js +++ b/angularFiles.js @@ -73,7 +73,6 @@ angularFiles = {      'src/ngRoute/routeParams.js',      'src/ngRoute/directive/ngView.js',      'src/ngSanitize/sanitize.js', -    'src/ngSanitize/directive/ngBindHtml.js',      'src/ngSanitize/filter/linky.js',      'src/ngMock/angular-mocks.js',      'src/ngMobile/mobile.js', diff --git a/src/AngularPublic.js b/src/AngularPublic.js index 25e21b2c..7745cce9 100755 --- a/src/AngularPublic.js +++ b/src/AngularPublic.js @@ -72,7 +72,7 @@ function publishExternalAPI(angular){              style: styleDirective,              option: optionDirective,              ngBind: ngBindDirective, -            ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective, +            ngBindHtml: ngBindHtmlDirective,              ngBindTemplate: ngBindTemplateDirective,              ngClass: ngClassDirective,              ngClassEven: ngClassEvenDirective, diff --git a/src/ng/directive/ngBind.js b/src/ng/directive/ngBind.js index fc54adcf..9e642ac2 100644 --- a/src/ng/directive/ngBind.js +++ b/src/ng/directive/ngBind.js @@ -116,23 +116,27 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {  /**   * @ngdoc directive - * @name ng.directive:ngBindHtmlUnsafe + * @name ng.directive:ngBindHtml   *   * @description   * Creates a binding that will innerHTML the result of evaluating the `expression` into the current - * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if - * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too - * restrictive and when you absolutely trust the source of the content you are binding to. + * element in a secure way.  By default, the innerHTML-ed content will be sanitized using the {@link + * ngSanitize.$sanitize $sanitize} service.  To utilize this functionality, ensure that `$sanitize` + * is available, for example, by including {@link ngSanitize} in your module's dependencies (not in + * core Angular.)  You may also bypass sanitization for values you know are safe. To do so, bind to + * an explicitly trusted value via {@link ng.$sce#trustAsHtml $sce.trustAsHtml}.  See the example + * under {@link ng.$sce#Example Strict Contextual Escaping (SCE)}.   * - * See {@link ngSanitize.$sanitize $sanitize} docs for examples. + * Note: If a `$sanitize` service is unavailable and the bound value isn't explicitly trusted, you + * will have an exception (instead of an exploit.)   *   * @element ANY - * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate. + * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.   */ -var ngBindHtmlUnsafeDirective = ['$sce', function($sce) { +var ngBindHtmlDirective = ['$sce', function($sce) {    return function(scope, element, attr) { -    element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe); -    scope.$watch($sce.parseAsHtml(attr.ngBindHtmlUnsafe), function ngBindHtmlUnsafeWatchAction(value) { +    element.addClass('ng-binding').data('$binding', attr.ngBindHtml); +    scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function ngBindHtmlWatchAction(value) {        element.html(value || '');      });    }; diff --git a/src/ng/sce.js b/src/ng/sce.js index ab3d2208..9a5a5af6 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -137,8 +137,17 @@ function $SceDelegateProvider() {              (documentProtocol === "http:" && resourceProtocol === "https:"));    } -  this.$get = ['$log', '$document', '$$urlUtils', function( -                $log,   $document,   $$urlUtils) { +  this.$get = ['$log', '$document', '$injector', '$$urlUtils', function( +                $log,   $document,   $injector,   $$urlUtils) { + +    var htmlSanitizer = function htmlSanitizer(html) { +      throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.'); +    }; + +    if ($injector.has('$sanitize')) { +      htmlSanitizer = $injector.get('$sanitize'); +    } +      function matchUrl(matcher, parsedUrl) {        if (matcher === 'self') { @@ -285,6 +294,9 @@ function $SceDelegateProvider() {        if (constructor && maybeTrusted instanceof constructor) {          return maybeTrusted.$$unwrapTrustedValue();        } +      // If we get here, then we may only take one of two actions. +      // 1. sanitize the value for the requested type, or +      // 2. throw an exception.        if (type === SCE_CONTEXTS.RESOURCE_URL) {          if (isResourceUrlAllowedByPolicy(maybeTrusted)) {            return maybeTrusted; @@ -293,6 +305,8 @@ function $SceDelegateProvider() {                'Blocked loading resource from url not allowed by $sceDelegate policy.  URL: {0}', maybeTrusted.toString());            return;          } +      } else if (type === SCE_CONTEXTS.HTML) { +        return htmlSanitizer(maybeTrusted);        }        throw $sceMinErr('unsafe', 'Attempting to use an unsafe value in a safe context.');      } @@ -329,8 +343,8 @@ function $SceDelegateProvider() {   *   * 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 privileged or SCE contexts. + * a context is binding arbitrary html controlled by the user via `ng-bind-html`.  We refer to these + * contexts as privileged or SCE contexts.   *   * As of version 1.2, Angular ships with SCE enabled by default.   * @@ -347,10 +361,10 @@ function $SceDelegateProvider() {   *   * <pre class="prettyprint">   *     <input ng-model="userHtml"> - *     <div ng-bind-html-unsafe="{{userHtml}}"> + *     <div ng-bind-html="{{userHtml}}">   * </pre>   * - * Notice that `ng-bind-html-unsafe` is bound to `{{userHtml}}` controlled by the user.  With SCE + * Notice that `ng-bind-html` is bound to `{{userHtml}}` controlled by the user.  With SCE   * disabled, this application allows the user to 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 @@ -384,14 +398,14 @@ function $SceDelegateProvider() {   * ng.$sce#parse $sce.parseAs} rather than `$parse` to watch attribute bindings, which performs the   * {@link ng.$sce#getTrusted $sce.getTrusted} behind the scenes on non-constant literals.   * - * As an example, {@link ng.directive:ngBindHtmlUnsafe ngBindHtmlUnsafe} uses {@link + * As an example, {@link ng.directive:ngBindHtml ngBindHtml} uses {@link   * ng.$sce#parseHtml $sce.parseAsHtml(binding expression)}.  Here's the actual code (slightly   * simplified):   *   * <pre class="prettyprint"> - *   var ngBindHtmlUnsafeDirective = ['$sce', function($sce) { + *   var ngBindHtmlDirective = ['$sce', function($sce) {   *     return function(scope, element, attr) { - *       scope.$watch($sce.parseAsHtml(attr.ngBindHtmlUnsafe), function(value) { + *       scope.$watch($sce.parseAsHtml(attr.ngBindHtml), function(value) {   *         element.html(value || '');   *       });   *     }; @@ -444,7 +458,7 @@ function $SceDelegateProvider() {   *   * | Context             | Notes          |   * |=====================|================| - * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtmlUnsafe ngBindHtmlUnsafe} directive uses this context for bindings. | + * | `$sce.HTML`         | For HTML that's safe to source into the application.  The {@link ng.directive:ngBindHtml ngBindHtml} directive uses this context for bindings. |   * | `$sce.CSS`          | For CSS that's safe to source into the application.  Currently unused.  Feel free to use it in your own directives. |   * | `$sce.URL`          | For URLs that are safe to follow as links.  Currently unused (`<a href=` and `<img src=` sanitize their urls and don't consititute an SCE context. |   * | `$sce.RESOURCE_URL` | For URLs that are not only safe to follow as links, but whose contens are also safe to include in your application.  Examples include `ng-include`, `src` / `ngSrc` bindings for tags other than `IMG` (e.g. `IFRAME`, `OBJECT`, etc.)  <br><br>Note that `$sce.RESOURCE_URL` makes a stronger statement about the URL than `$sce.URL` does and therefore contexts requiring values trusted for `$sce.RESOURCE_URL` can be used anywhere that values trusted for `$sce.URL` are required. | @@ -458,61 +472,37 @@ function $SceDelegateProvider() {   <example module="mySceApp">    <file name="index.html">      <div ng-controller="myAppController as myCtrl"> -      <button ng-click="myCtrl.fetchUserComments()" id="fetchBtn">Fetch Comments</button> -      <div ng-show="myCtrl.errorMsg">Error: {{myCtrl.errorMsg}}</div> -      <div ng-repeat="userComment in myCtrl.userComments"> -        <hr> -        <b>{{userComment.name}}</b>: -        <span ng-bind-html-unsafe="userComment.htmlComment" class="htmlComment"></span> +      <i ng-bind-html="myCtrl.explicitlyTrustedHtml" id="explicitlyTrustedHtml"></i><br><br> +      <b>User comments</b><br> +      By default, HTML that isn't explicitly trusted (e.g. Alice's comment) is sanitized when $sanitize is available.  If $sanitize isn't available, this results in an error instead of an exploit. +      <div class="well"> +        <div ng-repeat="userComment in myCtrl.userComments"> +          <b>{{userComment.name}}</b>: +          <span ng-bind-html="userComment.htmlComment" class="htmlComment"></span> +          <br> +        </div>        </div> -      <div ng-bind-html-unsafe="myCtrl.someHtml" id="someHtml"></div>      </div>    </file>    <file name="script.js"> -    // These types of functions would be in the data access layer of your application code. -    function fetchUserCommentsFromServer($http, $q, $templateCache, $sce) { -      var deferred = $q.defer(); -      $http({method: "GET", url: "test_data.json", cache: $templateCache}). -        success(function(userComments, status) { -          // The comments coming from the server have been sanitized by the server and can be -          // trusted. -          angular.forEach(userComments, function(userComment) { -            userComment.htmlComment = $sce.trustAsHtml(userComment.htmlComment); -          }); -          deferred.resolve(userComments); -        }). -        error(function (data, status) { -          deferred.reject("HTTP status code " + status + ": " + data); -        }); -      return deferred.promise; -    }; - -    var mySceApp = angular.module('mySceApp', []); +    var mySceApp = angular.module('mySceApp', ['ngSanitize']); -    mySceApp.controller("myAppController", function myAppController($injector) { +    mySceApp.controller("myAppController", function myAppController($http, $templateCache, $sce) {        var self = this; - -      self.someHtml = "This might have been any binding including an input element " + -                      "controlled by the user."; - -      self.fetchUserComments = function() { -        $injector.invoke(fetchUserCommentsFromServer).then( -            function onSuccess(userComments) { -              self.errorMsg = null; -              self.userComments = userComments; -            }, -            function onFailure(errorMsg) { -              self.errorMsg = errorMsg; -            }); -      } +      $http.get("test_data.json", {cache: $templateCache}).success(function(userComments) { +        self.userComments = userComments; +      }); +      self.explicitlyTrustedHtml = $sce.trustAsHtml( +          '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + +          'sanitization."">Hover over this text.</span>');      });    </file>    <file name="test_data.json">      [        { "name": "Alice", -        "htmlComment": "Is <i>anyone</i> reading this?" +        "htmlComment": "<span onmouseover='this.textContent=\"PWN3D!\"'>Is <i>anyone</i> reading this?</span>"        },        { "name": "Bob",          "htmlComment": "<i>Yes!</i>  Am I the only other one?" @@ -521,14 +511,15 @@ function $SceDelegateProvider() {    </file>    <file name="scenario.js"> -     describe('SCE doc demo', function() { -       it('should bind trusted values', function() { -         element('#fetchBtn').click(); -         expect(element('.htmlComment').html()).toBe('Is <i>anyone</i> reading this?'); -       }); -       it('should NOT bind arbitrary values', function() { -         expect(element('#someHtml').html()).toBe(''); -       }); +    describe('SCE doc demo', function() { +      it('should sanitize untrusted values', function() { +        expect(element('.htmlComment').html()).toBe('<span>Is <i>anyone</i> reading this?</span>'); +      }); +      it('should NOT sanitize explicitly trusted values', function() { +        expect(element('#explicitlyTrustedHtml').html()).toBe( +            '<span onmouseover="this.textContent="Explicitly trusted HTML bypasses ' + +            'sanitization."">Hover over this text.</span>'); +      });      });    </file>   </example> diff --git a/src/ngSanitize/directive/ngBindHtml.js b/src/ngSanitize/directive/ngBindHtml.js deleted file mode 100644 index 150e6bdc..00000000 --- a/src/ngSanitize/directive/ngBindHtml.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - - -/** - * @ngdoc directive - * @name ngSanitize.directive:ngBindHtml - * - * @description - * Creates a binding that will sanitize the result of evaluating the `expression` with the - * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element. - * - * See {@link ngSanitize.$sanitize $sanitize} docs for examples. - * - * @element ANY - * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. - */ -angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) { -  return function(scope, element, attr) { -    element.addClass('ng-binding').data('$binding', attr.ngBindHtml); -    scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) { -      value = $sanitize(value); -      element.html(value || ''); -    }); -  }; -}]); diff --git a/src/ngSanitize/sanitize.js b/src/ngSanitize/sanitize.js index 110b3a64..70932899 100644 --- a/src/ngSanitize/sanitize.js +++ b/src/ngSanitize/sanitize.js @@ -68,8 +68,7 @@ var ngSanitizeMinErr = angular.$$minErr('ngSanitize');               '<p style="color:blue">an html\n' +               '<em onmouseover="this.textContent=\'PWN3D!\'">click here</em>\n' +               'snippet</p>'; -           // ng-bind-html-unsafe requires a $sce trusted value of type $sce.HTML. -           $scope.getSceSnippet = function() { +           $scope.deliberatelyTrustDangerousSnippet = function() {               return $sce.trustAsHtml($scope.snippet);             };           } @@ -78,57 +77,57 @@ var ngSanitizeMinErr = angular.$$minErr('ngSanitize');            Snippet: <textarea ng-model="snippet" cols="60" rows="3"></textarea>             <table>               <tr> -               <td>Filter</td> +               <td>Directive</td> +               <td>How</td>                 <td>Source</td>                 <td>Rendered</td>               </tr> -             <tr id="html-filter"> -               <td>html filter</td> -               <td> -                 <pre><div ng-bind-html="snippet"><br/></div></pre> -               </td> -               <td> -                 <div ng-bind-html="snippet"></div> -               </td> +             <tr id="bind-html-with-sanitize"> +               <td>ng-bind-html</td> +               <td>Automatically uses $sanitize</td> +               <td><pre><div ng-bind-html="snippet"><br/></div></pre></td> +               <td><div ng-bind-html="snippet"></div></td>               </tr> -             <tr id="escaped-html"> -               <td>no filter</td> +             <tr id="bind-html-with-trust"> +               <td>ng-bind-html</td> +               <td>Bypass $sanitize by explicitly trusting the dangerous value</td> +               <td><pre><div ng-bind-html="deliberatelyTrustDangerousSnippet()"><br/></div></pre></td> +               <td><div ng-bind-html="deliberatelyTrustDangerousSnippet()"></div></td> +             </tr> +             <tr id="bind-default"> +               <td>ng-bind</td> +               <td>Automatically escapes</td>                 <td><pre><div ng-bind="snippet"><br/></div></pre></td>                 <td><div ng-bind="snippet"></div></td>               </tr> -             <tr id="html-unsafe-filter"> -               <td>unsafe html filter</td> -               <td><pre><div ng-bind-html-unsafe="getSceSnippet()"><br/></div></pre></td> -               <td><div ng-bind-html-unsafe="getSceSnippet()"></div></td> -             </tr>             </table>           </div>       </doc:source>       <doc:scenario> -       it('should sanitize the html snippet ', function() { -         expect(using('#html-filter').element('div').html()). +       it('should sanitize the html snippet by default', function() { +         expect(using('#bind-html-with-sanitize').element('div').html()).             toBe('<p>an html\n<em>click here</em>\nsnippet</p>');         }); +       it('should inline raw snippet if bound to a trusted value', function() { +         expect(using('#bind-html-with-trust').element("div").html()). +           toBe("<p style=\"color:blue\">an html\n" + +                "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + +                "snippet</p>"); +       }); +         it('should escape snippet without any filter', function() { -         expect(using('#escaped-html').element('div').html()). +         expect(using('#bind-default').element('div').html()).             toBe("<p style=\"color:blue\">an html\n" +                  "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" +                  "snippet</p>");         }); -       it('should inline raw snippet if filtered as unsafe', function() { -         expect(using('#html-unsafe-filter').element("div").html()). -           toBe("<p style=\"color:blue\">an html\n" + -                "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + -                "snippet</p>"); -       }); - -       it('should update', function($sce) { -         input('snippet').enter('new <b>text</b>'); -         expect(using('#html-filter').binding('snippet')).toBe('new <b>text</b>'); -         expect(using('#escaped-html').element('div').html()).toBe("new <b>text</b>"); -         expect(using('#html-unsafe-filter').element('div').html()).toBe('new <b>text</b>'); +       it('should update', function() { +         input('snippet').enter('new <b onclick="alert(1)">text</b>'); +         expect(using('#bind-html-with-sanitize').element('div').html()).toBe('new <b>text</b>'); +         expect(using('#bind-html-with-trust').element('div').html()).toBe('new <b onclick="alert(1)">text</b>'); +         expect(using('#bind-default').element('div').html()).toBe("new <b onclick=\"alert(1)\">text</b>");         });       </doc:scenario>     </doc:example> diff --git a/test/ng/directive/ngBindSpec.js b/test/ng/directive/ngBindSpec.js index 1d8f8ef4..be68464f 100644 --- a/test/ng/directive/ngBindSpec.js +++ b/test/ng/directive/ngBindSpec.js @@ -67,19 +67,14 @@ describe('ngBind*', function() {    }); -  describe('ngBindHtmlUnsafe', function() { - -    function configureSce(enabled) { -      module(function($provide, $sceProvider) { -        $sceProvider.enabled(enabled); -      }); -    }; - +  describe('ngBindHtml', function() {      describe('SCE disabled', function() { -      beforeEach(function() {configureSce(false)}); +      beforeEach(function() { +        module(function($sceProvider) { $sceProvider.enabled(false); }); +      }); -      it('should set unsafe html', inject(function($rootScope, $compile) { -        element = $compile('<div ng-bind-html-unsafe="html"></div>')($rootScope); +      it('should set html', inject(function($rootScope, $compile) { +        element = $compile('<div ng-bind-html="html"></div>')($rootScope);          $rootScope.html = '<div onclick="">hello</div>';          $rootScope.$digest();          expect(angular.lowercase(element.html())).toEqual('<div onclick="">hello</div>'); @@ -88,27 +83,35 @@ describe('ngBind*', function() {      describe('SCE enabled', function() { -      beforeEach(function() {configureSce(true)}); - -      it('should NOT set unsafe html for untrusted values', inject(function($rootScope, $compile) { -        element = $compile('<div ng-bind-html-unsafe="html"></div>')($rootScope); +      it('should NOT set html for untrusted values', inject(function($rootScope, $compile) { +        element = $compile('<div ng-bind-html="html"></div>')($rootScope);          $rootScope.html = '<div onclick="">hello</div>';          expect($rootScope.$digest).toThrow();        })); -      it('should NOT set unsafe html for wrongly typed values', inject(function($rootScope, $compile, $sce) { -        element = $compile('<div ng-bind-html-unsafe="html"></div>')($rootScope); +      it('should NOT set html for wrongly typed values', inject(function($rootScope, $compile, $sce) { +        element = $compile('<div ng-bind-html="html"></div>')($rootScope);          $rootScope.html = $sce.trustAsCss('<div onclick="">hello</div>');          expect($rootScope.$digest).toThrow();        })); -      it('should set unsafe html for trusted values', inject(function($rootScope, $compile, $sce) { -        element = $compile('<div ng-bind-html-unsafe="html"></div>')($rootScope); +      it('should set html for trusted values', inject(function($rootScope, $compile, $sce) { +        element = $compile('<div ng-bind-html="html"></div>')($rootScope);          $rootScope.html = $sce.trustAsHtml('<div onclick="">hello</div>');          $rootScope.$digest();          expect(angular.lowercase(element.html())).toEqual('<div onclick="">hello</div>');        })); +      describe('when $sanitize is available', function() { +        beforeEach(function() { module('ngSanitize'); }); + +        it('should sanitize untrusted html', inject(function($rootScope, $compile) { +          element = $compile('<div ng-bind-html="html"></div>')($rootScope); +          $rootScope.html = '<div onclick="">hello</div>'; +          $rootScope.$digest(); +          expect(angular.lowercase(element.html())).toEqual('<div>hello</div>'); +        })); +      });      });    }); diff --git a/test/ng/sceSpecs.js b/test/ng/sceSpecs.js index 16525b8d..6157fc17 100644 --- a/test/ng/sceSpecs.js +++ b/test/ng/sceSpecs.js @@ -341,7 +341,22 @@ describe('SCE', function() {          expect(function() { $sce.getTrustedResourceUrl('open_redirect'); }).toThrow(            '[$sce:isecrurl] Blocked loading resource from url not allowed by $sceDelegate policy.  URL: open_redirect');      })); +  }); + +  describe('sanitizing html', function() { +    describe('when $sanitize is NOT available', function() { +      it('should throw an exception for getTrusted(string) values', inject(function($sce) { +        expect(function() { $sce.getTrustedHtml('<b></b>'); }).toThrow( +            '[$sce:unsafe] Attempting to use an unsafe value in a safe context.'); +      })); +    }); +    describe('when $sanitize is available', function() { +      beforeEach(function() { module('ngSanitize'); }); +      it('should sanitize html using $sanitize', inject(function($sce) { +        expect($sce.getTrustedHtml('a<xxx><B>b</B></xxx>c')).toBe('a<b>b</b>c'); +      })); +    });    });  }); | 
