Skip to content

W3C Baggage propagator uses form encoding instead of percent encoding #5566

Description

@dwin-gharibi

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions