Try to fix some security issues.

Thanks to responsible security disclosure contributors and xet7 !
This commit is contained in:
Lauri Ojansivu 2023-02-20 01:21:33 +02:00
parent b349ecbdf7
commit ff993e7c91
9 changed files with 4272 additions and 2291 deletions

View file

@ -1,4 +1,4 @@
import DOMPurify from 'dompurify'; import DOMPurify from 'isomorphic-dompurify';
import { TAPi18n } from '/imports/i18n'; import { TAPi18n } from '/imports/i18n';
const activitiesPerPage = 500; const activitiesPerPage = 500;

View file

@ -34,22 +34,22 @@ template(name="attachmentsGalery")
.attachments-galery .attachments-galery
each attachments each attachments
.attachment-item .attachment-item
a.attachment-thumbnail.swipebox(href="{{link}}" title="{{name}}") a.attachment-thumbnail.swipebox(href="{{link}}" title="{{sanitize name}}")
if link if link
if isImage if isImage
img.attachment-thumbnail-img(src="{{link}}") img.attachment-thumbnail-img(src="{{link}}" title="{{sanitize name}}")
else if($eq extension 'mp3') else if($eq extension 'mp3')
video(width="100%" height="100%" controls="true") video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
source(src="{{link}}" type="audio/mpeg") source(src="{{link}}" type="audio/mpeg")
else if($eq extension 'ogg') else if($eq extension 'ogg')
video(width="100%" height="100%" controls="true") video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
source(src="{{link}}" type="video/ogg") source(src="{{link}}" type="video/ogg")
else if($eq extension 'webm') else if($eq extension 'webm')
video(width="100%" height="100%" controls="true") video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
source(src="{{link}}" type="video/webm") source(src="{{link}}" type="video/webm")
else if($eq extension 'mp4') else if($eq extension 'mp4')
video(width="100%" height="100%" controls="true") video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
source(src="{{link}}" type="video/mp4") source(src="{{link}}" type="video/mp4")
else else
span.attachment-thumbnail-ext= extension span.attachment-thumbnail-ext= extension
p.attachment-details p.attachment-details

View file

@ -1,4 +1,5 @@
import { ObjectID } from 'bson'; import { ObjectID } from 'bson';
import DOMPurify from 'isomorphic-dompurify';
const filesize = require('filesize'); const filesize = require('filesize');
const prettyMilliseconds = require('pretty-ms'); const prettyMilliseconds = require('pretty-ms');
@ -21,6 +22,9 @@ Template.attachmentsGalery.helpers({
const ret = filesize(size); const ret = filesize(size);
return ret; return ret;
}, },
sanitize(value) {
return DOMPurify.sanitize(value);
},
}); });
Template.cardAttachmentsPopup.onCreated(function() { Template.cardAttachmentsPopup.onCreated(function() {
@ -49,6 +53,10 @@ Template.cardAttachmentsPopup.events({
let uploads = []; let uploads = [];
for (const file of files) { for (const file of files) {
const fileId = new ObjectID().toString(); const fileId = new ObjectID().toString();
// If filename is not same as sanitized filename, has XSS, then cancel upload
if (file.name !== DOMPurify.sanitize(file.name)) {
return false;
}
const config = { const config = {
file: file, file: file,
fileId: fileId, fileId: fileId,

View file

@ -283,7 +283,7 @@ BlazeComponent.extendComponent({
} }
}).register('editor'); }).register('editor');
import DOMPurify from 'dompurify'; import DOMPurify from 'isomorphic-dompurify';
// Additional safeAttrValue function to allow for other specific protocols // Additional safeAttrValue function to allow for other specific protocols
// See https://github.com/leizongmin/js-xss/issues/52#issuecomment-241354114 // See https://github.com/leizongmin/js-xss/issues/52#issuecomment-241354114

View file

@ -6,6 +6,7 @@ import fs from 'fs';
import path from 'path'; import path from 'path';
import { AttachmentStoreStrategyFilesystem, AttachmentStoreStrategyGridFs, AttachmentStoreStrategyS3 } from '/models/lib/attachmentStoreStrategy'; import { AttachmentStoreStrategyFilesystem, AttachmentStoreStrategyGridFs, AttachmentStoreStrategyS3 } from '/models/lib/attachmentStoreStrategy';
import FileStoreStrategyFactory, {moveToStorage, rename, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS, STORAGE_NAME_S3} from '/models/lib/fileStoreStrategy'; import FileStoreStrategyFactory, {moveToStorage, rename, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS, STORAGE_NAME_S3} from '/models/lib/fileStoreStrategy';
import DOMPurify from 'isomorphic-dompurify';
let attachmentUploadExternalProgram; let attachmentUploadExternalProgram;
let attachmentUploadMimeTypes = []; let attachmentUploadMimeTypes = [];
@ -149,9 +150,11 @@ if (Meteor.isServer) {
renameAttachment(fileObjId, newName) { renameAttachment(fileObjId, newName) {
check(fileObjId, String); check(fileObjId, String);
check(newName, String); check(newName, String);
// If new name is same as sanitized name, does not have XSS, allow rename file
const fileObj = Attachments.findOne({_id: fileObjId}); if (newName === DOMPurify.sanitize(newName)) {
rename(fileObj, newName, fileStoreStrategyFactory); const fileObj = Attachments.findOne({_id: fileObjId});
rename(fileObj, newName, fileStoreStrategyFactory);
}
}, },
validateAttachment(fileObjId) { validateAttachment(fileObjId) {
check(fileObjId, String); check(fileObjId, String);

View file

@ -2499,6 +2499,7 @@ if (Meteor.isServer) {
Accounts.destroyToken(userId, token); Accounts.destroyToken(userId, token);
data.message = 'Delete token: [' + token + '] from user: ' + userId; data.message = 'Delete token: [' + token + '] from user: ' + userId;
} else if (userId) { } else if (userId) {
check(userId, String);
Users.update( Users.update(
{ {
_id: userId, _id: userId,

6518
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -41,6 +41,7 @@
"filesize": "^8.0.7", "filesize": "^8.0.7",
"i18next": "^21.6.16", "i18next": "^21.6.16",
"i18next-sprintf-postprocessor": "^0.2.2", "i18next-sprintf-postprocessor": "^0.2.2",
"isomorphic-dompurify": "^1.0.0",
"jquery": "^2.2.4", "jquery": "^2.2.4",
"jquery-ui": "^1.13.0", "jquery-ui": "^1.13.0",
"jquery-ui-touch-punch": "^0.2.3", "jquery-ui-touch-punch": "^0.2.3",

View file

@ -1,4 +1,4 @@
import DOMPurify from 'dompurify'; import DOMPurify from 'isomorphic-dompurify';
var Markdown = require('markdown-it')({ var Markdown = require('markdown-it')({
html: true, html: true,