Highlighting partial HTML string in Angular.js

I read about the default angular escaping method and $sce , so I have whitelist data with $sce.trustAsHtml() through a filter (since $sce does not work in the service), for example:

 <sup class="ng-binding" ng-bind-html="row|logEntry"></sup> 

But the problem is that I do not trust some parts of HTML.

To dive into the details - I have translations that have HTML, but they have replaceable markers / variables. Therefore, translations support HTML , but I do not want the provided tokens to include HTML.

My logEntry filter internally looks like this:

 var translated = $translate('Log.' + msg.context.entity_type) + '.' + msg.context.action, { 'object_name': msg.context.object_name, 'user': msg.context.user_name }); return $sce.trustAsHtml(translated); 

For example, I may have a translation about changing the userX article, but I do not want the result text to call alert () if the username includes <script>alert('evilname')</script>

$translate alone does not matter, it can be any HTML line where I want some parts to be replaced with regular JS .replace() , while the content remains β€œlike text”.

So my question is, how can I avoid parts of HTML ? Should I resort to cutting it in parts inside the view? Or do I need to resort to custom escaping ( The fastest way to avoid HTML tags as HTML objects? )? Is there a preferred practice for such things?

+5
source share
2 answers

Start by restructuring your logEntry to highlight interpolation

 var translationId = 'Log.' + msg.context.entity_type) + '.' + msg.context.action; var interpolateParams = { 'object_name': msg.context.object_name, 'user': msg.context.user_name }; var translated = $translate(translationId, interpolateParams); return $sce.trustAsHtml(translated); 

You want to avoid all the HTML from interpolateParams , but leave the HTML in your translation templates. Use this code to copy an object, iterate over its values, and replace it with escaped HTML.

 var safeParams = angular.copy(interpolateParams); angular.forEach(safeParams, function(value, key, obj) { obj[key] = encodeEntities(value) // if you want safe/sanitized HTML, use this instead // obj[key] = $sanitize(value); }); var translated = $translate(translationId, safeParams); 

Finally, the encodeEntities angular function is not displayed, so we had to borrow the source from angular -sanitize.js

 var SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g, // Match everything outside of normal chars and " (quote character) NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; function encodeEntities(value) { return value. replace(/&/g, '&amp;'). replace(SURROGATE_PAIR_REGEXP, function(value) { var hi = value.charCodeAt(0); var low = value.charCodeAt(1); return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';'; }). replace(NON_ALPHANUMERIC_REGEXP, function(value) { return '&#' + value.charCodeAt(0) + ';'; }). replace(/</g, '&lt;'). replace(/>/g, '&gt;'); } 

Update: After upgrading to angular -translate 2.7.0 this message appeared:

pascalprecht.translate. $ translateSanitization: Without sanitation, a strategy has been set up. This can have serious safety consequences. See http://angular-translate.imtqy.com/docs/#/guide/19_security for details.

Sp instead of the trustlate answer above, angular -translate can accomplish the same result with:

 $translateProvider.useSanitizeValueStrategy('escapeParameters'); 

See docs for more effective security strategies for more information.

+5
source

In the app add

 $translateProvider.useSanitizeValueStrategy('escapeParameters'); 

So your code looks like this:

 myApp.config(function ($translateProvider) { //...whatever $translateProvider.useSanitizeValueStrategy('escapeParameters'); }); 
+2
source

Source: https://habr.com/ru/post/1207403/


All Articles