Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace \n with <br> tag on a model variable that I use $sce.trustAsHtml() on

I use the combination of the 2 following filters to first strip all the HTML from the user input from obvious reasons(preventing attacks), and than replace all the \n in
tags.

<span data-ng-bind-html-unsafe="model.userInput | noHTML | newlines"></span>

  filters.filter('newlines', function () {
      return function(text) {
        console.log(text)
          return text.replace(/\n/g, '<br/>');
      }
  })
  filters.filter('noHTML', function () {
      return function(text) {
          return Boolean(text) ? text
                  .replace(/&/g, '&amp;')
                  .replace(/>/g, '&gt;')
                  .replace(/</g, '&lt;') : '';
      }
  });

the problem is that in angular 1.2.2 bind-html-unsafe is deprecated, and you must use $sce (strict contextual escaping) to 'trust the html', which returns a function, on which I obviously cannot apply those filters.

new code:

ctrls.controllers('someCtrl', function($scope, $sce){
$scope.trusterInput = $sce.trustAsHtml($scope.userInput);
});

Error: TypeError: Object [object Object] has no method 'replace' at Scope.<anonymous> (http://localhost:8000/js/filters.js:20:20) at fnInvoke (http://code.angularjs.org/1.2.2/angular.js:9756:21) at OPERATORS.| (http://code.angularjs.org/1.2.2/angular.js:9271:59) at extend.constant (http://code.angularjs.org/1.2.2/angular.js:9701:14) at OPERATORS.| (http://code.angularjs.org/1.2.2/angular.js:9271:74) at extend.constant (http://code.angularjs.org/1.2.2/angular.js:9701:14) at Object.getStringValue (http://code.angularjs.org/1.2.2/angular.js:16990:41) at Scope.$digest (http://code.angularjs.org/1.2.2/angular.js:11494:47) at Scope.$apply (http://code.angularjs.org/1.2.2/angular.js:11740:24) at http://code.angularjs.org/1.2.2/angular.js:13265:36

Obviously becasue $sce returns a function and not a primitive(value of 'text'): TrustedValueHolderType {$$unwrapTrustedValue: function, $$unwrapTrustedValue: function, valueOf: function, toString: function, valueOf: function…} $$unwrapTrustedValue: function () { arguments: (...) get arguments: function ThrowTypeError() { [native code] } set arguments: function ThrowTypeError() { [native code] } caller: (...) get caller: function ThrowTypeError() { [native code] } set caller: function ThrowTypeError() { [native code] } length: 0 name: "" prototype: Object __proto__: function Empty() {} <function scope> __proto__: TrustedValueHolderType

Any ide on how to solve this, beside calling my filters programmatically before the $sce, which is hardly the Angular way of doing things

like image 224
Oleg Belousov Avatar asked Dec 02 '13 14:12

Oleg Belousov


1 Answers

Instead of writing your own HTML escaper, just let the auto-escaper do it for you, and instead of replacing newlines with <br> just use the CSS property white-space: pre.

TypeError: Object [object Object] has no method 'replace'
at Scope.<anonymous> (http://localhost:8000/js/filters.js:20:20)

occurs because text is not a string -- the contextual auto-escaper has already done the first step for you, and converted the string to a privileged SCE safe HTML value.


$sce.trustAsHtml($scope.userInput)

is risky. Echoing a naïve user's input back to them as HTML can be dangerous if they are being socially engineered to copy/paste text that really comes from an attacker.

like image 139
Mike Samuel Avatar answered Nov 18 '22 08:11

Mike Samuel