@@ -28,6 +28,7 @@ import (
28
28
"path"
29
29
"path/filepath"
30
30
"reflect"
31
+ "regexp"
31
32
"strings"
32
33
33
34
helmchart "helm.sh/helm/v3/pkg/chart"
@@ -37,6 +38,8 @@ import (
37
38
"github.com/fluxcd/source-controller/internal/helm"
38
39
)
39
40
41
+ var drivePathPattern = regexp .MustCompile (`^[a-zA-Z]:/` )
42
+
40
43
// OverwriteChartDefaultValues overwrites the chart default values file with the given data.
41
44
func OverwriteChartDefaultValues (chart * helmchart.Chart , vals chartutil.Values ) (bool , error ) {
42
45
if vals == nil {
@@ -161,6 +164,9 @@ func LoadChartMetadataFromArchive(archive string) (*helmchart.Metadata, error) {
161
164
}
162
165
tr := tar .NewReader (zr )
163
166
167
+ // The following logic is on par with how Helm validates the package while
168
+ // unpackaging it, except that we only read the Metadata related files.
169
+ // Ref: https://git.1-hub.cnhelm/helm/blob/a499b4b179307c267bdf3ec49b880e3dbd2a5591/pkg/chart/loader/archive.go#L104
164
170
var m * helmchart.Metadata
165
171
for {
166
172
hd , err := tr .Next ()
@@ -189,19 +195,42 @@ func LoadChartMetadataFromArchive(archive string) (*helmchart.Metadata, error) {
189
195
delimiter = "\\ "
190
196
}
191
197
parts := strings .Split (hd .Name , delimiter )
192
-
193
- // We are only interested in files in the base directory
194
- if len (parts ) != 2 {
195
- continue
196
- }
198
+ n := strings .Join (parts [1 :], delimiter )
197
199
198
200
// Normalize the path to the / delimiter
199
- n := strings .Join (parts [1 :], delimiter )
200
201
n = strings .ReplaceAll (n , delimiter , "/" )
202
+
203
+ if path .IsAbs (n ) {
204
+ return nil , errors .New ("chart illegally contains absolute paths" )
205
+ }
206
+
201
207
n = path .Clean (n )
208
+ if n == "." {
209
+ // In this case, the original path was relative when it should have been absolute.
210
+ return nil , fmt .Errorf ("chart illegally contains content outside the base directory: %s" , hd .Name )
211
+ }
212
+ if strings .HasPrefix (n , ".." ) {
213
+ return nil , fmt .Errorf ("chart illegally references parent directory" )
214
+ }
215
+
216
+ // In some particularly arcane acts of path creativity, it is possible to intermix
217
+ // UNIX and Windows style paths in such a way that you produce a result of the form
218
+ // c:/foo even after all the built-in absolute path checks. So we explicitly check
219
+ // for this condition.
220
+ if drivePathPattern .MatchString (n ) {
221
+ return nil , errors .New ("chart contains illegally named files" )
222
+ }
223
+
224
+ // We are only interested in files in the base directory from here on
225
+ if len (parts ) != 2 {
226
+ continue
227
+ }
202
228
203
229
switch parts [1 ] {
204
230
case chartutil .ChartfileName , "requirements.yaml" :
231
+ if hd .Size > helm .MaxChartFileSize {
232
+ return nil , fmt .Errorf ("size of '%s' exceeds '%d' bytes limit" , hd .Name , helm .MaxChartFileSize )
233
+ }
205
234
b , err := io .ReadAll (tr )
206
235
if err != nil {
207
236
return nil , err
0 commit comments