@@ -318,26 +318,35 @@ func ImportConfigFromZip(w http.ResponseWriter, r *http.Request) {
318318 }
319319 defer rc .Close ()
320320
321- // Create the corresponding file on disk
322- zipFile .Name = strings .ReplaceAll (zipFile .Name , "../" , "" )
323- fmt .Println ("Restoring: " + strings .ReplaceAll (zipFile .Name , "\\ " , "/" ))
324- if zipFile .Name == "sys.db" {
321+ // Sanitize the file name to prevent path traversal (zip-slip)
322+ cleanedName := filepath .Clean (filepath .FromSlash (zipFile .Name ))
323+ cleanedNameSlash := filepath .ToSlash (cleanedName )
324+ fmt .Println ("Restoring: " + cleanedNameSlash )
325+ if cleanedNameSlash == "sys.db" {
325326 //Sysdb replacement. Close the database and restore
326327 sysdb .Close ()
327328 restoreDatabase = true
328- } else if ! strings .HasPrefix (strings . ReplaceAll ( zipFile . Name , " \\ " , "/" ) , "conf/" ) {
329+ } else if ! strings .HasPrefix (cleanedNameSlash , "conf/" ) {
329330 //Malformed zip file.
330- http .Error (w , fmt .Sprintf ("Invalid zip file structure or version too old" ), http .StatusInternalServerError )
331+ http .Error (w , "Invalid zip file structure or version too old" , http .StatusInternalServerError )
332+ return
333+ }
334+
335+ // Resolve to absolute path and verify it stays within the target directory
336+ absTargetDir , _ := filepath .Abs (targetDir )
337+ absFilePath , _ := filepath .Abs (cleanedName )
338+ if cleanedNameSlash != "sys.db" && ! strings .HasPrefix (absFilePath , absTargetDir + string (os .PathSeparator )) {
339+ http .Error (w , "Invalid file path in zip" , http .StatusBadRequest )
331340 return
332341 }
333342
334343 //Check if parent dir exists
335- if ! utils .FileExists (filepath .Dir (zipFile . Name )) {
336- os .MkdirAll (filepath .Dir (zipFile . Name ), 0775 )
344+ if ! utils .FileExists (filepath .Dir (cleanedName )) {
345+ os .MkdirAll (filepath .Dir (cleanedName ), 0775 )
337346 }
338347
339348 //Create the file
340- newFile , err := os .Create (zipFile . Name )
349+ newFile , err := os .Create (cleanedName )
341350 if err != nil {
342351 http .Error (w , fmt .Sprintf ("Failed to create file: %v" , err ), http .StatusInternalServerError )
343352 return
@@ -369,11 +378,12 @@ func ImportConfigFromZip(w http.ResponseWriter, r *http.Request) {
369378}
370379
371380func handleLoggerConfig (w http.ResponseWriter , r * http.Request ) {
372- if r .Method == http .MethodGet {
381+ switch r .Method {
382+ case http .MethodGet :
373383 logger .HandleGetLogConfig (CONF_LOG_CONFIG )(w , r )
374- } else if r . Method == http .MethodPost {
384+ case http .MethodPost :
375385 logger .HandleUpdateLogConfig (CONF_LOG_CONFIG , SystemWideLogger )(w , r )
376- } else {
386+ default :
377387 utils .SendErrorResponse (w , "Method not allowed" )
378388 }
379389}
0 commit comments