@@ -33,6 +33,15 @@ import (
33
33
"helm.sh/helm/v3/pkg/chart"
34
34
)
35
35
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
+
36
45
var drivePathPattern = regexp .MustCompile (`^[a-zA-Z]:/` )
37
46
38
47
// FileLoader loads a chart from a file
@@ -119,6 +128,7 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
119
128
120
129
files := []* BufferedFile {}
121
130
tr := tar .NewReader (unzipped )
131
+ remainingSize := MaxDecompressedChartSize
122
132
for {
123
133
b := bytes .NewBuffer (nil )
124
134
hd , err := tr .Next ()
@@ -178,10 +188,30 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
178
188
return nil , errors .New ("chart yaml not in base directory" )
179
189
}
180
190
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 {
182
203
return nil , err
183
204
}
184
205
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
+
185
215
data := bytes .TrimPrefix (b .Bytes (), utf8bom )
186
216
187
217
files = append (files , & BufferedFile {Name : n , Data : data })
0 commit comments