VYPR
Moderate severityOSV Advisory· Published Jan 22, 2026· Updated Jan 22, 2026

go-tuf improperly validates the configured threshold for delegations

CVE-2026-23992

Description

go-tuf is a Go implementation of The Update Framework (TUF). Starting in version 2.0.0 and prior to version 2.3.1, a compromised or misconfigured TUF repository can have the configured value of signature thresholds set to 0, which effectively disables signature verification. This can lead to unauthorized modification to TUF metadata files is possible at rest, or during transit as no integrity checks are made. Version 2.3.1 fixes the issue. As a workaround, always make sure that the TUF metadata roles are configured with a threshold of at least 1.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/theupdateframework/go-tuf/v2Go
< 2.3.12.3.1

Affected products

1

Patches

1
b38d91fdbc69

Verify threshold is valid (#712)

https://github.com/theupdateframework/go-tufFredrik SkogmanJan 19, 2026via ghsa
2 files changed · +48 9
  • metadata/metadata.go+7 0 modified
    @@ -292,6 +292,13 @@ func (meta *Metadata[T]) VerifyDelegate(delegatedRole string, delegatedMetadata
     	if len(roleKeyIDs) == 0 {
     		return &ErrValue{Msg: fmt.Sprintf("no delegation found for %s", delegatedRole)}
     	}
    +
    +	if roleThreshold < 1 {
    +		return &ErrValue{Msg: fmt.Sprintf("insufficient threshold (%d) configured for %s",
    +			roleThreshold,
    +			delegatedRole)}
    +	}
    +
     	// loop through each role keyID
     	for _, keyID := range roleKeyIDs {
     		key, ok := keys[keyID]
    
  • metadata/metadata_test.go+41 9 modified
    @@ -592,26 +592,24 @@ func TestVerifyDelegate(t *testing.T) {
     		},
     		Roles: []DelegatedRole{
     			{
    -				Name:   "test",
    -				KeyIDs: []string{delegateeKey.ID()},
    +				Name:      "test",
    +				KeyIDs:    []string{delegateeKey.ID()},
    +				Threshold: 1,
     			},
     		},
     	}
    +
     	targets.Signed.Delegations = delegations
    -	err = targets.VerifyDelegate("test", root)
    -	assert.NoError(t, err)
    +	err = targets.VerifyDelegate("root", targets)
    +	assert.Errorf(t, err, "Verifying test failed, not enough signatures, got %d, want %d", 0, 1)
     	err = targets.VerifyDelegate("test", targets)
    -	assert.NoError(t, err)
    +	assert.Errorf(t, err, "Verifying test failed, not enough signatures, got %d, want %d", 0, 1)
     
     	err = targets.VerifyDelegate("non-existing", root)
     	assert.EqualError(t, err, "value error: no delegation found for non-existing")
     	err = targets.VerifyDelegate("non-existing", targets)
     	assert.EqualError(t, err, "value error: no delegation found for non-existing")
     
    -	targets.Signed.Delegations.Roles[0].Threshold = 1
    -	err = targets.VerifyDelegate("test", targets)
    -	assert.Errorf(t, err, "Verifying test failed, not enough signatures, got %d, want %d", 0, 1)
    -
     	delegations.Keys["incorrectkey"] = delegations.Keys[delegateeKey.ID()]
     	delete(delegations.Keys, delegateeKey.ID())
     	err = targets.VerifyDelegate("test", root)
    @@ -626,6 +624,40 @@ func TestVerifyDelegate(t *testing.T) {
     	assert.EqualError(t, err, "type error: call is valid only on delegator metadata (should be either root or targets)")
     }
     
    +func TestVerifyDelegateThreshold(t *testing.T) {
    +	root := Root(fixedExpire)
    +	err := root.VerifyDelegate("test", root)
    +	assert.EqualError(t, err, "value error: no delegation found for test")
    +
    +	targets := Targets(fixedExpire)
    +	err = targets.VerifyDelegate("test", targets)
    +	assert.EqualError(t, err, "value error: no delegations found")
    +
    +	key, _, err := ed25519.GenerateKey(nil)
    +	assert.NoError(t, err)
    +
    +	delegateeKey, _ := KeyFromPublicKey(key)
    +	delegations := &Delegations{
    +		Keys: map[string]*Key{
    +			delegateeKey.ID(): delegateeKey,
    +		},
    +		Roles: []DelegatedRole{
    +			{
    +				Name:      "test",
    +				KeyIDs:    []string{delegateeKey.ID()},
    +				Threshold: 0,
    +			},
    +		},
    +	}
    +	targets.Signed.Delegations = delegations
    +	err = targets.VerifyDelegate("test", root)
    +	assert.ErrorIs(t, err, &ErrValue{})
    +	assert.EqualError(t, err, "value error: insufficient threshold (0) configured for test")
    +	err = targets.VerifyDelegate("test", targets)
    +	assert.ErrorIs(t, err, &ErrValue{})
    +	assert.EqualError(t, err, "value error: insufficient threshold (0) configured for test")
    +}
    +
     func TestVerifyLengthHashesTargetFiles(t *testing.T) {
     	targetFiles := TargetFile()
     	targetFiles.Hashes = map[string]HexBytes{}
    

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.