TraceContextTextMapPropagator injects invalid traceparent header (all zeros) when SpanContext is invalid
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 82/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- python
- Domain
- observability
Research direction
Start in opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py and reproduce the invalid SpanContext example from the issue. Check the propagator and the related B3MultiFormat, B3SingleFormat, and JaegerPropagator guards mentioned in the report. Done means invalid contexts inject neither traceparent nor tracestate, while valid contexts continue to propagate normally.
Written by the indexing model from the issue text.
Description
Describe your environment
- OS: Linux / macOS
- Python version: 3.10+
- SDK version: main (1.37.0.dev0)
- API version: main (1.37.0.dev0)
What happened?
In TraceContextTextMapPropagator.inject, the propagator guards against injecting invalid contexts by checking:
if span_context == trace.INVALID_SPAN_CONTEXT:
return
Because SpanContext is a tuple consisting of (trace_id, span_id, is_remote, trace_flags, trace_state, is_valid) and INVALID_SPAN_CONTEXT is statically defined with is_remote=False, trace_flags=0, and trace_state=DEFAULT_TRACE_STATE, any invalid SpanContext (i.e. where is_valid is False) that has:
is_remote=True- non-zero
trace_flags(such asTraceFlags.SAMPLED) - or non-empty
trace_state
evaluates span_context == trace.INVALID_SPAN_CONTEXT to False.
As a consequence, the guard fails to trigger and inject() proceeds to format and inject an illegal traceparent header containing all zeroes into outbound network requests:
traceparent: 00-00000000000000000000000000000000-0000000000000000-00
This violates:
- W3C Trace Context Specification: Section 3.2.2.3 forbids all-zero
trace-idandparent-id, and Section 4.2 states an implementation MUST NOT forward an invalidtraceparent. - OpenTelemetry Specification (TraceContext Propagator): "If the SpanContext is invalid, the propagator MUST NOT inject anything into the carrier."
Strict reverse proxies, service meshes (Envoy), API gateways, and downstream microservices may reject HTTP requests with invalid W3C headers with 400 Bad Request or drop the context.
Steps to Reproduce
from opentelemetry import trace
from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator
from opentelemetry.trace.span import NonRecordingSpan, SpanContext
propagator = TraceContextTextMapPropagator()
# An invalid remote span context (e.g. from an upstream call)
invalid_span_context = SpanContext(trace_id=0, span_id=0, is_remote=True)
print("is_valid:", invalid_span_context.is_valid) # False
print("== INVALID_SPAN_CONTEXT:", invalid_span_context == trace.INVALID_SPAN_CONTEXT) # False
carrier = {}
ctx = trace.set_span_in_context(NonRecordingSpan(invalid_span_context))
propagator.inject(carrier, ctx)
print("Injected carrier:", carrier)
Expected Result
No traceparent or tracestate header should be injected when span_context.is_valid is False:
Injected carrier: {}
Actual Result
An illegal all-zero traceparent header is injected onto the carrier:
Injected carrier: {'traceparent': '00-00000000000000000000000000000000-0000000000000000-00'}
Additional context
The fix is straightforward. Replace the equality comparison against trace.INVALID_SPAN_CONTEXT with a check on the is_valid property:
diff --git a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py
--- a/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py
+++ b/opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py
@@ -81,7 +81,7 @@ class TraceContextTextMapPropagator(textmap.TextMapPropagator):
"""
span = trace.get_current_span(context)
span_context = span.get_span_context()
- if span_context == trace.INVALID_SPAN_CONTEXT:
+ if not span_context.is_valid:
return
traceparent_string = f"00-{format_trace_id(span_context.trace_id)}-{format_span_id(span_context.span_id)}-{span_context.trace_flags:02x}"
setter.set(carrier, self._TRACEPARENT_HEADER_NAME, traceparent_string)
(Note: The same span_context == trace.INVALID_SPAN_CONTEXT pattern is also present in B3MultiFormat, B3SingleFormat, and JaegerPropagator.)
- Dominant language
- Python
- Stars
- 2.6k
- Forks
- 1k
- Avg merge
- 3d 14h
- Merged PRs (30d)
- 21
Getting set up
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from open-telemetry/opentelemetry-python
-
Difficulty 1/5 Under an hour Newbie friendliness 70/100
open-telemetry/opentelemetry-python#5700 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
open-telemetry/opentelemetry-python#5664 · 4 comments ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
open-telemetry/opentelemetry-python#5661 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
open-telemetry/opentelemetry-python#5638 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
open-telemetry/opentelemetry-python#5624 ·
Maintainers usually reply within 1 day
All issues in open-telemetry/opentelemetry-python
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
bug
Difficulty 1/5 Under an hour Newbie friendliness 88/100
qgis/QGIS-Plugins-Website#459 ·
-
bug severity:medium
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 2 days
-
bot-found bug priority: P3
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
madenvel/KalinkaPlayer#179 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
ls1intum/edutelligence#1098 ·
Maintainers usually reply within 1 day