OctoRPKI lacks contextual out-of-bounds check when validating RPKI ROA maxLength values
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.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/cloudflare/cfrpkiGo | < 1.3.0 | 1.3.0 |
Affected products
1- Range: unspecified
Patches
1a8db4e009ef2Merge pull request #90 from natesales/nsales/fix/maxlen-validation
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- github.com/advisories/GHSA-c8xp-8mf3-62h9ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-3761ghsaADVISORY
- www.debian.org/security/2022/dsa-5041ghsavendor-advisoryx_refsource_DEBIANWEB
- github.com/cloudflare/cfrpkighsaPACKAGE
- github.com/cloudflare/cfrpki/commit/a8db4e009ef217484598ba1fd1c595b54e0f6422ghsaWEB
- github.com/cloudflare/cfrpki/pull/90ghsaWEB
- github.com/cloudflare/cfrpki/releases/tag/v1.3.0ghsaWEB
- github.com/cloudflare/cfrpki/security/advisories/GHSA-c8xp-8mf3-62h9ghsax_refsource_MISCWEB
- pkg.go.dev/vuln/GO-2022-0246ghsaWEB
News mentions
0No linked articles in our index yet.