Skip to main content
Vulnerability Database/CVE-2026-73550

CVE-2026-73550: Envoy Proxy DOS Vulnerability

CVE-2026-73550 is a denial of service vulnerability in Envoy proxy that allows attackers to exhaust memory through HTTP/2 header manipulation. This post explains its technical details, affected versions, and mitigation steps.

Published:

CVE-2026-73550 Overview

CVE-2026-73550 is a memory exhaustion vulnerability in Envoy, an open source edge and service proxy for cloud-native applications. The flaw exists in Envoy's HTTP/2 codec, where duplicate Host headers are discarded when the :authority pseudo-header is already present. The discarded bytes bypass the saveHeader accounting path, so their size is not charged against request header limits. An unauthenticated remote client can leverage HPACK indexing to reference a large Host value repeatedly across a bounded number of streams. This forces excessive header-copy allocations and can trigger an out-of-memory (OOM) kill of the proxy process [CWE-401].

Critical Impact

Unauthenticated attackers can crash Envoy proxies with a small number of HTTP/2 streams, disrupting all services fronted by the affected instance.

Affected Products

  • Envoy versions prior to 1.36.10
  • Envoy versions prior to 1.37.6
  • Envoy versions prior to 1.38.4 and 1.39.1

Discovery Timeline

  • 2026-09-21 - CVE-2026-73550 published to NVD
  • 2026-09-23 - Last updated in NVD database

Technical Details for CVE-2026-73550

Vulnerability Analysis

Envoy's HTTP/2 codec normalizes requests by preferring the :authority pseudo-header over any Host header. When both are present and equivalent, the Host header is dropped. The dropped value never passes through saveHeader, so neither its byte length nor its header count is added to the per-stream header map size tracked against configured limits.

HPACK, the HTTP/2 header compression format, permits a client to reference a large indexed header value using a small on-wire token. An attacker can send many streams that each reference a large indexed Host value. Envoy still copies each decoded value before discarding it. The cumulative allocation grows without bound relative to the configured header limits.

As the process holds memory for every decoded but uncharged Host value in flight, resident memory climbs until the Linux OOM killer terminates the proxy. Because Envoy commonly fronts multiple upstream services, a single crash yields a broad denial of service.

Root Cause

The root cause is missing accounting for discarded headers. The ConnectionImpl::recordHistogramsForStream path and the header-limit enforcement path used stream.headers().byteSize() and stream.headers().size() directly, which reflect only headers retained in the final map. Discarded Host header bytes and counts were never added, allowing per-request enforcement to be bypassed via HPACK amplification.

Attack Vector

The attack is network-reachable, unauthenticated, and requires no user interaction. An attacker opens an HTTP/2 connection, populates the HPACK dynamic table with a large Host value, and issues multiple streams that each carry both :authority and an indexed Host reference. Envoy decodes and copies each Host value, discards it, and does not charge the memory against limits. Sustained traffic drives the proxy to an OOM kill.

text
// Patch: source/common/http/http2/codec_impl.cc
// The `histograms_recorded_` guard ensures we only record once (only for headers, not trailers).
 void ConnectionImpl::recordHistogramsForStream(StreamImpl& stream) {
   if (record_http2_histograms_ && !stream.histograms_recorded_) {
-    uint64_t headers_size = stream.headers().byteSize();
-    uint64_t headers_count = stream.headers().size();
+    uint64_t headers_size = stream.headers().byteSize() + stream.discarded_host_header_size_;
+    uint64_t headers_count = stream.headers().size() + stream.discarded_host_header_count_;
     uint64_t headers_with_cookies_size = headers_size + stream.cookies_.size();
     uint64_t headers_with_cookies_count = headers_count + stream.cookie_count_;
     stats_.header_list_size_.recordValue(headers_with_cookies_size);

Source: Envoy Commit 0910997. The fix adds discarded_host_header_size_ and discarded_host_header_count_ to the accounted totals so dropped Host headers count against configured limits.

Detection Methods for CVE-2026-73550

Indicators of Compromise

  • HTTP/2 requests where both :authority and Host are present, with Host referenced via HPACK indexed representation across many streams.
  • Sudden growth in Envoy resident memory correlated with a small number of client IPs opening HTTP/2 connections.
  • Envoy processes terminated by the Linux OOM killer, visible in dmesg or journalctl -k output.

Detection Strategies

  • Inspect Envoy access logs and connection statistics for high stream counts from single peers with abnormally large aggregated header bytes.
  • Monitor the http2.header_list_size histogram and downstream_rq_* counters for anomalies against baselines.
  • Correlate proxy restarts with upstream 503/504 spikes and container OOM events in orchestrator logs.

Monitoring Recommendations

  • Track Envoy container memory ceilings and OOMKilled events in Kubernetes via kubectl get events and pod restart counts.
  • Alert on repeated HTTP/2 GOAWAY or connection resets from the same source addresses.
  • Ingest Envoy admin /stats metrics into a monitoring platform and alert on rapid growth in header map size histograms.

How to Mitigate CVE-2026-73550

Immediate Actions Required

  • Upgrade Envoy to 1.36.10, 1.37.6, 1.38.4, or 1.39.1 on all data-plane and ingress instances.
  • Inventory service meshes and API gateways built on Envoy, including Istio, Contour, and Gloo, and apply vendor-provided patched builds.
  • Enforce per-connection HTTP/2 stream limits and reduce max_request_headers_kb toward the minimum required for your workloads.

Patch Information

The fix is tracked in Envoy Security Advisory GHSA-qgf6-qvhw-4hvh and released in v1.36.10, v1.37.6, v1.38.4, and v1.39.1. The patched code accounts for discarded Host header bytes and counts in HTTP/2 request header map size and count limits.

Workarounds

  • Place rate limiting in front of Envoy to cap HTTP/2 streams per client until patches are deployed.
  • Lower max_concurrent_streams and header size limits in the HTTP/2 protocol options to reduce amplification headroom.
  • After upgrading, leave the runtime guard envoy.reloadable_features.http2_track_size_of_dropped_host_header at its default of true; only revert to false if a regression is observed.
bash
# Verify Envoy version is patched
envoy --version

# Example HTTP/2 hardening in an Envoy listener (YAML snippet)
# typed_per_filter_config / http2_protocol_options tightening:
#   max_concurrent_streams: 100
#   initial_stream_window_size: 65536
#   max_request_headers_kb: 32

# Kubernetes: check for OOMKilled Envoy pods
kubectl get pods -A -o json | \
  jq '.items[] | select(.status.containerStatuses[]?.lastState.terminated.reason=="OOMKilled") | .metadata.name'

Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.

Default Legacy - Prefooter | Experience the World’s Most Advanced Cybersecurity Platform

Experience the Most Advanced Cybersecurity Platform

See how the world’s most intelligent, autonomous cybersecurity platform can protect your organization today and into the future.