diff --git a/public/app/features/dashlinks/module.ts b/public/app/features/dashlinks/module.ts
index 8fa110fe6b4..148d32f4399 100644
--- a/public/app/features/dashlinks/module.ts
+++ b/public/app/features/dashlinks/module.ts
@@ -15,7 +15,7 @@ function dashLinksContainer() {
}
/** @ngInject */
-function dashLink($compile, linkSrv) {
+function dashLink($compile, $sanitize, linkSrv) {
return {
restrict: 'E',
link: function(scope, elem) {
@@ -49,10 +49,21 @@ function dashLink($compile, linkSrv) {
var linkInfo = linkSrv.getAnchorInfo(link);
span.text(linkInfo.title);
anchor.attr('href', linkInfo.href);
+ sanitizeAnchor();
+
+ // tooltip
+ elem.find('a').tooltip({
+ title: $sanitize(scope.link.tooltip),
+ html: true,
+ container: 'body',
+ });
+ }
+
+ function sanitizeAnchor() {
+ const anchorSanitized = $sanitize(anchor.parent().html());
+ anchor.parent().html(anchorSanitized);
}
- // tooltip
- elem.find('a').tooltip({ title: scope.link.tooltip, html: true, container: 'body' });
icon.attr('class', 'fa fa-fw ' + scope.link.icon);
anchor.attr('target', scope.link.target);
diff --git a/public/app/features/panel/panel_ctrl.ts b/public/app/features/panel/panel_ctrl.ts
index 67725ec5fec..6402227164f 100644
--- a/public/app/features/panel/panel_ctrl.ts
+++ b/public/app/features/panel/panel_ctrl.ts
@@ -324,6 +324,7 @@ export class PanelCtrl {
}
var linkSrv = this.$injector.get('linkSrv');
+ var sanitize = this.$injector.get('$sanitize');
var templateSrv = this.$injector.get('templateSrv');
var interpolatedMarkdown = templateSrv.replace(markdown, this.panel.scopedVars);
var html = '
';
@@ -346,7 +347,8 @@ export class PanelCtrl {
html += '';
}
- return html + '
';
+ html += '';
+ return sanitize(html);
}
openInspector() {
diff --git a/public/test/specs/helpers.ts b/public/test/specs/helpers.ts
index 8e83915362f..ab7fbb5698b 100644
--- a/public/test/specs/helpers.ts
+++ b/public/test/specs/helpers.ts
@@ -1,14 +1,15 @@
import _ from 'lodash';
import config from 'app/core/config';
import * as dateMath from 'app/core/utils/datemath';
-import {angularMocks, sinon} from '../lib/common';
-import {PanelModel} from 'app/features/dashboard/panel_model';
+import { angularMocks, sinon } from '../lib/common';
+import { PanelModel } from 'app/features/dashboard/panel_model';
export function ControllerTestContext() {
var self = this;
this.datasource = {};
this.$element = {};
+ this.$sanitize = {};
this.annotationsSrv = {};
this.timeSrv = new TimeSrvStub();
this.templateSrv = new TemplateSrvStub();
@@ -30,6 +31,7 @@ export function ControllerTestContext() {
$provide.value('timeSrv', self.timeSrv);
$provide.value('templateSrv', self.templateSrv);
$provide.value('$element', self.$element);
+ $provide.value('$sanitize', self.$sanitize);
_.each(mocks, function(value, key) {
$provide.value(key, value);
});
@@ -42,8 +44,8 @@ export function ControllerTestContext() {
self.$location = $location;
self.$browser = $browser;
self.$q = $q;
- self.panel = new PanelModel({type: 'test'});
- self.dashboard = {meta: {}};
+ self.panel = new PanelModel({ type: 'test' });
+ self.dashboard = { meta: {} };
$rootScope.appEvent = sinon.spy();
$rootScope.onAppEvent = sinon.spy();
@@ -53,14 +55,14 @@ export function ControllerTestContext() {
$rootScope.colors.push('#' + i);
}
- config.panels['test'] = {info: {}};
+ config.panels['test'] = { info: {} };
self.ctrl = $controller(
Ctrl,
- {$scope: self.scope},
+ { $scope: self.scope },
{
panel: self.panel,
dashboard: self.dashboard,
- },
+ }
);
});
};
@@ -72,7 +74,7 @@ export function ControllerTestContext() {
self.$browser = $browser;
self.scope.contextSrv = {};
self.scope.panel = {};
- self.scope.dashboard = {meta: {}};
+ self.scope.dashboard = { meta: {} };
self.scope.dashboardMeta = {};
self.scope.dashboardViewState = new DashboardViewStateStub();
self.scope.appEvent = sinon.spy();
@@ -131,7 +133,7 @@ export function DashboardViewStateStub() {
export function TimeSrvStub() {
this.init = sinon.spy();
- this.time = {from: 'now-1h', to: 'now'};
+ this.time = { from: 'now-1h', to: 'now' };
this.timeRange = function(parse) {
if (parse === false) {
return this.time;
@@ -159,7 +161,7 @@ export function ContextSrvStub() {
export function TemplateSrvStub() {
this.variables = [];
- this.templateSettings = {interpolate: /\[\[([\s\S]+?)\]\]/g};
+ this.templateSettings = { interpolate: /\[\[([\s\S]+?)\]\]/g };
this.data = {};
this.replace = function(text) {
return _.template(text, this.templateSettings)(this.data);
@@ -188,7 +190,7 @@ var allDeps = {
TimeSrvStub: TimeSrvStub,
ControllerTestContext: ControllerTestContext,
ServiceTestContext: ServiceTestContext,
- DashboardViewStateStub: DashboardViewStateStub
+ DashboardViewStateStub: DashboardViewStateStub,
};
// for legacy