CVE-2026-50276 Overview
CVE-2026-50276 affects dd-trace-rb, Datadog's client library for Ruby. The vulnerability allows a remote unauthenticated attacker to trigger unbounded CPU and memory consumption by sending a crafted W3C baggage HTTP header. The extraction path fails to enforce DD_TRACE_BAGGAGE_MAX_ITEMS (default 64) and DD_TRACE_BAGGAGE_MAX_BYTES (default 8192), even though the limits are enforced during baggage injection. Any HTTP service using an affected tracer with baggage propagation enabled, which is the default configuration, can be forced into denial-of-service conditions. The issue is classified as [CWE-770: Allocation of Resources Without Limits or Throttling] and is fixed in version 2.32.0.
Critical Impact
A single unauthenticated HTTP request containing an oversized or many-entry baggage header can exhaust CPU and memory on any Ruby service running an affected dd-trace-rb version with default settings.
Affected Products
- Datadog dd-trace-rb versions prior to 2.32.0
- Ruby HTTP services with baggage propagation enabled (default)
- Applications using default DD_TRACE_BAGGAGE_MAX_ITEMS and DD_TRACE_BAGGAGE_MAX_BYTES configuration
Discovery Timeline
- 2026-09-14 - CVE-2026-50276 published to NVD
- 2026-09-14 - Last updated in NVD database
Technical Details for CVE-2026-50276
Vulnerability Analysis
The vulnerability resides in the W3C baggage header extraction logic in lib/datadog/tracing/distributed/baggage.rb. The parse_baggage_header method reads the incoming baggage HTTP header, splits it on commas, and allocates hash entries for each key-value pair. No upper bound is enforced on the header byte size or the number of parsed entries. An attacker controls the header contents entirely, so a single request can force the tracer to allocate arbitrarily large data structures. Ruby processes performing this parsing on every inbound request will consume CPU parsing the header and memory storing the resulting hash. Under sustained requests, workers exhaust available resources and stop serving legitimate traffic, producing a denial-of-service condition.
Root Cause
The root cause is missing input validation in the extraction path. Baggage injection correctly honored DD_TRACE_BAGGAGE_MAX_ITEMS and DD_TRACE_BAGGAGE_MAX_BYTES, but the corresponding extraction routine did not check either limit. This asymmetric enforcement maps directly to [CWE-770], allocation of resources without limits or throttling.
Attack Vector
Exploitation requires only network access to the target HTTP service. The attacker sends an HTTP request with a baggage header containing many comma-separated key-value pairs or a single very large value. No authentication, no user interaction, and no prior access is required. Because baggage propagation is enabled by default in most affected tracer configurations, most Ruby web services running dd-trace-rb prior to 2.32.0 are exposed at their public HTTP surface.
# Security patch in lib/datadog/tracing/distributed/baggage.rb
# Limit processing of large Baggage data (#5672)
# - Keys and values are URL-encoded
# - Returns an empty hash if the baggage header is malformed
#
+ # For entries with duplicate keys, only last one is preserved:
+ # https://www.w3.org/TR/2024/CR-baggage-20240530/#mutating-baggage
+ #
# @param baggage_header [String] The W3C Baggage header string to parse
# @return [Hash<String, String>] A hash of decoded baggage items
def parse_baggage_header(baggage_header)
+ if baggage_header.bytesize > DD_TRACE_BAGGAGE_MAX_BYTES
+ record_telemetry_metric('context_header.truncated', 1, {'header_style' => 'baggage', 'truncation_reason' => 'baggage_byte_count_exceeded'})
+
+ # We MUST NOT propagate partial entries, but we SHOULD try
+ # to parse as much of the baggage as possible:
+ # https://www.w3.org/TR/2024/CR-baggage-20240530/#limits
+
+ # We parse 1 byte over the limit to detect if the last entry
+ # is a partial entry (toss) or ends exactly at the limit (keep).
+ remove_last_entry = baggage_header.byteslice(DD_TRACE_BAGGAGE_MAX_BYTES, 1) != ','
+
+ # To ensure we don't have a trailing partial UTF-8 codepoint, we keep one extra byte
+ # and safely remove it with `#chop`.
+ baggage_header = baggage_header.byteslice(0, DD_TRACE_BAGGAGE_MAX_BYTES + 1)
+ baggage_header = baggage_header.chop
+ end
+
baggage = {}
- baggages = baggage_header.split(',')
Source: DataDog/dd-trace-rb commit 3619470. The patch enforces DD_TRACE_BAGGAGE_MAX_BYTES before parsing and emits a telemetry metric when truncation occurs.
Detection Methods for CVE-2026-50276
Indicators of Compromise
- Inbound HTTP requests containing baggage headers larger than 8192 bytes.
- Requests with baggage headers containing more than 64 comma-separated key-value pairs.
- Repeated requests from the same source presenting oversized baggage headers within short intervals.
- Ruby worker processes showing sudden CPU spikes or memory growth correlated with inbound traffic.
Detection Strategies
- Inspect HTTP request logs and reverse-proxy access logs for oversized baggage header values.
- Enable request header size logging at the load balancer or WAF and alert on anomalies.
- Correlate application performance metrics with inbound header sizes to identify parsing-driven resource exhaustion.
- Track the context_header.truncated telemetry metric emitted by dd-trace-rb 2.32.0 and later after upgrade.
Monitoring Recommendations
- Monitor per-process CPU and resident memory of Ruby workers for sudden growth without a matching request-count increase.
- Alert on HTTP 5xx error rate increases or worker restart events on services running dd-trace-rb.
- Capture packet or proxy samples of requests preceding worker exhaustion for post-incident analysis.
How to Mitigate CVE-2026-50276
Immediate Actions Required
- Upgrade dd-trace-rb to version 2.32.0 or later on all Ruby services.
- Inventory Ruby services and confirm the installed tracer version using bundle list | grep ddtrace or gem list datadog.
- If immediate upgrade is not possible, disable baggage propagation by removing baggage from the configured propagation styles.
- Restrict or drop inbound HTTP baggage headers at an upstream proxy, load balancer, or WAF.
Patch Information
The fix is included in dd-trace-rb version 2.32.0, released by Datadog. The patch enforces DD_TRACE_BAGGAGE_MAX_BYTES before parsing and truncates oversized headers at a safe boundary. See the GitHub Security Advisory GHSA-p5f6-rccc-jv98, the v2.32.0 release notes, and the pull request discussion for full details.
Workarounds
- Configure the tracer to exclude baggage from DD_TRACE_PROPAGATION_STYLE_EXTRACT until upgrade is complete.
- Enforce a maximum request header size at the edge (for example, large_client_header_buffers in NGINX) to reject oversized baggage headers.
- Deploy a WAF rule that rejects requests where the baggage header exceeds 8192 bytes or contains more than 64 comma-separated entries.
# Example NGINX configuration to cap header sizes at the edge
http {
client_header_buffer_size 1k;
large_client_header_buffers 4 8k;
}
# Example: disable baggage propagation via environment variable
export DD_TRACE_PROPAGATION_STYLE_EXTRACT="tracecontext,datadog"
export DD_TRACE_PROPAGATION_STYLE_INJECT="tracecontext,datadog"
Disclaimer: This content was generated using AI. While we strive for accuracy, please verify critical information with official sources.