@ -27,11 +27,15 @@ import (
"os"
"path"
"regexp"
"strconv"
"strings"
chart "helm.sh/helm/v4/pkg/chart/v2"
)
const MaxChartFileSizeEnv = "HELM_MAX_DECOMPRESSED_FILE_SIZE"
const MaxChartSizeEnv = "HELM_MAX_DECOMPRESSED_CHART_SIZE"
// MaxDecompressedChartSize is the maximum size of a chart archive that will be
// decompressed. This is the decompressed size of all the files.
// The default value is 100 MiB.
@ -115,6 +119,34 @@ func isGZipApplication(data []byte) bool {
return bytes . HasPrefix ( data , sig )
}
// getMaxDecompressedChartSize retrieves the maximum size of a decompressed chart from the environment variable
func getMaxDecompressedChartSize ( ) int64 {
chartSizeEnv , ok := os . LookupEnv ( MaxChartSizeEnv )
if ! ok {
return MaxDecompressedChartSize
}
maxSize , err := strconv . ParseInt ( chartSizeEnv , 10 , 64 )
if err != nil {
return MaxDecompressedChartSize
}
return maxSize
}
// getMaxDecompressedFileSize retrieves the maximum size of a decompressed file from the environment variable
func getMaxDecompressedFileSize ( ) int64 {
fileSizeEnv , ok := os . LookupEnv ( MaxChartFileSizeEnv )
if ! ok {
return MaxDecompressedFileSize
}
maxSize , err := strconv . ParseInt ( fileSizeEnv , 10 , 64 )
if err != nil {
return MaxDecompressedFileSize
}
return maxSize
}
// LoadArchiveFiles reads in files out of an archive into memory. This function
// performs important path security checks and should always be used before
// expanding a tarball
@ -127,7 +159,14 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
files := [ ] * BufferedFile { }
tr := tar . NewReader ( unzipped )
remainingSize := MaxDecompressedChartSize
// Set the maximum size of the decompressed chart.
maxChartSize := getMaxDecompressedChartSize ( )
remainingSize := maxChartSize
// Set the maximum size of a single file in the decompressed chart.
maxChartFileSize := getMaxDecompressedFileSize ( )
for {
b := bytes . NewBuffer ( nil )
hd , err := tr . Next ( )
@ -188,11 +227,11 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
}
if hd . Size > remainingSize {
return nil , fmt . Errorf ( "decompressed chart is larger than the maximum size %d" , MaxDecompressed ChartSize)
return nil , fmt . Errorf ( "decompressed chart is larger than the maximum size %d" , max ChartSize)
}
if hd . Size > MaxDecompressed FileSize {
return nil , fmt . Errorf ( "decompressed chart file %q is larger than the maximum file size %d" , hd . Name , MaxDecompressed FileSize)
if hd . Size > maxChart FileSize {
return nil , fmt . Errorf ( "decompressed chart file %q is larger than the maximum file size %d" , hd . Name , maxChart FileSize)
}
limitedReader := io . LimitReader ( tr , remainingSize )
@ -208,7 +247,7 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) {
// is the one that goes over the limit. It assumes the Size stored in the tar header
// is correct, something many applications do.
if bytesWritten < hd . Size || remainingSize <= 0 {
return nil , fmt . Errorf ( "decompressed chart is larger than the maximum size %d" , MaxDecompressed ChartSize)
return nil , fmt . Errorf ( "decompressed chart is larger than the maximum size %d" , max ChartSize)
}
data := bytes . TrimPrefix ( b . Bytes ( ) , utf8bom )