@@ -33,6 +33,15 @@ import (
3333 "helm.sh/helm/v3/pkg/chart"
3434)
3535
36+ // MaxDecompressedChartSize is the maximum size of a chart archive that will be
37+ // decompressed. This is the decompressed size of all the files.
38+ // The default value is 100 MiB.
39+ var MaxDecompressedChartSize int64 = 100 * 1024 * 1024 // Default 100 MiB
40+
41+ // MaxDecompressedFileSize is the size of the largest file that Helm will attempt to load.
42+ // The size of the file is the decompressed version of it when it is stored in an archive.
43+ var MaxDecompressedFileSize int64 = 5 * 1024 * 1024 // Default 5 MiB
44+
3645var drivePathPattern = regexp .MustCompile (`^[a-zA-Z]:/` )
3746
3847// FileLoader loads a chart from a file
@@ -119,6 +128,7 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
119128
120129 files := []* BufferedFile {}
121130 tr := tar .NewReader (unzipped )
131+ remainingSize := MaxDecompressedChartSize
122132 for {
123133 b := bytes .NewBuffer (nil )
124134 hd , err := tr .Next ()
@@ -178,10 +188,30 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
178188 return nil , errors .New ("chart yaml not in base directory" )
179189 }
180190
181- if _ , err := io .Copy (b , tr ); err != nil {
191+ if hd .Size > remainingSize {
192+ return nil , fmt .Errorf ("decompressed chart is larger than the maximum file size %d" , MaxDecompressedChartSize )
193+ }
194+
195+ if hd .Size > MaxDecompressedFileSize {
196+ return nil , fmt .Errorf ("decompressed chart file %q is larger than the maximum file size %d" , hd .Name , MaxDecompressedFileSize )
197+ }
198+
199+ limitedReader := io .LimitReader (tr , remainingSize )
200+
201+ bytesWritten , err := io .Copy (b , limitedReader )
202+ if err != nil {
182203 return nil , err
183204 }
184205
206+ remainingSize -= bytesWritten
207+ // When the bytesWritten are less than the file size it means the limit reader ended
208+ // copying early. Here we report that error. This is important if the last file extracted
209+ // is the one that goes over the limit. It assumes the Size stored in the tar header
210+ // is correct, something many applications do.
211+ if bytesWritten < hd .Size || remainingSize <= 0 {
212+ return nil , fmt .Errorf ("decompressed chart is larger than the maximum file size %d" , MaxDecompressedChartSize )
213+ }
214+
185215 data := bytes .TrimPrefix (b .Bytes (), utf8bom )
186216
187217 files = append (files , & BufferedFile {Name : n , Data : data })
0 commit comments