VYPR
High severityNVD Advisory· Published Sep 9, 2021· Updated Sep 17, 2024

OctoRPKI lacks contextual out-of-bounds check when validating RPKI ROA maxLength values

CVE-2021-3761

Description

Any CA issuer in the RPKI can trick OctoRPKI prior to 1.3.0 into emitting an invalid VRP "MaxLength" value, causing RTR sessions to terminate. An attacker can use this to disable RPKI Origin Validation in a victim network (for example AS 13335 - Cloudflare) prior to launching a BGP hijack which during normal operations would be rejected as "RPKI invalid". Additionally, in certain deployments RTR session flapping in and of itself also could cause BGP routing churn, causing availability issues.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/cloudflare/cfrpkiGo
< 1.3.01.3.0

Affected products

1

Patches

1
a8db4e009ef2

Merge pull request #90 from natesales/nsales/fix/maxlen-validation

https://github.com/cloudflare/cfrpkiEvan J JohnsonAug 19, 2021via ghsa
2 files changed · +66 0
  • validator/lib/roa.go+11 0 modified
    @@ -154,6 +154,17 @@ func (entry *ROAEntry) Validate() error {
     	if entry.MaxLength < s {
     		return errors.New(fmt.Sprintf("Max length (%v) is smaller than prefix length (%v)", entry.MaxLength, s))
     	}
    +
    +	if entry.MaxLength < 0 {
    +		return fmt.Errorf("max length (%d) is less than 0", entry.MaxLength)
    +	}
    +
    +	if entry.IPNet.IP.To4() != nil && entry.MaxLength > 32 { // If IPv4
    +		return fmt.Errorf("max length (%d) too small for IPv4 prefix", entry.MaxLength)
    +	} else if entry.MaxLength > 128 { // If IPv6
    +		return fmt.Errorf("max length (%d) too small for IPv6 prefix", entry.MaxLength)
    +	}
    +
     	return nil
     }
     
    
  • validator/lib/roa_test.go+55 0 modified
    @@ -72,3 +72,58 @@ func TestEncodeROA(t *testing.T) {
     	_, err = dc.DecodeROA(entriesBytes)
     	assert.Nil(t, err)
     }
    +
    +func TestValidateROAEntry(t *testing.T) {
    +	// Valid
    +	_, ipnet, _ := net.ParseCIDR("192.0.2.0/24")
    +	roaEntryValid := ROAEntry{
    +		IPNet:     ipnet,
    +		MaxLength: 24,
    +	}
    +
    +	// Invalid (max length too small)
    +	_, ipnet, _ = net.ParseCIDR("192.0.2.0/24")
    +	roaEntryInvalidSmallMaxLength := ROAEntry{
    +		IPNet:     ipnet,
    +		MaxLength: 8,
    +	}
    +
    +	// Invalid IPv4 (max length out of bounds)
    +	_, ipnet, _ = net.ParseCIDR("192.0.2.0/24")
    +	roaEntryInvalidLargeMaxLength := ROAEntry{
    +		IPNet:     ipnet,
    +		MaxLength: 128,
    +	}
    +
    +	// Invalid IPv6 (max length out of bounds)
    +	_, ipnet, _ = net.ParseCIDR("2001:db8::/128")
    +	roaEntryInvalidv6LargeMaxLength := ROAEntry{
    +		IPNet:     ipnet,
    +		MaxLength: 130,
    +	}
    +
    +	// Invalid (max length negative)
    +	_, ipnet, _ = net.ParseCIDR("0.0.0.0/0")
    +	roaEntryInvalidNegativeMaxLength := ROAEntry{
    +		IPNet:     ipnet,
    +		MaxLength: -1,
    +	}
    +
    +	for _, tc := range []struct {
    +		ROAEntry    ROAEntry
    +		ShouldError bool
    +	}{
    +		{roaEntryValid, false},
    +		{roaEntryInvalidSmallMaxLength, true},
    +		{roaEntryInvalidLargeMaxLength, true},
    +		{roaEntryInvalidv6LargeMaxLength, true},
    +		{roaEntryInvalidNegativeMaxLength, true},
    +	} {
    +		err := tc.ROAEntry.Validate()
    +		if !tc.ShouldError {
    +			assert.Nil(t, err)
    +		} else {
    +			assert.NotNil(t, err)
    +		}
    +	}
    +}
    

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

9

News mentions

0

No linked articles in our index yet.