@@ -20,6 +20,8 @@ import (
2020
2121var logsDownloadZipLog = logger .New ("cli:logs_download_zip" )
2222
23+ const maxZipEntrySize = 1 * 1024 * 1024 * 1024 // 1GB
24+
2325// unzipFile extracts a zip file to a destination directory
2426func unzipFile (zipPath , destDir string , verbose bool ) error {
2527 // Open the zip file
@@ -72,8 +74,7 @@ func extractZipFile(f *zip.File, destDir string, verbose bool) (extractErr error
7274
7375 // Decompression bomb protection - limit individual file size to 1GB
7476 // #nosec G110 -- Decompression bomb is mitigated by size check below
75- const maxFileSize = 1 * 1024 * 1024 * 1024 // 1GB
76- if f .UncompressedSize64 > maxFileSize {
77+ if f .UncompressedSize64 > maxZipEntrySize {
7778 logsDownloadZipLog .Printf ("Rejected oversized zip entry (decompression bomb guard): %s (%d bytes)" , f .Name , f .UncompressedSize64 )
7879 return fmt .Errorf ("file too large in zip (>1GB): %s (%d bytes)" , f .Name , f .UncompressedSize64 )
7980 }
@@ -83,6 +84,10 @@ func extractZipFile(f *zip.File, destDir string, verbose bool) (extractErr error
8384 return fmt .Errorf ("failed to create directory: %w" , err )
8485 }
8586
87+ return extractZipFileContents (f , filePath )
88+ }
89+
90+ func extractZipFileContents (f * zip.File , filePath string ) (extractErr error ) {
8691 // Open the file in the zip
8792 srcFile , err := f .Open ()
8893 if err != nil {
@@ -91,7 +96,7 @@ func extractZipFile(f *zip.File, destDir string, verbose bool) (extractErr error
9196 defer srcFile .Close ()
9297
9398 // Create the destination file
94- destFile , err := os .OpenFile (filePath , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , f . Mode () )
99+ destFile , err := os .OpenFile (filePath , os .O_WRONLY | os .O_CREATE | os .O_TRUNC , constants . FilePermSensitive )
95100 if err != nil {
96101 return fmt .Errorf ("failed to create destination file: %w" , err )
97102 }
@@ -107,7 +112,7 @@ func extractZipFile(f *zip.File, destDir string, verbose bool) (extractErr error
107112 // Copy the content with size limit enforcement.
108113 // Limit to maxFileSize+1 bytes: if exactly maxFileSize+1 bytes can be read
109114 // the archive is over the limit and must be rejected.
110- limitedReader := io .LimitReader (srcFile , int64 (maxFileSize )+ 1 )
115+ limitedReader := io .LimitReader (srcFile , int64 (maxZipEntrySize )+ 1 )
111116 written , err := io .Copy (destFile , limitedReader )
112117 if err != nil {
113118 extractErr = fmt .Errorf ("failed to extract file: %w" , err )
@@ -117,7 +122,7 @@ func extractZipFile(f *zip.File, destDir string, verbose bool) (extractErr error
117122 // Verify we didn't exceed the size limit.
118123 // written == maxFileSize+1 means the reader was not exhausted, i.e. the
119124 // actual content is larger than maxFileSize.
120- if written > int64 (maxFileSize ) {
125+ if written > int64 (maxZipEntrySize ) {
121126 extractErr = fmt .Errorf ("file extraction exceeded size limit: %s" , f .Name )
122127 return extractErr
123128 }
0 commit comments