Sanitization for mostly non-HTML translations
See original GitHub issueExposition
I have been working on a project where most translations are plain text strings without HTML. Our team ran into an issue when the translation contained an ampersand character (‘&’): The character would get doubly escaped, resulting in “&” in the code and “&”, instead of just “&”, visible to the user.
Digging into the issue, we found that the cause was the sanitization strategy “sanitize” we were using in combination with the {{ key | translate }} filter, each of which was responsible for one round of encoding the ampersand.
Since we made heavy use of the translate filter and rarely needed HTML in the translations, the sanitization strategy would get in our way. We would prefer having it set to null, but that strategy is said to be up for removal in version 3.0.
Realising the security risks of using a null sanitization strategy, we tested some XSS attacks with injections in both the translation string and the interpolation parameters. To our surprise:
- Just putting
{{ key | translate: params }}into an Angular template does not create a vulnerability because Angular escapes the content. - Putting
data-ng-bind-html="{{ key | translate: params }}"also does not create a vulnerability because Angular sanitizes the content. - Using the result of
$translate(key, params)also does not create a vulnerability unless the result is used in a sensitive context (like thehrefattribute) or explicitly trusted with$sce. - Only using the
translatedirective would create a vulnerability, because it would interpret the translation as HTML and implicitly trust it.
To sum it all up, if we don’t use the translate directive, we see no risks with a null sanitization strategy. If there is an error in this logic of reasoning, I would hugely appreciate anyone pointing it out.
Still, even if this solution works now, it requires avoiding the translate directive and will likely stop working in version 3.0.
There is also the possibility of using the escape sanitization strategy for non-HTML use cases, but:
- there is no easy way to make exceptions for a small number of messages that do contain HTML, other than temporarily changing the global sanitization strategy,
- using the
$translateservice results in an escaped string even if such string was not meant to be used in an HTML context, and - using an Angular expression like
{{ key | translate }}results in doubly escaped text.
Suggestion
I suggest that there should be an option to limit the effects of the selected sanitization strategy to the translate directive. The service and filter should have the option to be used without sanitization, since Angular takes care of the sanitization in many cases anyway, making the sanitization inside angular-translate redundant.
Issue Analytics
- State:
- Created 7 years ago
- Comments:9 (6 by maintainers)

Top Related StackOverflow Question
Hm, get it. This requires some work as directive and service cannot be distinguished at the moment.
Meanwhile,
contexthas been added in mostly all calls. The strategysceis using this already.