VYPR
Moderate severityNVD Advisory· Published Dec 15, 2022· Updated Apr 18, 2025

Helm vulnerable to Denial of service via NULL Pointer Dereference

CVE-2022-23525

Description

Helm is a tool for managing Charts, pre-configured Kubernetes resources. Versions prior to 3.10.3 are subject to NULL Pointer Dereference in the _repo_package. The _repo_ package contains a handler that processes the index file of a repository. For example, the Helm client adds references to chart repositories where charts are managed. The _repo_ package parses the index file of the repository and loads it into structures Go can work with. Some index files can cause array data structures to be created causing a memory violation. Applications that use the _repo_ package in the Helm SDK to parse an index file can suffer a Denial of Service when that input causes a panic that cannot be recovered from. The Helm Client will panic with an index file that causes a memory violation panic. Helm is not a long running service so the panic will not affect future uses of the Helm client. This issue has been patched in 3.10.3. SDK users can validate index files that are correctly formatted before passing them to the _repo_ functions.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
helm.sh/helm/v3Go
< 3.10.33.10.3

Affected products

1

Patches

1
638ebffbc2e4

Merge pull request from GHSA-53c4-hhmh-vw5q

https://github.com/helm/helmMartin HickeyDec 14, 2022via ghsa
4 files changed · +75 0
  • pkg/repo/index.go+8 0 modified
    @@ -118,6 +118,10 @@ func LoadIndexFile(path string) (*IndexFile, error) {
     // MustAdd adds a file to the index
     // This can leave the index in an unsorted state
     func (i IndexFile) MustAdd(md *chart.Metadata, filename, baseURL, digest string) error {
    +	if i.Entries == nil {
    +		return errors.New("entries not initialized")
    +	}
    +
     	if md.APIVersion == "" {
     		md.APIVersion = chart.APIVersionV1
     	}
    @@ -339,6 +343,10 @@ func loadIndex(data []byte, source string) (*IndexFile, error) {
     
     	for name, cvs := range i.Entries {
     		for idx := len(cvs) - 1; idx >= 0; idx-- {
    +			if cvs[idx] == nil {
    +				log.Printf("skipping loading invalid entry for chart %q from %s: empty entry", name, source)
    +				continue
    +			}
     			if cvs[idx].APIVersion == "" {
     				cvs[idx].APIVersion = chart.APIVersionV1
     			}
    
  • pkg/repo/index_test.go+33 0 modified
    @@ -59,6 +59,15 @@ entries:
           version: 1.0.0
           home: https://github.com/something
           digest: "sha256:1234567890abcdef"
    +`
    +	indexWithEmptyEntry = `
    +apiVersion: v1
    +entries:
    +  grafana:
    +  - apiVersion: v2
    +    name: grafana
    +  foo:
    +  -
     `
     )
     
    @@ -152,6 +161,12 @@ func TestLoadIndex_Duplicates(t *testing.T) {
     	}
     }
     
    +func TestLoadIndex_EmptyEntry(t *testing.T) {
    +	if _, err := loadIndex([]byte(indexWithEmptyEntry), "indexWithEmptyEntry"); err != nil {
    +		t.Errorf("unexpected error: %s", err)
    +	}
    +}
    +
     func TestLoadIndex_Empty(t *testing.T) {
     	if _, err := loadIndex([]byte(""), "indexWithEmpty"); err == nil {
     		t.Errorf("Expected an error when index.yaml is empty.")
    @@ -526,3 +541,21 @@ func TestIndexWrite(t *testing.T) {
     		t.Fatal("Index files doesn't contain expected content")
     	}
     }
    +
    +func TestAddFileIndexEntriesNil(t *testing.T) {
    +	i := NewIndexFile()
    +	i.APIVersion = chart.APIVersionV1
    +	i.Entries = nil
    +	for _, x := range []struct {
    +		md       *chart.Metadata
    +		filename string
    +		baseURL  string
    +		digest   string
    +	}{
    +		{&chart.Metadata{APIVersion: "v2", Name: " ", Version: "8033-5.apinie+s.r"}, "setter-0.1.9+beta.tgz", "http://example.com/charts", "sha256:1234567890abc"},
    +	} {
    +		if err := i.MustAdd(x.md, x.filename, x.baseURL, x.digest); err == nil {
    +			t.Errorf("expected err to be non-nil when entries not initialized")
    +		}
    +	}
    +}
    
  • pkg/repo/repo.go+3 0 modified
    @@ -100,6 +100,9 @@ func (r *File) Remove(name string) bool {
     	cp := []*Entry{}
     	found := false
     	for _, rf := range r.Repositories {
    +		if rf == nil {
    +			continue
    +		}
     		if rf.Name == name {
     			found = true
     			continue
    
  • pkg/repo/repo_test.go+31 0 modified
    @@ -225,3 +225,34 @@ func TestRepoNotExists(t *testing.T) {
     		t.Errorf("expected prompt `couldn't load repositories file`")
     	}
     }
    +
    +func TestRemoveRepositoryInvalidEntries(t *testing.T) {
    +	sampleRepository := NewFile()
    +	sampleRepository.Add(
    +		&Entry{
    +			Name: "stable",
    +			URL:  "https://example.com/stable/charts",
    +		},
    +		&Entry{
    +			Name: "incubator",
    +			URL:  "https://example.com/incubator",
    +		},
    +		&Entry{},
    +		nil,
    +		&Entry{
    +			Name: "test",
    +			URL:  "https://example.com/test",
    +		},
    +	)
    +
    +	removeRepository := "stable"
    +	found := sampleRepository.Remove(removeRepository)
    +	if !found {
    +		t.Errorf("expected repository %s not found", removeRepository)
    +	}
    +
    +	found = sampleRepository.Has(removeRepository)
    +	if found {
    +		t.Errorf("repository %s not deleted", removeRepository)
    +	}
    +}
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.