From f4fdb8716b8d6efa63f989485aec539485fcaddc Mon Sep 17 00:00:00 2001 From: Sylwester Piskozub Date: Wed, 29 Oct 2025 11:11:18 +0100 Subject: [PATCH 1/2] fix(helm-chart): allow empty values Signed-off-by: Sylwester Piskozub --- pkg/attestation/crafter/materials/helmchart.go | 11 ++++++++--- .../crafter/materials/helmchart_test.go | 6 ++++++ .../crafter/materials/testdata/empty-values.tgz | Bin 0 -> 273 bytes 3 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 pkg/attestation/crafter/materials/testdata/empty-values.tgz diff --git a/pkg/attestation/crafter/materials/helmchart.go b/pkg/attestation/crafter/materials/helmchart.go index 417933003..c38c41795 100644 --- a/pkg/attestation/crafter/materials/helmchart.go +++ b/pkg/attestation/crafter/materials/helmchart.go @@ -121,12 +121,12 @@ func (c *HelmChartCrafter) craftLocalHelmChart(ctx context.Context, filepath str // it was compressed from. So, we can check if the file name contains the required file names // Ex: helm-chart/Chart.yaml, helm-chart/values.yaml if strings.Contains(header.Name, chartFileName) { - if err := c.validateYamlFile(tarReader); err != nil { + if err := c.validateYamlFile(tarReader, false); err != nil { return nil, fmt.Errorf("invalid Chart.yaml file: %w", err) } chartFileValid = true } else if strings.Contains(header.Name, chartValuesYamlFileName) { - if err := c.validateYamlFile(tarReader); err != nil { + if err := c.validateYamlFile(tarReader, true); err != nil { return nil, fmt.Errorf("invalid values.yaml file: %w", err) } chartValuesValid = true @@ -148,9 +148,14 @@ func (c *HelmChartCrafter) craftLocalHelmChart(ctx context.Context, filepath str } // validateYamlFile validates the YAML file just by trying to unmarshal it -func (c *HelmChartCrafter) validateYamlFile(r io.Reader) error { +func (c *HelmChartCrafter) validateYamlFile(r io.Reader, allowEmpty bool) error { v := make(map[string]interface{}) if err := yaml.NewDecoder(r).Decode(v); err != nil { + // io.EOF means the file is empty or contains only comments + // This is valid for values.yaml + if err == io.EOF && allowEmpty { + return nil + } return fmt.Errorf("failed to unmarshal YAML file: %w", err) } diff --git a/pkg/attestation/crafter/materials/helmchart_test.go b/pkg/attestation/crafter/materials/helmchart_test.go index 66af7c58b..9799806a5 100644 --- a/pkg/attestation/crafter/materials/helmchart_test.go +++ b/pkg/attestation/crafter/materials/helmchart_test.go @@ -102,6 +102,12 @@ func TestHelmChartCraft(t *testing.T) { wantDigest: "sha256:08a46a850789938ede61d6a53552f48cb8ba74c4e17dcf30c9c50e5783ca6a13", wantFilename: "valid-chart.tgz", }, + { + name: "chart with empty values.yaml", + filePath: "./testdata/empty-values.tgz", + wantDigest: "sha256:6c5bc910da7ecb00aa1c7be70e51db237d129e3f41ff6ada1d11ea402ff7082e", + wantFilename: "empty-values.tgz", + }, } assert := assert.New(t) diff --git a/pkg/attestation/crafter/materials/testdata/empty-values.tgz b/pkg/attestation/crafter/materials/testdata/empty-values.tgz new file mode 100644 index 0000000000000000000000000000000000000000..9082243102dba5200dc0a6f7475d8cd46c7d05f8 GIT binary patch literal 273 zcmb2|=3oE==C@Z4X0;fIum)WJ*>(KQRzs=Qo4j|waPRWZO=xjxRulWbukh5Ag$YYT zqS)R={i)Iio_fXSy1hDf zc~s~v72rJiciRTNo;Y3?&kD}D{P%lqzqr3L&Gdi& Date: Wed, 29 Oct 2025 11:26:54 +0100 Subject: [PATCH 2/2] lint Signed-off-by: Sylwester Piskozub --- pkg/attestation/crafter/materials/helmchart.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/attestation/crafter/materials/helmchart.go b/pkg/attestation/crafter/materials/helmchart.go index c38c41795..1dfdc3b0f 100644 --- a/pkg/attestation/crafter/materials/helmchart.go +++ b/pkg/attestation/crafter/materials/helmchart.go @@ -19,6 +19,7 @@ import ( "archive/tar" "compress/gzip" "context" + "errors" "fmt" "io" "os" @@ -153,7 +154,7 @@ func (c *HelmChartCrafter) validateYamlFile(r io.Reader, allowEmpty bool) error if err := yaml.NewDecoder(r).Decode(v); err != nil { // io.EOF means the file is empty or contains only comments // This is valid for values.yaml - if err == io.EOF && allowEmpty { + if errors.Is(err, io.EOF) && allowEmpty { return nil } return fmt.Errorf("failed to unmarshal YAML file: %w", err)