AngularJS Strict Contextual Escaping ($sce)

  • 6,238 views
Uploaded on

What is $sce and how do I use it? …

What is $sce and how do I use it?

Why did Angular eliminate ng-bind-html-unsafe? How can I emulate the old behavior? How can I do better than emulating the old behavior of html binding?

Presented at the Seattle AngularJS Meetup on March 19, 2014 - http://www.meetup.com/AngularJS-SEA/events/169192362/

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
6,238
On Slideshare
0
From Embeds
0
Number of Embeds
3

Actions

Shares
Downloads
23
Comments
0
Likes
4

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. $ S C E A N G U L A R J S
  • 2. J o s h S c h u m a c h e r @ j o s h s c h u m a c h e r h t t p s : / / p l u s . g o o g l e . c o m / + J o s h S c h u m a c h e r s H a s O ff e r s
  • 3. S T R I C T C O N T E X T U A L E S C A P I N G
  • 4. – N O O N E E V E R “We can trust our users and the input they provide.”
  • 5. A N G U L A R 1 . 0 . 8 • ng-bind • ng-bind-html • ng-bind-html-unsafe <script> function snippetController($scope) { $scope.snippet = '<p style="color:blue">n an htmln' + ' <em onmouseover="this.textContent='PWN3D!'">click here</em>' + ' snippetn</p>'; } </script> ! <div ng-controller="snippetController" class="container"> <form> <h1>User Input</h1> <textarea class="form-control" rows="4" ng-model="snippet"></textarea> </form> ! <h2>ng-bind</h2> <pre ng-bind="snippet"></pre> ! ! <h2>ng-bind-html</h2> <div ng-bind-html="snippet"></div> ! ! <h2>ng-bind-html-unsafe</h2> <div ng-bind-html-unsafe="snippet"></div> ! </div> Demo…
  • 6. G O O D B Y E N G - B I N D - H T M L - U N S A F E
  • 7. A N G U L A R 1 . 2 • ng-bind • ng-bind-html • ng-bind-html-unsafe <script> function snippetController($scope) { $scope.snippet = '<p style="color:blue">n an htmln' + ' <em onmouseover="this.textContent='PWN3D!'">click here</em>' + ' snippetn</p>'; } </script> ! <div ng-controller="snippetController" class="container"> <form> <h1>User Input</h1> <textarea class="form-control" rows="4" ng-model="snippet"></textarea> </form> ! <h2>ng-bind</h2> <pre ng-bind="snippet"></pre> ! ! <h2>ng-bind-html</h2> <div ng-bind-html="snippet"></div> ! </div>
  • 8. Y O U ’ R E N O T T H AT L U C K Y Error: [$sce:unsafe] http://errors.angularjs.org/1.2.14/$sce/unsafe at Error (native) at http://code.angularjs.org/1.2.14/angular.min.js:6:450 at e (http://code.angularjs.org/1.2.14/angular.min.js:110:34) at getTrusted (http://code.angularjs.org/1.2.14/angular.min.js:111:327) at Object.e.(anonymous function) [as getTrustedHtml] 
 (http://code.angularjs.org/1.2.14/angular.min.js:113:71) at Object.fn (http://code.angularjs.org/1.2.14/angular.min.js:182:71) at h.$digest (http://code.angularjs.org/1.2.14/angular.min.js:102:370) at h.$apply (http://code.angularjs.org/1.2.14/angular.min.js:105:173) at http://code.angularjs.org/1.2.14/angular.min.js:18:23 at Object.d [as invoke] (http://code.angularjs.org/1.2.14/angular.min.js:30:452)
  • 9. L O N G L I V E n g S A N I T I Z E var app = angular.module('myApp', ['ngSanitize']); <script src="http://code.angularjs.org/1.2.14/angular-sanitize.min.js"></script> Demo…
  • 10. var ngBindHtmlDirective = ['$sce', function($sce) { return function(scope, element, attr) { scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) { element.html($sce.getTrustedHtml(value) || ''); }); }; }]; Bread and Butter <div ng-bind-html="snippet"></div>
  • 11. $sce.getTrustedHtml(value); → $sceDelegate.getTrusted($sce.HTML, value) → $sceDelegate.getTrusted($sce.URL, value) → $sceDelegate.getTrusted($sce.RESOURCE_URL, value) → $sceDelegate.getTrusted($sce.JS, value) → $sceDelegate.getTrusted($sce.CSS, value)
  • 12. var ngBindHtmlDirective = ['$sce', function($sce) { return function(scope, element, attr) { scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) { element.html($sce.getTrustedHtml(value) || ''); }); }; }]; return value.$$unwrapTrustedValue(); if (type === SCE_CONTEXTS.HTML) { return htmlSanitizer(value); } {$sceDelegate. getTrusted()
  • 13. S O W H Y WA S N ’ T I L U C K Y B E F O R E ? 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'); } $sceDelegateProvider
  • 14. return value.$$unwrapTrustedValue(); ????? var app = angular.module('myApp'); ! app.controller('snippetController', function($scope, $sce) { $scope.$watch('snippet', function(value) { $scope.snippetHarmful = $sce.trustAsHtml(value); }); }); function TrustedValueHolderType(trustedValue) { this.$$unwrapTrustedValue = function() { return trustedValue; }; }; Demo…
  • 15. Context Notes $sce.HTML HTML that is safe to render in application. $sce.CSS CSS that is safe to render in application. [currently unused by AngularJS core] $sce.URL URLs that are safe to follow as links. <a href= and <img src= don’t use $sce [currently unused by AngularJS core] $sce.RESOURCE_URL URLs whose contents are safe to include in your app. ng-include, ngSrc, iframe, object, etc $sce.JS JavaScript that is safe to render in application. [currently unused by AngularJS core]
  • 16. C U S T O M N G - B I N D - H T M L <h2>ng-bind-html (trusted w/ filter)</h2> <div ng-bind-html="snippet|trustedHtml"></div> Generally a RISKY idea $scope.$watch('snippet', function(value) { value = value.replace(' onmouseover="this.textContent='PWN3D!'"', ''); $scope.snippetCustomSanitized = $sce.trustAsHtml(value); });
  • 17. L O N G L I V E N G - B I N D - H T M L - U N S A F E Demo… var app = angular.module('myApp', ['ngSanitize']); ! app.filter('trustedHtml', ['$sce', function($sce) { return function(value) { return $sce.trustAsHtml(value); }; }]); ! <h2>ng-bind-html (trusted w/ filter)</h2> <div ng-bind-html="snippet|trustedHtml"></div> Generally a BAD idea
  • 18. C U S T O M I Z I N G T H E H T M L PA R S E R • Not easy • Dart recently introduced an injectable dom.NodeValidator • Re-implement $sanitize htmlParser for global customization • Write new htmlParser that returns $sce.trustAsHtml(parsedValue) /** * HTML Parser By Misko Hevery (misko@hevery.com) * based on: HTML Parser By John Resig (ejohn.org) * Original code by Erik Arvidsson, Mozilla Public License */
  • 19. S C E R E S O U R C E _ U R L app.config(function($sceDelegateProvider) { $sceDelegateProvider.resourceUrlWhitelist([ 'self', // Allow loading from our assets domain. Notice the difference between * and **. 'http://cdn*.assets.example.com/**' ]); }); ! ! ! ! ! ‘*’ matches 0 or more occurrences of any character EXCEPT ':', '/', '.', '?', '&' and ‘;' ! ‘**’ matches 0 or more of ANY character - be careful, generally only use at the end of a whitelist url