CVE-2026-50274: dd-trace-go Unbounded W3C Baggage Header Parsing DoS
The Datadog Go tracing library parsed incoming W3C baggage HTTP headers with no item-count or size limits, letting any unauthenticated attacker crash an instrumented service by sending a single oversi
The problem
dd-trace-go's W3C baggage propagator applied `DD_TRACE_BAGGAGE_MAX_ITEMS` (default 64) and `DD_TRACE_BAGGAGE_MAX_BYTES` (default 8192) limits only on the inject (outbound) path. The extract (inbound) path had no such guards.
Every incoming HTTP request is parsed on the hot path. An attacker who sends a baggage header with hundreds or thousands of comma-separated key=value pairs forces the tracer to allocate a hash-map entry for every pair, on every request, with no upper bound. This causes unbounded CPU and memory consumption, enabling remote DoS against any internet-facing Go service instrumented with an affected tracer version.
Proof of concept
A working proof-of-concept for CVE-2026-50274 in github.com/DataDog/dd-trace-go, with the exact payload below.
GET / HTTP/1.1
Host: victim.example.com
baggage: k1=v1,k2=v2,k3=v3,k4=v4,k5=v5,k6=v6,k7=v7,k8=v8,k9=v9,k10=v10,k11=v11,k12=v12,k13=v13,k14=v14,k15=v15,k16=v16,k17=v17,k18=v18,k19=v19,k20=v20,k21=v21,k22=v22,k23=v23,k24=v24,k25=v25,k26=v26,k27=v27,k28=v28,k29=v29,k30=v30,k31=v31,k32=v32,k33=v33,k34=v34,k35=v35,k36=v36,k37=v37,k38=v38,k39=v39,k40=v40,k41=v41,k42=v42,k43=v43,k44=v44,k45=v45,k46=v46,k47=v47,k48=v48,k49=v49,k50=v50,k51=v51,k52=v52,k53=v53,k54=v54,k55=v55,k56=v56,k57=v57,k58=v58,k59=v59,k60=v60,k61=v61,k62=v62,k63=v63,k64=v64,k65=v65,...,kN=vNThe root cause is an asymmetric limit enforcement (CWE-400, CWE-770): the same max-items and max-bytes constants that capped baggage on the way out were never checked on the way in. The tracer iterated the full comma-separated member list and allocated a map entry per pair regardless of count or total size.
PR #4720 (`fix(tracer): enforce baggage item and byte limits on extraction`) adds early-exit checks on the extract path that mirror the existing inject-side guards, stopping allocation once either the item count reaches `DD_TRACE_BAGGAGE_MAX_ITEMS` (64) or the running byte total reaches `DD_TRACE_BAGGAGE_MAX_BYTES` (8192).
The same class of bug was independently reported and fixed across the OpenTelemetry ecosystem (Go, Java, .NET, JS, Rust) at roughly the same time.
The fix
Upgrade to dd-trace-go v2.8.1 or later. If an immediate upgrade is not possible, remove `baggage` from `DD_TRACE_PROPAGATION_STYLE` (or `DD_TRACE_PROPAGATION_STYLE_EXTRACT`) to disable baggage extraction entirely. As an additional layer, cap inbound header sizes at a proxy or web server: Nginx `large_client_header_buffers`, Apache `LimitRequestFieldSize`, or Envoy `max_request_headers_kb`.
Reported by tonghuaroot.
Related research
- highCVE-2026-54448CVE-2026-54448: Trivy Helm Chart Tar Bomb OOM via Unbounded io.ReadAll
- high · 7.5CVE-2026-50285CVE-2026-50285: Pomerium Pre-Auth Denial of Service via HPKE Decompression Bomb
- highEch0: Accept-Language `_` Separator Bypass Causes ~70x CPU Amplification DoS
- high · 7.5CVE-2026-50125CVE-2026-50125: MKP Unbounded Pod Log Read Memory Exhaustion