Commit 00454b32 by Alexander Zobnin Committed by Marcus Efraimsson

fix XSS vulnerabilities in dashboard links (#11813)

fix XSS vulnerabilities in dashboard links
parent 7e9a10a5
...@@ -15,7 +15,7 @@ function dashLinksContainer() { ...@@ -15,7 +15,7 @@ function dashLinksContainer() {
} }
/** @ngInject */ /** @ngInject */
function dashLink($compile, linkSrv) { function dashLink($compile, $sanitize, linkSrv) {
return { return {
restrict: 'E', restrict: 'E',
link: function(scope, elem) { link: function(scope, elem) {
...@@ -49,10 +49,21 @@ function dashLink($compile, linkSrv) { ...@@ -49,10 +49,21 @@ function dashLink($compile, linkSrv) {
var linkInfo = linkSrv.getAnchorInfo(link); var linkInfo = linkSrv.getAnchorInfo(link);
span.text(linkInfo.title); span.text(linkInfo.title);
anchor.attr('href', linkInfo.href); 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); icon.attr('class', 'fa fa-fw ' + scope.link.icon);
anchor.attr('target', scope.link.target); anchor.attr('target', scope.link.target);
......
...@@ -324,6 +324,7 @@ export class PanelCtrl { ...@@ -324,6 +324,7 @@ export class PanelCtrl {
} }
var linkSrv = this.$injector.get('linkSrv'); var linkSrv = this.$injector.get('linkSrv');
var sanitize = this.$injector.get('$sanitize');
var templateSrv = this.$injector.get('templateSrv'); var templateSrv = this.$injector.get('templateSrv');
var interpolatedMarkdown = templateSrv.replace(markdown, this.panel.scopedVars); var interpolatedMarkdown = templateSrv.replace(markdown, this.panel.scopedVars);
var html = '<div class="markdown-html">'; var html = '<div class="markdown-html">';
...@@ -346,7 +347,8 @@ export class PanelCtrl { ...@@ -346,7 +347,8 @@ export class PanelCtrl {
html += '</ul>'; html += '</ul>';
} }
return html + '</div>'; html += '</div>';
return sanitize(html);
} }
openInspector() { openInspector() {
......
import _ from 'lodash'; import _ from 'lodash';
import config from 'app/core/config'; import config from 'app/core/config';
import * as dateMath from 'app/core/utils/datemath'; import * as dateMath from 'app/core/utils/datemath';
import {angularMocks, sinon} from '../lib/common'; import { angularMocks, sinon } from '../lib/common';
import {PanelModel} from 'app/features/dashboard/panel_model'; import { PanelModel } from 'app/features/dashboard/panel_model';
export function ControllerTestContext() { export function ControllerTestContext() {
var self = this; var self = this;
this.datasource = {}; this.datasource = {};
this.$element = {}; this.$element = {};
this.$sanitize = {};
this.annotationsSrv = {}; this.annotationsSrv = {};
this.timeSrv = new TimeSrvStub(); this.timeSrv = new TimeSrvStub();
this.templateSrv = new TemplateSrvStub(); this.templateSrv = new TemplateSrvStub();
...@@ -30,6 +31,7 @@ export function ControllerTestContext() { ...@@ -30,6 +31,7 @@ export function ControllerTestContext() {
$provide.value('timeSrv', self.timeSrv); $provide.value('timeSrv', self.timeSrv);
$provide.value('templateSrv', self.templateSrv); $provide.value('templateSrv', self.templateSrv);
$provide.value('$element', self.$element); $provide.value('$element', self.$element);
$provide.value('$sanitize', self.$sanitize);
_.each(mocks, function(value, key) { _.each(mocks, function(value, key) {
$provide.value(key, value); $provide.value(key, value);
}); });
...@@ -42,8 +44,8 @@ export function ControllerTestContext() { ...@@ -42,8 +44,8 @@ export function ControllerTestContext() {
self.$location = $location; self.$location = $location;
self.$browser = $browser; self.$browser = $browser;
self.$q = $q; self.$q = $q;
self.panel = new PanelModel({type: 'test'}); self.panel = new PanelModel({ type: 'test' });
self.dashboard = {meta: {}}; self.dashboard = { meta: {} };
$rootScope.appEvent = sinon.spy(); $rootScope.appEvent = sinon.spy();
$rootScope.onAppEvent = sinon.spy(); $rootScope.onAppEvent = sinon.spy();
...@@ -53,14 +55,14 @@ export function ControllerTestContext() { ...@@ -53,14 +55,14 @@ export function ControllerTestContext() {
$rootScope.colors.push('#' + i); $rootScope.colors.push('#' + i);
} }
config.panels['test'] = {info: {}}; config.panels['test'] = { info: {} };
self.ctrl = $controller( self.ctrl = $controller(
Ctrl, Ctrl,
{$scope: self.scope}, { $scope: self.scope },
{ {
panel: self.panel, panel: self.panel,
dashboard: self.dashboard, dashboard: self.dashboard,
}, }
); );
}); });
}; };
...@@ -72,7 +74,7 @@ export function ControllerTestContext() { ...@@ -72,7 +74,7 @@ export function ControllerTestContext() {
self.$browser = $browser; self.$browser = $browser;
self.scope.contextSrv = {}; self.scope.contextSrv = {};
self.scope.panel = {}; self.scope.panel = {};
self.scope.dashboard = {meta: {}}; self.scope.dashboard = { meta: {} };
self.scope.dashboardMeta = {}; self.scope.dashboardMeta = {};
self.scope.dashboardViewState = new DashboardViewStateStub(); self.scope.dashboardViewState = new DashboardViewStateStub();
self.scope.appEvent = sinon.spy(); self.scope.appEvent = sinon.spy();
...@@ -131,7 +133,7 @@ export function DashboardViewStateStub() { ...@@ -131,7 +133,7 @@ export function DashboardViewStateStub() {
export function TimeSrvStub() { export function TimeSrvStub() {
this.init = sinon.spy(); this.init = sinon.spy();
this.time = {from: 'now-1h', to: 'now'}; this.time = { from: 'now-1h', to: 'now' };
this.timeRange = function(parse) { this.timeRange = function(parse) {
if (parse === false) { if (parse === false) {
return this.time; return this.time;
...@@ -159,7 +161,7 @@ export function ContextSrvStub() { ...@@ -159,7 +161,7 @@ export function ContextSrvStub() {
export function TemplateSrvStub() { export function TemplateSrvStub() {
this.variables = []; this.variables = [];
this.templateSettings = {interpolate: /\[\[([\s\S]+?)\]\]/g}; this.templateSettings = { interpolate: /\[\[([\s\S]+?)\]\]/g };
this.data = {}; this.data = {};
this.replace = function(text) { this.replace = function(text) {
return _.template(text, this.templateSettings)(this.data); return _.template(text, this.templateSettings)(this.data);
...@@ -188,7 +190,7 @@ var allDeps = { ...@@ -188,7 +190,7 @@ var allDeps = {
TimeSrvStub: TimeSrvStub, TimeSrvStub: TimeSrvStub,
ControllerTestContext: ControllerTestContext, ControllerTestContext: ControllerTestContext,
ServiceTestContext: ServiceTestContext, ServiceTestContext: ServiceTestContext,
DashboardViewStateStub: DashboardViewStateStub DashboardViewStateStub: DashboardViewStateStub,
}; };
// for legacy // for legacy
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment