opentelemetry-python

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

1post · 30d
Nov 30 posts
  1. DEV · · @cverports

    CVE-2026-116694: CVE-2026-116694: Unbounded Memory Allocation and Denial of Service in OpenTelemetry Python Jaeger Propagator CVE-2026-116694: Unbounded Memory Allocation and Denial of Service in OpenTelemetry Python Jaeger Propagator > Vulnerability ID: CVE-2026-116694 > CVSS Score: 6.3 > Published: 2026-10-27 CVE-2026-116694 (GHSA-f5m9-jfrj-jjj7) is an unbounded resource allocation vulnerability (CWE-770) in the optional Jaeger propagator component (opentelemetry-propagator-jaeger) of the OpenTelemetry Python SDK prior to version 1.45.0. When extracting distributed tracing context from inbound carriers, JaegerPropagator.extract() processes all headers prefixed with 'uberctx-' without enforcing limits on entry count, per-entry byte size, or aggregate byte size. In environments where transport-level header constraints are absent, relaxed, or bypassed (such as non-HTTP message brokers, RPC frameworks, or web servers with elevated buffer configurations), an unauthenticated remote attacker can supply high-volume or oversized baggage headers to trigger excessive URL unquoting, short-lived immutable dictionary allocations, and CPU starvation. TL;DR OpenTelemetry Python's opentelemetry-propagator-jaeger package prior to version 1.45.0 fails to enforce entry count or byte-length boundaries when parsing 'uberctx-' baggage headers. Remote attackers can send oversized or numerous baggage keys to exhaust CPU and memory resources, leading to denial of service. Version 1.45.0 resolves this by applying W3C Baggage limits (180 entries, 4,096 bytes per entry, and 8,192 bytes total) to both extraction and injection routines. --- ⚠️ Exploit Status: POC Technical Details - CVE / Advisory ID: CVE-2026-116694 / GHSA-f5m9-jfrj-jjj7 - Affected Package: opentelemetry-propagator-jaeger (< 1.45.0) - Weakness Class: CWE-770 (Allocation of Resources Without Limits or Throttling) - CVSS v4.0 Score: 6.3 Medium (CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N) - Attack Vector: Network via inbound 'uberctx-*' carrier headers/metadata - Security Impact: Denial of Service via CPU exhaustion and repeated heap allocations - Exploit Status: Unit test reproduction in official repository; no wild exploitation reported - Patched Version: 1.45.0 (Enforces 180 entries, 4,096B/entry, 8,192B total) Affected Systems - opentelemetry-propagator-jaeger (PyPI) - open-telemetry/opentelemetry-python - opentelemetry-propagator-jaeger: < 1.45.0 (Fixed in: 1.45.0) Code Analysis Commit: 65c4eeb opentelemetry-propagator-jaeger: enforce baggage limits on extract (#5556) diff --git a/.changelog/5556.fixed b/.changelog/5556.fixed new file mode 100644 index 00000000000..d8bb2ca6631 --- /dev/null +++ b/.changelog/5556.fixed @@ -0,0 +1 @@ +`opentelemetry-propagator-jaeger`: enforce baggage limits on both `uberctx-` extract and inject, borrowing the same limits (180 entries, 4096 bytes per entry, 8192 bytes total) the package's core `W3CBaggagePropagator` already uses, so neither an inbound carrier nor an in-process baggage map can produce unbounded work or headers. diff --git a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py index 04a3e8ff5e6..08c6e99de80 100644 --- a/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py +++ b/propagator/opentelemetry-propagator-jaeger/src/opentelemetry/propagators/jaeger/__init__.py @@ -2,6 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 import collections.abc +import itertools import urllib.parse from opentelemetry import baggage, trace @@ -26,6 +27,11 @@ class JaegerPropagator(TextMapPropagator): TRACE_ID_KEY = "uber-trace-id" BAGGAGE_PREFIX = "uberctx-" DEBUG_FLAG = 0x02 + # The Jaeger format defines no baggage limits, so the W3C Baggage spec + # limits are borrowed to bound an unbounded inbound carrier on extract. + MAX_BAGGAGE_ENTRIES = 180 + MAX_BAGGAGE_ENTRY_BYTES = 4096 + MAX_BAGGAGE_TOTAL_BYTES = 8192 def extract( self, @@ -90,9 +96,7 @@ def inject( baggage_entries = baggage.get_all(context=context) if not baggage_entries: return - for key, value in baggage_entries.items(): - baggage_key = self.BAGGAGE_PREFIX + key - setter.set(carrier, baggage_key, urllib.parse.quote(str(value))) + self._inject_baggage(setter, carrier, baggage_entries) @property def fields(self) -> set[str]: @@ -104,18 +108,61 @@ def _extract_baggage( carrier: CarrierT, context: Context, ) -> Context: - baggage_keys = [key for key in getter.keys(carrier) if key.startswith(self.BAGGAGE_PREFIX)] - for key in baggage_keys: + # The limit bounds the candidates inspected, not the entries kept, so a + # carrier full of oversized ones cannot force unbounded work. + candidates = itertools.islice( + (key for key in getter.keys(carrier) if key.startswith(self.BAGGAGE_PREFIX)), + self.MAX_BAGGAGE_ENTRIES, + ) + pairs = [] + for key in candidates: value = _extract_first_element(getter.get(carrier, key)) - if value is None: - continue + if value is not None: + pairs.append((key.replace(self.BAGGAGE_PREFIX, ""), value)) + + for baggage_key, value in _limit_baggage_bytes( + pairs, self.MAX_BAGGAGE_ENTRY_BYTES, self.MAX_BAGGAGE_TOTAL_BYTES + ): context = baggage.set_baggage( - key.replace(self.BAGGAGE_PREFIX, ""), + baggage_key, urllib.parse.unquote(value).strip(), context=context, ) return context + def _inject_baggage( + self, + setter: Setter[CarrierT], + carrier: CarrierT, + baggage_entries: collections.abc.Mapping[str, object], + ) -> None: + candidates = itertools.islice(baggage_entries.items(), self.MAX_BAGGAGE_ENTRIES) + pairs = [(key, urllib.parse.quote(str(value))) for key, value in candidates] + + for key, encoded_value in _limit_baggage_bytes( + pairs, self.MAX_BAGGAGE_ENTRY_BYTES, self.MAX_BAGGAGE_TOTAL_BYTES + ): + setter.set(carrier, self.BAGGAGE_PREFIX + key, encoded_value) + + +def _limit_baggage_bytes( + pairs: collections.abc.Iterable[tuple[str, str]], + max_entry_bytes: int, + max_total_bytes: int, +) -> collections.abc.Iterator[tuple[str, str]]: + total_bytes = 0 + accepted = 0 + for key, value in pairs: + entry_bytes = len(key.encode()) + len(value.encode()) + 1 + if entry_bytes > max_entry_bytes: + continue + separator_bytes = 1 if accepted > 0 else 0 + if total_bytes + separator_bytes + entry_bytes > max_total_bytes: + continue + yield key, value + total_bytes += separator_bytes + entry_bytes + accepted += 1 + def _format_uber_trace_id(trace_id, span_id, parent_span_id, flags): return f"{format_trace_id(trace_id)}:{format_span_id(span_id)}:{format_span_id(parent_span_id)}:{flags:02x}" Mitigation Strategies - Upgrade opentelemetry-propagator-jaeger to version 1.45.0 or later to enforce W3C Baggage size and entry count limits. - Migrate from legacy Jaeger context propagation (JaegerPropagator) to the standardized W3C Trace Context and W3C Baggage propagators (W3CBaggagePropagator). - Enforce strict HTTP header count and byte-length boundaries at the reverse proxy (Nginx, Envoy) and WSGI/ASGI server (Gunicorn, Uvicorn) layers. - Sanitize and bound carrier dictionaries in custom TextMapGetter implementations used for non-HTTP message queues (Kafka, RabbitMQ, Celery) or RPC frameworks. Remediation Steps: 1. Audit application dependencies and deployment manifests (requirements.txt, pyproject.toml, Pipfile) to identify installations of opentelemetry-propagator-jaeger prior to 1.45.0. 2. Check application initialization code and environment variables (such as OTEL_PROPAGATORS) to determine whether 'jaeger' propagation is actively enabled. 3. Update the package using pip: pip install --upgrade 'opentelemetry-propagator-jaeger>=1.45.0'. 4. If upgrading immediately is not feasible, verify that Gunicorn limit_request_fields (default 100) and limit_request_field_size (default 8190) or equivalent reverse proxy header buffer limits have not been raised or disabled. 5. For non-HTTP consumers that cannot be immediately patched, wrap the custom TextMapGetter to yield at most 180 'uberctx-' keys and reject values larger than 4,096 bytes. References - GitHub Security Advisory: GHSA-f5m9-jfrj-jjj7 - GitHub Pull Request #5556: Enforce baggage limits on extract - Fix Commit 65c4eeb87cd3815dc795d3b5485e9ea0d5affcc7 - OpenTelemetry Python Release v1.45.0 - CVE.org Record: CVE-2026-116694 - OpenTelemetry Python Repository --- Read the full report for CVE-2026-116694 on our website for more details including interactive diagrams and full exploit analysis.

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

31
PackageVersionDownloads · 30dTrend · 30d
———
———
———
———
———
v1.45.1
≥446.4M
———
v0.66b1
≥29.7K
v0.66b1
≥37.1M
v0.66b1
≥3.7K
v1.45.1
≥45.8M
v0.66b1
≥43.4M
v0.66b1
≥84K
v0.66b1
≥53K
v0.66b1
≥845
v1.45.1
≥169.3M
v1.45.1
≥85M
v1.45.1
≥151.5M
v0.66b1
≥11.7M
v1.45.1
≥24.4K
v1.45.1
≥221K
v1.45.1
≥26.4K
v0.66b1
≥1.2K
v0.66b1
≥20.9K
v1.45.1
≥2.8M
v1.45.1
≥2M
v1.45.1
≥183.9M
v0.66b1
≥84K
———
v1.45.1
≥221.9M
v0.66b1
≥226.2M

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
open-telemetry/opentelemetry-python mentions in the last 30 days