@@ -257,7 +257,11 @@ func extractTar(archivePath, destPath, archiveType string, logger io.Writer) err
257257 continue
258258 }
259259
260- target := filepath .Join (destPath , name )
260+ // Security: Validate path to prevent path traversal attacks
261+ target , err := sanitizePath (destPath , name )
262+ if err != nil {
263+ return err
264+ }
261265
262266 switch header .Typeflag {
263267 case tar .TypeDir :
@@ -323,7 +327,11 @@ func extractZip(archivePath, destPath string, logger io.Writer) error {
323327 continue
324328 }
325329
326- target := filepath .Join (destPath , name )
330+ // Security: Validate path to prevent path traversal attacks
331+ target , err := sanitizePath (destPath , name )
332+ if err != nil {
333+ return err
334+ }
327335
328336 if file .FileInfo ().IsDir () {
329337 if err := os .MkdirAll (target , 0755 ); err != nil {
@@ -358,3 +366,32 @@ func extractZip(archivePath, destPath string, logger io.Writer) error {
358366
359367 return nil
360368}
369+
370+ // sanitizePath validates that an archive entry path is safe to extract.
371+ // It prevents path traversal attacks by ensuring the resolved path
372+ // stays within the destination directory.
373+ func sanitizePath (destDir , entryName string ) (string , error ) {
374+ // Reject absolute paths
375+ if filepath .IsAbs (entryName ) {
376+ return "" , fmt .Errorf ("path traversal detected: absolute path %q not allowed" , entryName )
377+ }
378+
379+ // Clean the path to resolve . and .. components
380+ cleanName := filepath .Clean (entryName )
381+
382+ // Reject paths that start with .. after cleaning
383+ if strings .HasPrefix (cleanName , ".." ) {
384+ return "" , fmt .Errorf ("path traversal detected: %q escapes destination directory" , entryName )
385+ }
386+
387+ // Construct the full target path
388+ target := filepath .Join (destDir , cleanName )
389+
390+ // Final check: ensure the resolved path is within destDir
391+ // This catches edge cases where filepath.Join might not prevent traversal
392+ if ! strings .HasPrefix (target , destDir + string (filepath .Separator )) && target != destDir {
393+ return "" , fmt .Errorf ("path traversal detected: %q resolves outside destination directory" , entryName )
394+ }
395+
396+ return target , nil
397+ }
0 commit comments