Skip to content

Commit 3431f76

Browse files
MigaroezZeegaan
authored andcommitted
Prevents XSS when viewing an uploaded SVG
from the media-info and image-preview components.
1 parent 1bc5466 commit 3431f76

File tree

4 files changed

+38
-26
lines changed

4 files changed

+38
-26
lines changed

src/Umbraco.Web.UI.Client/src/common/directives/components/media/umbmedianodeinfo.directive.js

+1-9
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,7 @@
136136
editorService.mediaTypeEditor(editor);
137137
};
138138

139-
scope.openSVG = () => {
140-
var popup = window.open('', '_blank');
141-
var html = '<!DOCTYPE html><body><img src="' + scope.nodeUrl + '"/>' +
142-
'<script>history.pushState(null, null,"' + $location.$$absUrl + '");</script></body>';
143-
144-
popup.document.open();
145-
popup.document.write(html);
146-
popup.document.close();
147-
}
139+
scope.openSVG = () => mediaHelper.openSVG(scope.nodeUrl);
148140

149141
// watch for content updates - reload content when node is saved, published etc.
150142
scope.$watch('node.updateDate', function(newValue, oldValue){

src/Umbraco.Web.UI.Client/src/common/services/mediahelper.service.js

+24-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* @name umbraco.services.mediaHelper
44
* @description A helper object used for dealing with media items
55
**/
6-
function mediaHelper(umbRequestHelper, $http, $log) {
6+
function mediaHelper(umbRequestHelper, $http, $log, $location) {
77

88
//container of fileresolvers
99
var _mediaFileResolvers = {};
@@ -449,7 +449,29 @@ function mediaHelper(umbRequestHelper, $http, $log) {
449449
cropY2: options.crop ? options.crop.y2 : null
450450
})),
451451
"Failed to retrieve processed image URL for image: " + imagePath);
452-
}
452+
},
453+
454+
/**
455+
* @ngdoc function
456+
* @name umbraco.services.mediaHelper#openSVG
457+
* @methodOf umbraco.services.mediaHelper
458+
* @function
459+
*
460+
* @description
461+
* Opens an SVG file in a new window as an image file, to prevent any potential XSS exploits.
462+
*
463+
* @param {string} imagePath File path, ex /media/1234/my-image.svg
464+
*/
465+
openSVG: function (imagePath) {
466+
var popup = window.open('', '_blank');
467+
var html = '<!DOCTYPE html><body style="background-image: linear-gradient(45deg, #ccc 25%, transparent 25%), linear-gradient(135deg, #ccc 25%, transparent 25%), linear-gradient(45deg, transparent 75%, #ccc 75%), linear-gradient(135deg, transparent 75%, #ccc 75%); background-size:30px 30px; background-position:0 0, 15px 0, 15px -15px, 0px 15px;">'
468+
+ '<img src="' + imagePath + '"/>'
469+
+ '<script>history.pushState(null, null,"' + $location.$$absUrl + '");</script></body>';
470+
471+
popup.document.open();
472+
popup.document.write(html);
473+
popup.document.close();
474+
}
453475

454476
};
455477
} angular.module('umbraco.services').factory('mediaHelper', mediaHelper);
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<div class="umb-image-preview" ng-controller="umbImagePreviewController as controller">
22
<img class="umb-image-preview--image" ng-if="vm.clientSide" ng-init="previewUrl = controller.getClientSideUrl(vm.clientSideData)" ng-src="{{previewUrl}}" alt="{{vm.name}}" />
3-
<a ng-if="!vm.clientSide" href="#" ng-href="{{vm.source}}" target="_blank" rel="noopener">
3+
<a ng-if="!vm.clientSide" href="" ng-attr-href="{{vm.extension !== 'svg' ? vm.source : undefined}}" ng-click="vm.extension === 'svg' && controller.openSVG(vm.source)" target="_blank" rel="noopener">
44
<img class="umb-image-preview--image" ng-init="previewUrl = controller.getThumbnail(vm.source)" ng-src="{{previewUrl}}" alt="{{vm.name}}" />
55
</a>
66
</div>
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
1-
2-
3-
4-
51
angular.module("umbraco")
6-
.controller("umbImagePreviewController",
7-
function (mediaHelper) {
2+
.controller("umbImagePreviewController",
3+
function (mediaHelper) {
4+
5+
var vm = this;
86

9-
var vm = this;
7+
vm.getThumbnail = function (source) {
8+
return mediaHelper.getThumbnailFromPath(source) || source;
9+
}
1010

11-
vm.getThumbnail = function(source) {
12-
return mediaHelper.getThumbnailFromPath(source) || source;
13-
}
14-
vm.getClientSideUrl = function(sourceData) {
15-
return URL.createObjectURL(sourceData);
16-
}
11+
vm.getClientSideUrl = function (sourceData) {
12+
return URL.createObjectURL(sourceData);
13+
}
1714

18-
});
15+
vm.openSVG = (source) => mediaHelper.openSVG(source);
16+
});

0 commit comments

Comments
 (0)