@@ -51,6 +51,69 @@ export class AttachmentsService {
5151 userId ?: string ,
5252 ) : Promise < AttachmentResponseDto > {
5353 try {
54+ // Blocked file extensions for security
55+ const BLOCKED_EXTENSIONS = [
56+ 'exe' ,
57+ 'bat' ,
58+ 'cmd' ,
59+ 'com' ,
60+ 'scr' ,
61+ 'msi' , // Windows executables
62+ 'js' ,
63+ 'vbs' ,
64+ 'vbe' ,
65+ 'wsf' ,
66+ 'wsh' ,
67+ 'ps1' , // Scripts
68+ 'sh' ,
69+ 'bash' ,
70+ 'zsh' , // Shell scripts
71+ 'dll' ,
72+ 'sys' ,
73+ 'drv' , // System files
74+ 'app' ,
75+ 'deb' ,
76+ 'rpm' , // Application packages
77+ 'jar' , // Java archives (can execute)
78+ 'pif' ,
79+ 'lnk' ,
80+ 'cpl' , // Shortcuts and control panel
81+ 'hta' ,
82+ 'reg' , // HTML apps and registry
83+ ] ;
84+
85+ // Blocked MIME types for security
86+ const BLOCKED_MIME_TYPES = [
87+ 'application/x-msdownload' , // .exe
88+ 'application/x-msdos-program' ,
89+ 'application/x-executable' ,
90+ 'application/x-sh' , // Shell scripts
91+ 'application/x-bat' , // Batch files
92+ 'text/x-sh' ,
93+ 'text/x-python' ,
94+ 'text/x-perl' ,
95+ 'text/x-ruby' ,
96+ 'application/x-httpd-php' , // PHP files
97+ 'application/x-javascript' , // Executable JS (not JSON)
98+ 'application/javascript' ,
99+ 'text/javascript' ,
100+ ] ;
101+
102+ // Validate file extension
103+ const fileExt = uploadDto . fileName . split ( '.' ) . pop ( ) ?. toLowerCase ( ) ;
104+ if ( fileExt && BLOCKED_EXTENSIONS . includes ( fileExt ) ) {
105+ throw new BadRequestException (
106+ `File extension '.${ fileExt } ' is not allowed for security reasons` ,
107+ ) ;
108+ }
109+
110+ // Validate MIME type
111+ if ( BLOCKED_MIME_TYPES . includes ( uploadDto . fileType . toLowerCase ( ) ) ) {
112+ throw new BadRequestException (
113+ `File type '${ uploadDto . fileType } ' is not allowed for security reasons` ,
114+ ) ;
115+ }
116+
54117 // Validate file size
55118 const fileBuffer = Buffer . from ( uploadDto . fileData , 'base64' ) ;
56119 if ( fileBuffer . length > this . MAX_FILE_SIZE_BYTES ) {
0 commit comments