GO.OPENTELEMETRY.IO/OTEL/BAGGAGE · CVE-2026-128086 · Package
FIX → 1.47.0
Parsing a valid, densely populated W3C baggage header in OpenTelemetry Go eagerly builds a property object for each entry, causing roughly 95 times the input size in allocation traffic per parse. An attacker sending large baggage headers can drive extra allocation and garbage collection pressure, but the sources do not show reliable out-of-memory crashes or full denial of service.
first public Oct 28, 2026 · 2 sources
Check it with your coding agent
It reads this page and tells you if your code or app is affected.
A service is exposed when it enables W3C Baggage propagation and extracts inbound headers from attacker-controlled requests, especially when extraction runs before authentication or on a public route. Services that do not enable baggage propagation, or that authenticate before the OpenTelemetry handler runs, are not on this path. The sources describe this as a source-level check of a normal integration, not a tested HTTP benchmark.
Not affected if auth-before-extraction, default-config, no-baggage-propagation
Who cares go, opentelemetry, otelhttp, public-api, self-hosted
go.opentelemetry.io/otel or go.opentelemetry.io/otel/baggage and go.opentelemetry.io/otel/propagation in go.mod; affected versions are >= 1.0.0-RC1 and < 1.47.0.OpenTelemetry Go eagerly materializes W3C baggage metadata into property objects during parsing. Slice growth, serialization, and copying into the internal representation cause bounded but disproportionate memory-allocation amplification for a valid, densely populated header. In v1.46.0 and v1.47.0-rc.1, the 8,192-byte raw-input limit is checked before member parsing; this is not unlimited allocation or a bypass of that limit.
A valid 8,191-byte value containing one member and 4,094 properties causes approximately 778 KB of cumulative allocation per parse. A corrected measurement with forced garbage collection before and after parsing retains approximately 164 KB per result while it remains live. These are different metrics: approximately 95 times the input in allocation traffic versus approximately 20 times in incremental live heap in the measured environment.
The relevant security configuration is a service that enables Baggage propagation and extracts attacker-controlled inbound context before authentication or on a public route. Concurrent or sustained requests can increase allocation and GC pressure. The evidence establishes allocation amplification, but does not establish reliable OOM, process termination, or complete denial of service.
This is a pre-existing, independent allocation-amplification path not addressed by GHSA-5wrp-cwcj-q835 / CVE-2026-41178. It predates that advisory; it is not described as having been introduced by its fix.
go.opentelemetry.io/otel.go.opentelemetry.io/otel/baggage.Parse and go.opentelemetry.io/otel/propagation.Baggage.Extract.Are you affected?
Ask from here. InfraStack checks the affected versions against your stack and answers in your inbox.
InfraStack checks the affected versions against your stack and answers in Slack, with the evidence and the fix.
InfraStack checks it against your stack and answers on your report, with the evidence and the fix.
propagation.Baggage or otelhttp.NewHandler to see whether baggage extraction is enabled.otelhttp.NewHandler wraps the authentication handler, so that extraction runs before authentication on inbound requests.Upgrade to 1.47.0
go.opentelemetry.io/otel and related modules: upgrade to 1.47.0otelhttpparseMember, property-slice growth and serialization, and conversion into internal/baggage.Item.4bf6150fa94e18bdf01c96ed78ee6d1c76f8e308, first included in v1.0.0-RC1; the stable release line starts at v1.0.0.>= 1.0.0-RC1, < 1.47.0.v1.47.0 (https://github.com/open-telemetry/opentelemetry-go/pull/9024), which validates and normalizes W3C property metadata in place during Parse and materializes Property structs lazily only when Member.Properties() is explicitly called.v1.0.0-RC1, v1.0.0, v1.46.0, and v1.47.0-rc.1; this is not a claim to have dynamically tested every intervening release. The v1.46.0 and v1.47.0-rc.1 parser source is identical to the inspected main commit 901e812ec023f45f791cd4d49cfbbef353ae21ae.Early releases have a 4,096-byte per-member limit. They reproduce the same mechanism with a 4,095-byte member containing 2,046 properties; the 8,191-byte single-member input is rejected there. The 8 KB example and its numerical allocation result must not be projected onto every historical version.
For the valid dense input, each short property becomes a Go Property, and the slice grows as parsing proceeds. The parser subsequently serializes the member and copies its properties into the internal representation. A two-byte wire fragment can therefore produce substantially more than two bytes of allocation work. Temporary parser objects and internal retained objects must not be added together and described as permanently retained memory.
In the currently measured parser, the raw 8,192-byte limit and 64-member limit still apply. The number of accepted properties is consequently bounded by input length even though there is no separate property-count guard. Eager representation and copying are the defect described here; the absence of an arbitrary count cap is not, by itself, the defect.
The primary input is constructed as "k=v" + strings.Repeat(";a", 4094) (8,191 bytes); the equal-size value-only control is "k=" + strings.Repeat("v", 8189). Call baggage.Parse once for each measured result. To verify the property count separately, inspect bag.Members()[0].Properties() outside the measured interval; this accessor itself allocates. The primary example remains the valid 8,191-byte, 4,094-property input already supplied in this private report. Empty-property input discussed in the maintainer review is malformed and is supplementary parser-hardening evidence, not the standards-compliant primary example or the basis of the severity score.
The Go global propagator is initially a no-op. Installing the library alone does not expose this path. Baggage must be enabled explicitly or by applicable auto-configuration; standardized auto-configuration defaults do not establish an individual application's configuration.
An ordinary HTTP composition can place otelhttp.NewHandler outside the authentication handler. With propagation.Baggage{} enabled and the request not excluded by a filter, the checked otelhttp implementation calls h.propagators.Extract(r.Context(), propagation.HeaderCarrier(r.Header)) before next.ServeHTTP. Authentication inside next therefore runs after extraction, including for a request that is ultimately rejected with 401/403. Reversing the composition so authentication rejects before entering otelhttp prevents this unauthenticated extraction path. This is a source-level ordering check of a normal integration, not a claim about all services or an executed HTTP benchmark.
Source checked: otelhttp handler at ce138eb092f223e4e41e0420c58fc34910bc2b56, extraction at line 98 and downstream handler at line 185. A filter that bypasses instrumentation takes a separate path and is outside this stated composition.
Remote reachability requires all of the following: Baggage extraction is enabled; attacker-controlled input reaches it; the transport and proxy accept the relevant header size; and extraction runs before authentication or on a public route. Material service impact further depends on request rate, concurrency, request lifetime, GC behavior, and resource limits. Authentication is a mitigation only if it precedes extraction. A path that requires a properly authenticated triggering client must also be evaluated under the project's authenticated-client DoS exclusion.
This page as .md · .json · CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
GitHub Advisory Database, CC-BY 4.0 · NVD data is provided by NIST and is public domain. Posts quoted belong to their authors.