Browse Source

Panel: Fully escape html in drilldown links (was only sanitized before) (#17731)

* Sanitize HTML

* Replace sanitization lib and check for config

* Add htmlToText

* Refactor: Renaming htmlToText to escapeHtml
Tobias Skarhed 6 years ago
parent
commit
75c29566a6

+ 8 - 0
public/app/core/utils/text.ts

@@ -101,3 +101,11 @@ export function sanitize(unsanitizedString: string): string {
 export function hasAnsiCodes(input: string): boolean {
   return /\u001b\[\d{1,2}m/.test(input);
 }
+
+export function escapeHtml(str: string): string {
+  return String(str)
+    .replace(/&/g, '&')
+    .replace(/</g, '&lt;')
+    .replace(/>/g, '&gt;')
+    .replace(/"/g, '&quot;');
+}

+ 8 - 6
public/app/features/panel/panel_ctrl.ts

@@ -1,5 +1,6 @@
 import _ from 'lodash';
 import Remarkable from 'remarkable';
+import { sanitize, escapeHtml } from 'app/core/utils/text';
 
 import config from 'app/core/config';
 import { profiler } from 'app/core/core';
@@ -254,30 +255,31 @@ export class PanelCtrl {
     }
 
     const linkSrv: LinkSrv = this.$injector.get('linkSrv');
-    const sanitize: any = this.$injector.get('$sanitize');
     const templateSrv: TemplateSrv = this.$injector.get('templateSrv');
     const interpolatedMarkdown = templateSrv.replace(markdown, this.panel.scopedVars);
     let html = '<div class="markdown-html">';
 
-    html += new Remarkable().render(interpolatedMarkdown);
+    const md = new Remarkable().render(interpolatedMarkdown);
+    html += config.disableSanitizeHtml ? md : sanitize(md);
 
     if (this.panel.links && this.panel.links.length > 0) {
       html += '<ul>';
       for (const link of this.panel.links) {
         const info = linkSrv.getPanelLinkAnchorInfo(link, this.panel.scopedVars);
+
         html +=
           '<li><a class="panel-menu-link" href="' +
-          info.href +
+          escapeHtml(info.href) +
           '" target="' +
-          info.target +
+          escapeHtml(info.target) +
           '">' +
-          info.title +
+          escapeHtml(info.title) +
           '</a></li>';
       }
       html += '</ul>';
     }
 
     html += '</div>';
-    return sanitize(html);
+    return html;
   }
 }

+ 3 - 7
public/app/plugins/panel/text/module.ts

@@ -1,7 +1,7 @@
 import _ from 'lodash';
 import { PanelCtrl } from 'app/plugins/sdk';
 import Remarkable from 'remarkable';
-import { sanitize } from 'app/core/utils/text';
+import { sanitize, escapeHtml } from 'app/core/utils/text';
 import config from 'app/core/config';
 import { auto, ISCEService } from 'angular';
 import { TemplateSrv } from 'app/features/templating/template_srv';
@@ -77,12 +77,8 @@ export class TextPanelCtrl extends PanelCtrl {
   }
 
   renderText(content: string) {
-    content = content
-      .replace(/&/g, '&amp;')
-      .replace(/>/g, '&gt;')
-      .replace(/</g, '&lt;')
-      .replace(/\n/g, '<br/>');
-    this.updateContent(content);
+    const safeContent = escapeHtml(content).replace(/\n/g, '<br/>');
+    this.updateContent(safeContent);
   }
 
   renderMarkdown(content: string) {