VYPR
Moderate severityNVD Advisory· Published Oct 28, 2025· Updated Dec 9, 2025

Consul's event endpoint is vulnerable to denial of service

CVE-2025-11375

Description

Consul and Consul Enterprise’s (“Consul”) event endpoint is vulnerable to denial of service (DoS) due to lack of maximum value on the Content Length header. This vulnerability, CVE-2025-11375, is fixed in Consul Community Edition 1.22.0 and Consul Enterprise 1.22.0, 1.21.6, 1.20.8 and 1.18.12.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Consul event endpoint vulnerable to DoS via oversized Content-Length header; fixed in versions 1.22.0, 1.21.6, 1.20.8, 1.18.12.

Vulnerability

The event endpoint in Consul and Consul Enterprise lacked a maximum value check on the Content-Length header, allowing an attacker to send a request with an arbitrarily large Content-Length value. This could cause resource exhaustion and denial of service (DoS) [1][2]. The fix introduces a limit of 100 bytes, as documented in the Consul event command documentation [1].

Exploitation

An attacker with network access to the Consul HTTP API can exploit this vulnerability by sending a crafted HTTP request with an oversized Content-Length header. No authentication is required for the event endpoint, making it accessible to unauthenticated attackers. The server may allocate excessive resources or hang, leading to a denial of service [2].

Impact

Successful exploitation results in denial of service, rendering the Consul service unavailable. This can disrupt service discovery, health checking, and other critical functions within a Consul cluster, potentially affecting all dependent services [2].

Mitigation

The vulnerability is fixed in Consul Community Edition 1.22.0 and Consul Enterprise 1.22.0, 1.21.6, 1.20.8, and 1.18.12 [2][3]. Users should upgrade to these versions or apply the patch from the referenced commit [4]. No workarounds are currently available.

AI Insight generated on May 19, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
github.com/hashicorp/consulGo
< 1.22.01.22.0

Affected products

4

Patches

1
e794201d0c61

