Angular Trust Filter
It seems every Angular project I write, at some point, sees the error:
Attempting to use an unsafe value in a safe context.
This is because of Angular’s $sce
service, which enabled by default:
$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.
Unfortunately, it can be cumbersome, especially when working with dynamic objects.
The View
Suppose you’re writing the front-end for a blog where the content is consumed via an AJAX request:
<h1 ng-bind-html="response.title"></h1>
<section ng-bind-html="response.content"></section>
When your view attempts to use the raw response
content, you’ll get an error
because it’s unsafe.
The Controller
To get around this, you can have your controller “whitelist” the content:
angular
.module('example', [])
.controller('ExampleController', [
'$sce',
'$scope',
function($sce, $scope) {
...
// Assume there's a previous `$http` response
response['title'] = $sce.trustAsHtml(response['title']);
response['content'] = $sce.trustAsHtml(response['content']);
$scope.response = response;
}
])
;
The Filter
Instead, create a trust
filter.
angular.module('example', []).filter('trust', [
'$sce',
function ($sce) {
return function (value, type) {
// Defaults to treating trusted text as `html`
return $sce.trustAs(type || 'html', text)
}
},
])
Now your view and simply read:
<h1 ng-bind-html="response.title | trust"></h1>
<section ng-bind-html="response.content | trust"></section>
As with all things Angular, your view will contain your rendering logic and your controllers can stay as thin as possible.