From c26a6d6c754e5dbb4ff2c965caa5c5471c71c538 Mon Sep 17 00:00:00 2001 From: Leanid Shutau Date: Thu, 1 Nov 2018 14:50:06 +0300 Subject: [PATCH] [I18n] Sanitize angular directive message before inserting it to DOM (#24830) (#24969) * [I18n] Sanitize message before inserting it to DOM * Add tests --- .../__snapshots__/directive.test.ts.snap | 42 ++++++++++++++++ .../kbn-i18n/src/angular/directive.test.ts | 48 ++++++++++++++++++- packages/kbn-i18n/src/angular/directive.ts | 26 ++++++---- 3 files changed, 107 insertions(+), 9 deletions(-) diff --git a/packages/kbn-i18n/src/angular/__snapshots__/directive.test.ts.snap b/packages/kbn-i18n/src/angular/__snapshots__/directive.test.ts.snap index b845ea4228838..9e783305a5a38 100644 --- a/packages/kbn-i18n/src/angular/__snapshots__/directive.test.ts.snap +++ b/packages/kbn-i18n/src/angular/__snapshots__/directive.test.ts.snap @@ -3,3 +3,45 @@ exports[`i18nDirective inserts correct translation html content with values 1`] = `"default-message word"`; exports[`i18nDirective inserts correct translation html content with values 2`] = `"default-message anotherWord"`; + +exports[`i18nDirective sanitizes message before inserting it to DOM 1`] = ` +
' }" +> + Default message, +
+
+`; + +exports[`i18nDirective sanitizes onclick attribute 1`] = ` +
+ Default + + Press + + message +
+`; + +exports[`i18nDirective sanitizes onmouseover attribute 1`] = ` +
Press' }" +> + Default + + Press + + message +
+`; diff --git a/packages/kbn-i18n/src/angular/directive.test.ts b/packages/kbn-i18n/src/angular/directive.test.ts index 813863fed7e4e..bd454192a9b2d 100644 --- a/packages/kbn-i18n/src/angular/directive.test.ts +++ b/packages/kbn-i18n/src/angular/directive.test.ts @@ -19,12 +19,13 @@ import angular from 'angular'; import 'angular-mocks'; +import 'angular-sanitize'; import { i18nDirective } from './directive'; import { I18nProvider } from './provider'; angular - .module('app', []) + .module('app', ['ngSanitize']) .provider('i18n', I18nProvider) .directive('i18nId', i18nDirective); @@ -82,4 +83,49 @@ describe('i18nDirective', () => { expect(element.html()).toMatchSnapshot(); }); + + test('sanitizes message before inserting it to DOM', () => { + const element = angular.element( + `
` + ); + + compile(element)(scope); + scope.$digest(); + + expect(element[0]).toMatchSnapshot(); + }); + + test('sanitizes onclick attribute', () => { + const element = angular.element( + `
` + ); + + compile(element)(scope); + scope.$digest(); + + expect(element[0]).toMatchSnapshot(); + }); + + test('sanitizes onmouseover attribute', () => { + const element = angular.element( + `
` + ); + + compile(element)(scope); + scope.$digest(); + + expect(element[0]).toMatchSnapshot(); + }); }); diff --git a/packages/kbn-i18n/src/angular/directive.ts b/packages/kbn-i18n/src/angular/directive.ts index 1dc817a82ab24..0b111c3daad68 100644 --- a/packages/kbn-i18n/src/angular/directive.ts +++ b/packages/kbn-i18n/src/angular/directive.ts @@ -27,7 +27,10 @@ interface I18nScope extends IScope { id: string; } -export function i18nDirective(i18n: I18nServiceType): IDirective { +export function i18nDirective( + i18n: I18nServiceType, + $sanitize: (html: string) => string +): IDirective { return { restrict: 'A', scope: { @@ -38,20 +41,27 @@ export function i18nDirective(i18n: I18nServiceType): IDirective { link($scope, $element) { if ($scope.values) { $scope.$watchCollection('values', () => { - setHtmlContent($element, $scope, i18n); + setHtmlContent($element, $scope, $sanitize, i18n); }); } else { - setHtmlContent($element, $scope, i18n); + setHtmlContent($element, $scope, $sanitize, i18n); } }, }; } -function setHtmlContent($element: IRootElementService, $scope: I18nScope, i18n: I18nServiceType) { +function setHtmlContent( + $element: IRootElementService, + $scope: I18nScope, + $sanitize: (html: string) => string, + i18n: I18nServiceType +) { $element.html( - i18n($scope.id, { - values: $scope.values, - defaultMessage: $scope.defaultMessage, - }) + $sanitize( + i18n($scope.id, { + values: $scope.values, + defaultMessage: $scope.defaultMessage, + }) + ) ); }