AngularJS Strict Contextual Escaping ($sce)
-
Upload
josh-schumacher -
Category
Technology
-
view
8.788 -
download
3
description
Transcript of AngularJS Strict Contextual Escaping ($sce)
$ S C EA N G U L A R J S
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 f f e r s
S T R I C T C O N T E X T U A L E S C A P I N G
– N O O N E E V E R
“We can trust our users and the input they provide.”
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 html\n' + ' <em onmouseover="this.textContent=\'PWN3D!\'">click here</em>' + ' snippet\n</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…
G O O D B Y E N G - B I N D - H T M L - U N S A F E
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 html\n' + ' <em onmouseover="this.textContent=\'PWN3D!\'">click here</em>' + ' snippet\n</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>
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)
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…
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>
$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)
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()
S O W H Y W A 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
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…
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.URLURLs 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]
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); });
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
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 ([email protected]) * based on: HTML Parser By John Resig (ejohn.org) * Original code by Erik Arvidsson, Mozilla Public License */
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