|
@@ -2994,11 +2994,18 @@ jQuery.PrivateBin = (function($) {
|
|
|
|
|
|
|
|
const mimeType = me.getAttachmentMimeType(attachmentData);
|
|
const mimeType = me.getAttachmentMimeType(attachmentData);
|
|
|
|
|
|
|
|
|
|
+ // We explicitly do _not_ use the original mime type for the download link
|
|
|
|
|
+ // to always force a download instead of potentially dangerous browser rendering/parsing/interpretation
|
|
|
|
|
+ let safeMimeType = 'application/octet-stream';
|
|
|
|
|
+ if (me.isSafeMimeType(mimeType)) {
|
|
|
|
|
+ safeMimeType = mimeType;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// extract data and convert to binary
|
|
// extract data and convert to binary
|
|
|
const rawData = attachmentData.substring(base64Start);
|
|
const rawData = attachmentData.substring(base64Start);
|
|
|
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
|
const decodedData = rawData.length > 0 ? atob(rawData) : '';
|
|
|
|
|
|
|
|
- let blobUrl = getBlobUrl(decodedData, mimeType);
|
|
|
|
|
|
|
+ let blobUrl = getBlobUrl(decodedData, safeMimeType);
|
|
|
attachmentLink.attr('href', blobUrl);
|
|
attachmentLink.attr('href', blobUrl);
|
|
|
|
|
|
|
|
if (typeof fileName !== 'undefined') {
|
|
if (typeof fileName !== 'undefined') {
|
|
@@ -3028,6 +3035,28 @@ jQuery.PrivateBin = (function($) {
|
|
|
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
|
me.handleBlobAttachmentPreview($attachmentPreview, blobUrl, mimeType);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Evaluates whether this is known a safe mime type.
|
|
|
|
|
+ *
|
|
|
|
|
+ * This means, the media can safely be displayed and e.g. no XSS should be possible.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @name AttachmentViewer.isSafeMimeType
|
|
|
|
|
+ * @function
|
|
|
|
|
+ * @param {string}
|
|
|
|
|
+ * @returns {bool}
|
|
|
|
|
+ */
|
|
|
|
|
+ me.isSafeMimeType = function(mimeType) {
|
|
|
|
|
+ return (
|
|
|
|
|
+ mimeType.startsWith('image/') &&
|
|
|
|
|
+ !mimeType.includes('svg')
|
|
|
|
|
+ ) ||
|
|
|
|
|
+ mimeType.startsWith('video/') ||
|
|
|
|
|
+ mimeType.startsWith('audio/') ||
|
|
|
|
|
+ mimeType.endsWith('/pdf') ||
|
|
|
|
|
+ mimeType === 'text/plain';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* displays the attachment
|
|
* displays the attachment
|
|
|
*
|
|
*
|
|
@@ -6064,4 +6093,4 @@ jQuery.PrivateBin = (function($) {
|
|
|
CopyToClipboard: CopyToClipboard,
|
|
CopyToClipboard: CopyToClipboard,
|
|
|
Controller: Controller
|
|
Controller: Controller
|
|
|
};
|
|
};
|
|
|
-})(jQuery);
|
|
|
|
|
|
|
+})(jQuery);
|