TextPanel: Fixes issue with template variable value not properly html escaped (#20588)

* sanitize html after replacing variables

* TextPanel: Always html escape variable values
This commit is contained in:
Torkel Ödegaard 2019-11-22 10:28:54 +01:00 committed by GitHub
parent 11304b14b6
commit f47759b98e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 5 deletions

View File

@ -268,6 +268,14 @@ describe('templateSrv', () => {
}); });
}); });
describe('html format', () => {
it('should encode values html escape sequences', () => {
initTemplateSrv([{ type: 'query', name: 'test', current: { value: '<script>alert(asd)</script>' } }]);
const target = _templateSrv.replace('$test', {}, 'html');
expect(target).toBe('&lt;script&gt;alert(asd)&lt;/script&gt;');
});
});
describe('format variable to string values', () => { describe('format variable to string values', () => {
it('single value should return value', () => { it('single value should return value', () => {
const result = _templateSrv.formatValue('test'); const result = _templateSrv.formatValue('test');

View File

@ -1,6 +1,7 @@
import kbn from 'app/core/utils/kbn'; import kbn from 'app/core/utils/kbn';
import _ from 'lodash'; import _ from 'lodash';
import { variableRegex } from 'app/features/templating/variable'; import { variableRegex } from 'app/features/templating/variable';
import { escapeHtml } from 'app/core/utils/text';
import { ScopedVars, TimeRange } from '@grafana/data'; import { ScopedVars, TimeRange } from '@grafana/data';
function luceneEscape(value: string) { function luceneEscape(value: string) {
@ -165,6 +166,12 @@ export class TemplateSrv {
} }
return value; return value;
} }
case 'html': {
if (_.isArray(value)) {
return escapeHtml(value.join(', '));
}
return escapeHtml(value);
}
case 'json': { case 'json': {
return JSON.stringify(value); return JSON.stringify(value);
} }

View File

@ -89,13 +89,13 @@ export class TextPanelCtrl extends PanelCtrl {
} }
updateContent(html: string) { updateContent(html: string) {
html = config.disableSanitizeHtml ? html : sanitize(html);
try { try {
this.content = this.$sce.trustAsHtml(this.templateSrv.replace(html, this.panel.scopedVars)); html = this.templateSrv.replace(html, this.panel.scopedVars, 'html');
} catch (e) { } catch (e) {
console.log('Text panel error: ', e); console.log('Text panel error: ', e);
this.content = this.$sce.trustAsHtml(html);
} }
this.content = this.$sce.trustAsHtml(config.disableSanitizeHtml ? html : sanitize(html));
} }
} }

View File

@ -41,9 +41,9 @@ export class TextPanel extends PureComponent<Props, State> {
prepareHTML(html: string): string { prepareHTML(html: string): string {
const { replaceVariables } = this.props; 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 { prepareText(content: string): string {