2
0
Эх сурвалжийг харах

Add support to validate attachment uploads by type and size

Tobias Wolf 2 жил өмнө
parent
commit
ed3223fedc

+ 2 - 0
.devcontainer/Dockerfile

@@ -30,6 +30,8 @@ ENV \
     RICHER_CARD_COMMENT_EDITOR=false \
     CARD_OPENED_WEBHOOK_ENABLED=false \
     ATTACHMENTS_STORE_PATH="" \
+    ATTACHMENTS_UPLOAD_MIME_TYPES="" \
+    ATTACHMENTS_UPLOAD_MAX_SIZE=0 \
     MAX_IMAGE_PIXEL="" \
     IMAGE_COMPRESS_RATIO="" \
     NOTIFICATION_TRAY_AFTER_READ_DAYS_BEFORE_REMOVE="" \

+ 2 - 0
Dockerfile

@@ -33,6 +33,8 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
     ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60 \
     ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15 \
     ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90 \
+    ATTACHMENTS_UPLOAD_MIME_TYPES="" \
+    ATTACHMENTS_UPLOAD_MAX_SIZE=0 \
     RICHER_CARD_COMMENT_EDITOR=false \
     CARD_OPENED_WEBHOOK_ENABLED=false \
     MAX_IMAGE_PIXEL="" \

+ 4 - 0
docker-compose.yml

@@ -266,6 +266,10 @@ services:
       # https://github.com/wekan/wekan/issues/2518
       - CARD_OPENED_WEBHOOK_ENABLED=false
       #---------------------------------------------------------------
+      # ==== Allow configuration to validate uploaded attachments ====
+      #-ATTACHMENTS_UPLOAD_MIME_TYPES=image/*,text/*
+      #-ATTACHMENTS_UPLOAD_MAX_SIZE=5000000
+      #---------------------------------------------------------------
       # ==== Allow to shrink attached/pasted image ====
       # https://github.com/wekan/wekan/pull/2544
       #-MAX_IMAGE_PIXEL=1024

+ 52 - 2
models/attachments.js

@@ -2,14 +2,32 @@ import { Meteor } from 'meteor/meteor';
 import { FilesCollection } from 'meteor/ostrio:files';
 import { createBucket } from './lib/grid/createBucket';
 import fs from 'fs';
+import FileType from 'file-type';
 import path from 'path';
 import { AttachmentStoreStrategyFilesystem, AttachmentStoreStrategyGridFs} from '/models/lib/attachmentStoreStrategy';
 import FileStoreStrategyFactory, {moveToStorage, rename, STORAGE_NAME_FILESYSTEM, STORAGE_NAME_GRIDFS} from '/models/lib/fileStoreStrategy';
 
+let attachmentUploadMimeTypes = [];
+let attachmentUploadSize = 0;
 let attachmentBucket;
 let storagePath;
+
 if (Meteor.isServer) {
   attachmentBucket = createBucket('attachments');
+
+  if (process.env.ATTACHMENTS_UPLOAD_MIME_TYPES) {
+    attachmentUploadMimeTypes = process.env.ATTACHMENTS_UPLOAD_MIME_TYPES.split(',');
+    attachmentUploadMimeTypes = attachmentUploadMimeTypes.map(value => value.trim());
+  }
+
+  if (process.env.ATTACHMENTS_UPLOAD_MAX_SIZE) {
+    attachmentUploadSize = parseInt(process.env.ATTACHMENTS_UPLOAD_MAX_SIZE);
+
+    if (isNaN(attachmentUploadSize)) {
+      attachmentUploadSize = 0
+    }
+  }
+
   storagePath = path.join(process.env.WRITABLE_PATH, 'attachments');
 }
 
