diff --git a/public/app/features/templating/specs/template_srv.test.ts b/public/app/features/templating/specs/template_srv.test.ts index 4d2f4accd6c..eda529815de 100644 --- a/public/app/features/templating/specs/template_srv.test.ts +++ b/public/app/features/templating/specs/template_srv.test.ts @@ -268,6 +268,14 @@ describe('templateSrv', () => { }); }); + describe('html format', () => { + it('should encode values html escape sequences', () => { + initTemplateSrv([{ type: 'query', name: 'test', current: { value: '' } }]); + const target = _templateSrv.replace('$test', {}, 'html'); + expect(target).toBe('<script>alert(asd)</script>'); + }); + }); + describe('format variable to string values', () => { it('single value should return value', () => { const result = _templateSrv.formatValue('test'); diff --git a/public/app/features/templating/template_srv.ts b/public/app/features/templating/template_srv.ts index d35e7241649..93287ab1c25 100644 --- a/public/app/features/templating/template_srv.ts +++ b/public/app/features/templating/template_srv.ts @@ -1,6 +1,7 @@ import kbn from 'app/core/utils/kbn'; import _ from 'lodash'; import { variableRegex } from 'app/features/templating/variable'; +import { escapeHtml } from 'app/core/utils/text'; import { ScopedVars, TimeRange } from '@grafana/data'; function luceneEscape(value: string) { @@ -165,6 +166,12 @@ export class TemplateSrv { } return value; } + case 'html': { + if (_.isArray(value)) { + return escapeHtml(value.join(', ')); + } + return escapeHtml(value); + } case 'json': { return JSON.stringify(value); } diff --git a/public/app/plugins/panel/text/module.ts b/public/app/plugins/panel/text/module.ts index 8456de471d0..8fed0cb339e 100644 --- a/public/app/plugins/panel/text/module.ts +++ b/public/app/plugins/panel/text/module.ts @@ -89,13 +89,13 @@ export class TextPanelCtrl extends PanelCtrl { } updateContent(html: string) { - html = config.disableSanitizeHtml ? html : sanitize(html); try { - this.content = this.$sce.trustAsHtml(this.templateSrv.replace(html, this.panel.scopedVars)); + html = this.templateSrv.replace(html, this.panel.scopedVars, 'html'); } catch (e) { console.log('Text panel error: ', e); - this.content = this.$sce.trustAsHtml(html); } + + this.content = this.$sce.trustAsHtml(config.disableSanitizeHtml ? html : sanitize(html)); } } diff --git a/public/app/plugins/panel/text2/TextPanel.tsx b/public/app/plugins/panel/text2/TextPanel.tsx index 67bb2d4daf3..cd6d202ebfd 100644 --- a/public/app/plugins/panel/text2/TextPanel.tsx +++ b/public/app/plugins/panel/text2/TextPanel.tsx @@ -41,9 +41,9 @@ export class TextPanel extends PureComponent { prepareHTML(html: string): string { const { replaceVariables } = this.props; - html = config.disableSanitizeHtml ? html : sanitize(html); + html = replaceVariables(html, {}, 'html'); - return replaceVariables(html); + return config.disableSanitizeHtml ? html : sanitize(html); } prepareText(content: string): string {