fix: event endpoint content lenght limit (#22836)

https://github.com/hashicorp/consulDeniz Onur DuzgunOct 13, 2025via ghsa
3 files changed · +144 4
  • agent/event_endpoint.go+22 4 modified
    @@ -5,6 +5,7 @@ package agent
     
     import (
     	"bytes"
    +	"fmt"
     	"io"
     	"net/http"
     	"strconv"
    @@ -44,12 +45,29 @@ func (s *HTTPHandlers) EventFire(resp http.ResponseWriter, req *http.Request) (i
     	}
     
     	// Get the payload
    -	if req.ContentLength > 0 {
    +	if req.ContentLength >= 0 {
    +		// The underlying gossip sets limits on the size of a user event
    +		// message. It is hard to give an exact number, as it depends on various
    +		// parameters of the event, but the payload should be kept very small
    +		// (< 100 bytes). We've multiplied this by 3 to be safe.
    +		const maxEventPayloadSize = 300
    +		if req.ContentLength > maxEventPayloadSize {
    +			return nil, HTTPError{
    +				StatusCode: http.StatusRequestEntityTooLarge,
    +				Reason: fmt.Sprintf("Event payload too large, received %d bytes, max size: %d bytes. User events should be kept small for efficient gossip propagation.",
    +					req.ContentLength, maxEventPayloadSize),
    +			}
    +		}
    +
     		var buf bytes.Buffer
    -		if _, err := io.Copy(&buf, req.Body); err != nil {
    -			return nil, err
    +		if req.Body != nil {
    +			if _, err := io.Copy(&buf, req.Body); err != nil {
    +				return nil, err
    +			}
    +			event.Payload = buf.Bytes()
     		}
    -		event.Payload = buf.Bytes()
    +	} else {
    +		return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "Event payload size must be greater than zero"}
     	}
     
     	// Try to fire the event
    
  • agent/event_endpoint_test.go+119 0 modified
    @@ -379,6 +379,125 @@ func TestEventList_EventBufOrder(t *testing.T) {
     	})
     }
     
    +func TestEventFire_PayloadSizeLimit(t *testing.T) {
    +	if testing.Short() {
    +		t.Skip("too slow for testing.Short")
    +	}
    +
    +	t.Parallel()
    +	a := NewTestAgent(t, "")
    +	defer a.Shutdown()
    +	testrpc.WaitForTestAgent(t, a.RPC, "dc1")
    +
    +	const maxPayloadSize = 300
    +
    +	type expectedResponse struct {
    +		success      bool
    +		statusCode   int
    +		errorMessage string
    +		eventName    string
    +		payloadSize  int
    +	}
    +
    +	testCases := []struct {
    +		name             string
    +		payloadSize      int
    +		expectedResponse *expectedResponse
    +		description      string
    +	}{
    +		{
    +			name:        "empty payload",
    +			payloadSize: 0,
    +			expectedResponse: &expectedResponse{
    +				success:     true,
    +				eventName:   "test",
    +				payloadSize: 0,
    +			},
    +			description: "empty payload should be accepted",
    +		},
    +		{
    +			name:        "payload within limit",
    +			payloadSize: 50,
    +			expectedResponse: &expectedResponse{
    +				success:     true,
    +				eventName:   "test",
    +				payloadSize: 50,
    +			},
    +			description: "small payload should be accepted",
    +		},
    +		{
    +			name:        "payload at exact limit",
    +			payloadSize: maxPayloadSize,
    +			expectedResponse: &expectedResponse{
    +				success:     true,
    +				eventName:   "test",
    +				payloadSize: maxPayloadSize,
    +			},
    +			description: "payload at exactly 300 bytes should be accepted",
    +		},
    +		{
    +			name:        "payload exceeds limit by 1 byte",
    +			payloadSize: maxPayloadSize + 1,
    +			expectedResponse: &expectedResponse{
    +				statusCode:   http.StatusRequestEntityTooLarge,
    +				errorMessage: "Event payload too large",
    +			},
    +			description: "payload exceeding limit should be rejected",
    +		},
    +		{
    +			name:        "large payload",
    +			payloadSize: 500,
    +			expectedResponse: &expectedResponse{
    +				statusCode:   http.StatusRequestEntityTooLarge,
    +				errorMessage: "Event payload too large",
    +			},
    +			description: "large payload should be rejected",
    +		},
    +	}
    +
    +	for _, tc := range testCases {
    +		t.Run(tc.name, func(t *testing.T) {
    +			var payload []byte
    +			if tc.payloadSize <= 0 {
    +				payload = []byte{}
    +			} else {
    +				payload = bytes.Repeat([]byte("x"), tc.payloadSize)
    +			}
    +
    +			url := "/v1/event/fire/test"
    +			req, err := http.NewRequest("PUT", url, bytes.NewBuffer(payload))
    +			require.NoError(t, err)
    +
    +			resp := httptest.NewRecorder()
    +			obj, err := a.srv.EventFire(resp, req)
    +
    +			if tc.expectedResponse.success {
    +				require.NoError(t, err, tc.description)
    +				require.NotNil(t, obj, "Should return event object on success")
    +
    +				event, ok := obj.(*UserEvent)
    +				require.True(t, ok, "Expected *UserEvent, got %T", obj)
    +				require.Equal(t, tc.expectedResponse.eventName, event.Name)
    +
    +				if tc.expectedResponse.payloadSize == 0 {
    +					// Empty payload should result in nil
    +					require.Nil(t, event.Payload)
    +				} else {
    +					expectedPayload := bytes.Repeat([]byte("x"), tc.expectedResponse.payloadSize)
    +					require.Equal(t, expectedPayload, event.Payload)
    +				}
    +			} else {
    +				require.Error(t, err, tc.description)
    +				httpErr, ok := err.(HTTPError)
    +				require.True(t, ok, "Expected HTTPError, got %T", err)
    +				require.Equal(t, tc.expectedResponse.statusCode, httpErr.StatusCode)
    +				require.Contains(t, httpErr.Reason, tc.expectedResponse.errorMessage)
    +				require.Nil(t, obj, "Should not return event object on error")
    +			}
    +		})
    +	}
    +}
    +
     func TestUUIDToUint64(t *testing.T) {
     	t.Parallel()
     	inp := "cb9a81ad-fff6-52ac-92a7-5f70687805ec"
    
  • .changelog/22836.txt+3 0 added
    @@ -0,0 +1,3 @@
    +```release-note:security
    +security: adding a maximum Content-Length on the event endpoint to fix denial-of-service (DoS) attacks. This resolves [CVE-2025-11375](https://nvd.nist.gov/vuln/detail/CVE-2025-11375).
    +```
    

Vulnerability mechanics

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

References

7

News mentions

0

No linked articles in our index yet.