@@ -7,6 +7,7 @@ import type { BinaryMetadata } from 'n8n-workflow';
77import  {  jsonParse  }  from  'n8n-workflow' ; 
88
99import  type  {  IBinaryDataConfig ,  IBinaryDataManager  }  from  '../Interfaces' ; 
10+ import  {  FileNotFoundError  }  from  '../errors' ; 
1011
1112const  PREFIX_METAFILE  =  'binarymeta' ; 
1213const  PREFIX_PERSISTED_METAFILE  =  'persistedmeta' ; 
@@ -85,17 +86,17 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
8586	} 
8687
8788	getBinaryPath ( identifier : string ) : string  { 
88- 		return  path . join ( this . storagePath ,   identifier ) ; 
89+ 		return  this . resolveStoragePath ( identifier ) ; 
8990	} 
9091
9192	getMetadataPath ( identifier : string ) : string  { 
92- 		return  path . join ( this . storagePath ,   `${ identifier }  .metadata` ) ; 
93+ 		return  this . resolveStoragePath ( `${ identifier }  .metadata` ) ; 
9394	} 
9495
9596	async  markDataForDeletionByExecutionId ( executionId : string ) : Promise < void >  { 
9697		const  tt  =  new  Date ( new  Date ( ) . getTime ( )  +  this . binaryDataTTL  *  60000 ) ; 
9798		return  fs . writeFile ( 
98- 			path . join ( this . getBinaryDataMetaPath ( ) ,  `${ PREFIX_METAFILE }  _${ executionId }  _${ tt . valueOf ( ) }  ` ) , 
99+ 			this . resolveStoragePath ( 'meta' ,  `${ PREFIX_METAFILE }  _${ executionId }  _${ tt . valueOf ( ) }  ` ) , 
99100			'' , 
100101		) ; 
101102	} 
@@ -116,8 +117,8 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
116117		const  timeAtNextHour  =  currentTime  +  3600000  -  ( currentTime  %  3600000 ) ; 
117118		const  timeoutTime  =  timeAtNextHour  +  this . persistedBinaryDataTTL  *  60000 ; 
118119
119- 		const  filePath  =  path . join ( 
120- 			this . getBinaryDataPersistMetaPath ( ) , 
120+ 		const  filePath  =  this . resolveStoragePath ( 
121+ 			'persistMeta' , 
121122			`${ PREFIX_PERSISTED_METAFILE }  _${ executionId }  _${ timeoutTime }  ` , 
122123		) ; 
123124
@@ -170,21 +171,18 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
170171		const  newBinaryDataId  =  this . generateFileName ( prefix ) ; 
171172
172173		return  fs 
173- 			. copyFile ( 
174- 				path . join ( this . storagePath ,  binaryDataId ) , 
175- 				path . join ( this . storagePath ,  newBinaryDataId ) , 
176- 			) 
174+ 			. copyFile ( this . resolveStoragePath ( binaryDataId ) ,  this . resolveStoragePath ( newBinaryDataId ) ) 
177175			. then ( ( )  =>  newBinaryDataId ) ; 
178176	} 
179177
180178	async  deleteBinaryDataByExecutionId ( executionId : string ) : Promise < void >  { 
181179		const  regex  =  new  RegExp ( `${ executionId }  _*` ) ; 
182- 		const  filenames  =  await  fs . readdir ( path . join ( this . storagePath ) ) ; 
180+ 		const  filenames  =  await  fs . readdir ( this . storagePath ) ; 
183181
184182		const  proms  =  filenames . reduce ( 
185183			( allProms ,  filename )  =>  { 
186184				if  ( regex . test ( filename ) )  { 
187- 					allProms . push ( fs . rm ( path . join ( this . storagePath ,   filename ) ) ) ; 
185+ 					allProms . push ( fs . rm ( this . resolveStoragePath ( filename ) ) ) ; 
188186				} 
189187
190188				return  allProms ; 
@@ -253,4 +251,11 @@ export class BinaryDataFileSystem implements IBinaryDataManager {
253251			throw  new  Error ( `Error finding file: ${ filePath }  ` ) ; 
254252		} 
255253	} 
254+ 
255+ 	private  resolveStoragePath ( ...args : string [ ] )  { 
256+ 		const  returnPath  =  path . join ( this . storagePath ,  ...args ) ; 
257+ 		if  ( path . relative ( this . storagePath ,  returnPath ) . startsWith ( '..' ) ) 
258+ 			throw  new  FileNotFoundError ( 'Invalid path detected' ) ; 
259+ 		return  returnPath ; 
260+ 	} 
256261} 
0 commit comments