CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Dashboard
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-43971
8.60.11%

GoBGP Panic: How a Single Byte Kills the Routing Table

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 21, 2026·5 min read·27 visits

PoC Available

Executive Summary (TL;DR)

GoBGP versions before 3.35.0 crash if they receive a BGP OPEN message with a Software Version Capability length of 0. This is a classic Go slice bounds panic (low > high) exploitable remotely without authentication.

A critical denial-of-service vulnerability in GoBGP allows unauthenticated remote attackers to crash the BGP daemon by sending a malformed OPEN message. The flaw resides in the parsing logic for the Software Version Capability (RFC 9174), where a zero-length field triggers a Go runtime panic due to invalid slice bounds. This results in an immediate teardown of BGP sessions and potential network outages.

The Hook: The Fragile Backbone

BGP (Border Gateway Protocol) is the duct tape holding the internet together. It relies on trust, keepalives, and the assumption that your peer isn't trying to murder your router process. GoBGP has emerged as a modern, high-performance alternative to legacy routing daemons like Quagga or FRR, written in Go to leverage memory safety and concurrency.

But memory safety doesn't mean logic safety. In CVE-2025-43971, we find a vulnerability that is almost poetic in its simplicity. It's not a complex heap overflow or a race condition. It is a simple disagreement between a developer's assumption and the Go runtime's strict rules on slicing. By sending a single byte set to 0x00 inside a specific BGP capability, an attacker can force the GoBGP process to commit suicide via panic(), tearing down all routing sessions instantly.

The Flaw: Logic vs. Runtime

The vulnerability lies in how GoBGP handles RFC 9174, which defines the "Software Version Capability" (Type 71). This capability allows a BGP speaker to tell its peer what software version it's running (mostly for debugging or vanity). The structure is simple: a Type Code, a Length, and a Value string.

In the DecodeFromBytes function within pkg/packet/bgp/bgp.go, the code is responsible for taking the raw bytes of the capability and turning them into a struct. It reads the length byte to determine how long the version string is.

The fatal flaw? The code assumed that if the declared length wasn't too big (over 64 bytes), it was valid. It forgot to check if the length was too small (zero). In the world of C, this might have just resulted in an empty string or a pointer to nothing. In the world of Go, however, messing up slice indices is a capital offense punishable by immediate process termination.

The Code: The Smoking Gun

Let's look at the vulnerable code in pkg/packet/bgp/bgp.go prior to version 3.35.0. The parser takes a byte slice data containing the capability payload.

// Vulnerable Code
softwareVersionLen := uint8(data[0]) // Read the length byte
 
// Check if we have enough data, or if length is absurdly large
if len(data[1:]) < int(softwareVersionLen) || softwareVersionLen > 64 {
    return NewMessageError(...) 
}
 
// THE CRASH SITE
c.SoftwareVersion = string(data[1:c.SoftwareVersionLen])

Here is the logic trap:

  1. An attacker sends a capability where data[0] is 0.
  2. softwareVersionLen becomes 0.
  3. The validation check: len(data[1:]) < 0 is false. The check passes.
  4. The assignment: data[1:0].

In Go syntax slice[low : high], the rule is strict: low must be less than or equal to high. Here, we are asking for a slice starting at index 1 and ending at index 0. This is impossible.

The Result: panic: runtime error: slice bounds out of range [1:0]

The fix was painfully simple: explicitly forbid zero lengths.

- if len(data[1:]) < int(softwareVersionLen) || softwareVersionLen > 64 {
+ if len(data[1:]) < int(softwareVersionLen) || softwareVersionLen > 64 || softwareVersionLen == 0 {

The Exploit: Dropping the Hammer

Exploiting this does not require a complex fuzzing harness. It requires a basic BGP speaker implementation (like a Python script using Scapy or a small Go program). The attack vector is the BGP OPEN message, which is the very first message sent to establish a session.

The Attack Chain:

  1. Connect: Establish a TCP connection to the target GoBGP server on port 179.
  2. Handshake: Construct a BGP OPEN message.
  3. Payload: Insert an Optional Parameter for Capabilities.
  4. The Trigger: Add Capability Type 71 (Software Version). Set the Length field to 0x00.
  5. Send: Fire the packet.

Because this happens during the OPEN phase, the attacker does not need to be fully established or authenticated if the router accepts connections from 0.0.0.0/0 (common in Route Server or public peering scenarios). Even if ACLs are in place, if the attacker can spoof a trusted IP (hard with TCP, but possible) or is a disgruntled peer, they can take down the router with a single packet.

The Impact: Why Panic is Bad

In a web server, a panic might just restart a single goroutine or worker process. In GoBGP, this panic happens in the packet decoding path, often bubbling up to the main loop depending on how the supervisor is configured.

If the GoBGP binary crashes:

  1. Session Drop: All BGP sessions (Peers, Upstreams, Downstreams) are immediately severed.
  2. Route Withdrawal: The router stops advertising prefixes. If this router was a Route Reflector (RR), its clients lose reachability information.
  3. Blackholing: Traffic destined for networks behind this router is dropped until the service restarts and reconverges (which can take minutes for full routing tables).

Since BGP implementations are expected to be robust, this is a high-severity Availability impact (CVSS 8.6).

Official Patches

GoBGP GitHubCommit fixing the off-by-one panic

Fix Analysis (1)

Technical Appendix

CVSS Score
8.6/ 10
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:N/I:N/A:H
EPSS Probability
0.11%
Top 70% most exploited

Affected Systems

GoBGP < 3.35.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
GoBGP
OSRG (Open Source Routing Gym)
< 3.35.03.35.0
AttributeDetail
CWE IDCWE-193 (Off-by-one / Range Error)
CVSS v3.18.6 (High)
Attack VectorNetwork (BGP OPEN Message)
ImpactDenial of Service (DoS)
EPSS Score0.00115 (~30%)
Exploit StatusTrivial PoC possible

MITRE ATT&CK Mapping

T1498Network Denial of Service
Impact
T1190Exploit Public-Facing Application
Initial Access
CWE-193
Off-by-one Error

A product calculates or uses an incorrect maximum or minimum value that is 1 more, or 1 less, than the correct value.

Known Exploits & Detection

N/ANo public exploit script released, but logic is trivial to reproduce.

Vulnerability Timeline

Fix committed to main branch
2025-02-07
CVE Published
2025-04-21
GHSA Advisory Released
2025-04-21

References & Sources

  • [1]GHSA Advisory
  • [2]NVD Detail
  • [3]Go Vulnerability Database

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.