@@ -34,13 +52,39 @@ Attachments = new FilesCollection({
     return ret;
   },
   onAfterUpload(fileObj) {
-    let storage = fileObj.meta.copyStorage || STORAGE_NAME_GRIDFS;
+    let isValid = true;
+
+    if (attachmentUploadMimeTypes.length) {
+      const mimeTypeResult = Promise.await(FileType.fromFile(fileObj.path));
+
+      const mimeType = (mimeTypeResult ? mimeTypeResult.mime : fileObj.type);
+      const baseMimeType = mimeType.split('/', 1)[0];
+
+      isValid = attachmentUploadMimeTypes.includes(mimeType) || attachmentUploadMimeTypes.includes(baseMimeType + '/*') || attachmentUploadMimeTypes.includes('*');
+
+      if (!isValid) {
+        console.log("Validation of uploaded file failed: file " + fileObj.path + " - mimetype " + mimeType);
+      }
+    }
+
+    if (attachmentUploadSize && fileObj.size > attachmentUploadSize) {
+      console.log("Validation of uploaded file failed: file " + fileObj.path + " - size " + fileObj.size);
+      isValid = false;
+    }
+
     // current storage is the filesystem, update object and database
     Object.keys(fileObj.versions).forEach(versionName => {
       fileObj.versions[versionName].storage = STORAGE_NAME_FILESYSTEM;
     });
+
     Attachments.update({ _id: fileObj._id }, { $set: { "versions" : fileObj.versions } });
-    moveToStorage(fileObj, storage, fileStoreStrategyFactory);
+
+    if (isValid) {
+      let storage = fileObj.meta.copyStorage || STORAGE_NAME_GRIDFS;
+      moveToStorage(fileObj, storage, fileStoreStrategyFactory);
+    } else {
+      this.remove(fileObj._id);
+    }
   },
   interceptDownload(http, fileObj, versionName) {
     const ret = fileStoreStrategyFactory.getFileStrategy(fileObj, versionName).interceptDownload(http, this.cacheControl);
@@ -57,10 +101,16 @@ Attachments = new FilesCollection({
   // - if the board is public, everyone (even unconnected) can download it
   // - if the board is private, only board members can download it
   protected(fileObj) {
+    // file may have been deleted already again after upload validation failed
+    if (!fileObj) {
+      return false;
+    }
+
     const board = Boards.findOne(fileObj.meta.boardId);
     if (board.isPublic()) {
       return true;
     }
+
     return board.hasMember(this.userId);
   },
 });

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 5639 - 1
package-lock.json


+ 1 - 0
package.json

@@ -36,6 +36,7 @@
     "escape-string-regexp": "^5.0.0",
     "exceljs": "^4.2.1",
     "fibers": "^5.0.0",
+    "file-type": "<17",
     "i18next": "^21.6.16",
     "i18next-sprintf-postprocessor": "^0.2.2",
     "jQuery": "^1.7.4",

+ 4 - 0
releases/virtualbox/start-wekan.sh

@@ -48,6 +48,10 @@
       # Defaults below. Uncomment to change. wekan/server/accounts-common.js
       # - ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90
       #---------------------------------------------------------------
+      # ==== Allow configuration to validate uploaded attachments ====
+      #export ATTACHMENTS_UPLOAD_MIME_TYPES="image/*,text/*"
+      #export ATTACHMENTS_UPLOAD_MAX_SIZE=5000000
+      #---------------------------------------------------------------
       # ==== RICH TEXT EDITOR IN CARD COMMENTS ====
       # https://github.com/wekan/wekan/pull/2560
       export RICHER_CARD_COMMENT_EDITOR=false

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 0 - 0
snap-src/bin/config


+ 4 - 0
start-wekan.bat

@@ -54,6 +54,10 @@ REM SET ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15
 REM # ==== ACCOUNT OPTIONS ====
 REM SET ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90
 
+REM # ==== Allow configuration to validate uploaded attachments ====
+REM SET ATTACHMENTS_UPLOAD_MIME_TYPES="image/*,text/*"
+REM SET ATTACHMENTS_UPLOAD_MAX_SIZE=5000000
+
 REM # ==== NOTIFICATION TRAY AFTER READ DAYS BEFORE REMOVE =====
 REM # Number of days after a notification is read before we remove it.
 REM # Default: 2

+ 4 - 0
start-wekan.sh

@@ -53,6 +53,10 @@
       # Defaults below. Uncomment to change. wekan/server/accounts-common.js
       # - ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90
       #---------------------------------------------------------------
+      # ==== Allow configuration to validate uploaded attachments ====
+      #export ATTACHMENTS_UPLOAD_MIME_TYPES="image/*,text/*"
+      #export ATTACHMENTS_UPLOAD_MAX_SIZE=5000000
+      #---------------------------------------------------------------
       # ==== RICH TEXT EDITOR IN CARD COMMENTS ====
       # https://github.com/wekan/wekan/pull/2560
       export RICHER_CARD_COMMENT_EDITOR=false

+ 4 - 0
torodb-postgresql/docker-compose.yml

@@ -276,6 +276,10 @@ services:
       # https://github.com/wekan/wekan/issues/2518
       - CARD_OPENED_WEBHOOK_ENABLED=false
       #---------------------------------------------------------------
+      # ==== Allow configuration to validate uploaded attachments ====
+      #-ATTACHMENTS_UPLOAD_MIME_TYPES=image/*,text/*
+      #-ATTACHMENTS_UPLOAD_MAX_SIZE=5000000
+      #---------------------------------------------------------------
       # ==== Allow to shrink attached/pasted image ====
       # https://github.com/wekan/wekan/pull/2544
       #-MAX_IMAGE_PIXEL=1024

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно