W3C Baggage propagator uses form encoding instead of percent encoding

Open Beginner friendly
#5,566 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
python
Domain
api

Research direction

Start at the W3CBaggagePropagator entry point in the affected opentelemetry-api package and reproduce the extract and inject examples from this issue. Check the quote_plus/unquote_plus handling against the W3C Baggage grammar, then verify that literal '+' is preserved and spaces are represented as %20 in both directions.

Written by the indexing model from the issue text.

Description

bug
Describe your environment

Labels: bug, api, propagator, spec-compliance
Affected packages: opentelemetry-api
Found on: main @ 0a5d76b6
Environment: CPython 3.12

What happened?

W3CBaggagePropagator encodes and decodes baggage with quote_plus / unquote_plus, which is application/x-www-form-urlencoded. That form maps a space to + and decodes + back to a space. The W3C Baggage grammar defines baggage-octet as %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E, so + (%x2B) is an ordinary literal that must be preserved, and SP (%x20) is excluded and must be percent-encoded as %20.

Both directions are wrong, and neither raises: values are silently corrupted as they cross a service boundary.

Steps to Reproduce
from opentelemetry.baggage import get_all, set_baggage
from opentelemetry.baggage.propagation import W3CBaggagePropagator

p = W3CBaggagePropagator()

# extract: a compliant peer sends a literal "+"
print(dict(get_all(p.extract({"baggage": "key=a+b"}))))

# inject: a value containing a space
carrier = {}
p.inject(carrier, context=set_baggage("key", "a b"))
print(carrier)
Expected Result

extract of key=a+b yields {'key': 'a+b'}, and inject of a value containing a space emits key=a%20b.

Actual Result
{'key': 'a b'}          # extract corrupted "a+b" into "a b"
{'baggage': 'key=a+b'}  # inject emitted "+" where %20 is required

# further extract cases
wire 'key=+'      -> ''       (value destroyed entirely)
wire 'key=c++'    -> 'c'      (trailing strip() eats the rest)
wire 'key=a+b+c'  -> 'a b c'
Additional context

Silent data corruption at service boundaries in any polyglot deployment. Baggage commonly carries tenant identifiers, routing keys and feature flags, so a corrupted value can misroute a request rather than merely degrade telemetry. OpenTelemetry implementations in other languages percent-encode, so the corruption only appears when Python talks to a non-Python peer - which makes it hard to spot in a single-language test environment.

Would you like to implement a fix?

Yes

Tip

React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Dominant language
Python
Stars
2.6k
Forks
1k
Avg merge
5d 29m
Merged PRs (30d)
17

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from open-telemetry/opentelemetry-python

All issues in open-telemetry/opentelemetry-python

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.