Skip to content

fix: cap W3C Baggage extract at 8192 bytes and 180 entries - #993

Open
tonghuaroot wants to merge 1 commit into
open-telemetry:mainfrom
tonghuaroot:fix-baggage-extract-cap
Open

fix: cap W3C Baggage extract at 8192 bytes and 180 entries#993
tonghuaroot wants to merge 1 commit into
open-telemetry:mainfrom
tonghuaroot:fix-baggage-extract-cap

Conversation

@tonghuaroot

Copy link
Copy Markdown

Fixes #992.

otel_propagator_baggage:extract/5 currently walks the inbound baggage HTTP header through string:lexemes(String, [$,]) and lists:foldl/3 without any byte or entry-count cap. The W3C Baggage specification recommends 8192 bytes and 180 entries, and the other OpenTelemetry SDKs (Java SDK 1.62.0 W3CBaggagePropagator, Go propagation/baggage.go maxBytes/maxMembers, .NET BaggagePropagator.cs MaxBaggageLength/MaxBaggageItems, C++ baggage.h FromHeader kMaxSize/kMaxKeyValuePairs) all enforce equivalent caps. This brings the Erlang implementation in line.

The maintainers reviewed this off-list as GHSA-64w2-whjg-q7q7 and asked for it to land as a regular issue/PR (https://github.com/open-telemetry/opentelemetry-erlang/security/advisories/GHSA-64w2-whjg-q7q7).

Changes

  • apps/opentelemetry_api/src/otel_propagator_baggage.erl
    • Add MAX_BAGGAGE_BYTES = 8192 and MAX_BAGGAGE_ENTRIES = 180 defines.
    • extract/5 rejects headers larger than MAX_BAGGAGE_BYTES before string:lexemes/2 walks them.
    • Decode loop is rewritten as decode_pairs/3, which stops after MAX_BAGGAGE_ENTRIES regardless of how many pairs lexemes produced.
    • decode_pairs/3 matches string:split(Pair, "=") via case and skips malformed pairs instead of crashing on [Key, Value] = ... like the previous code did.
  • apps/opentelemetry_api/test/otel_propagator_baggage_SUITE.erl
    • New CT suite with cases for simple extract, byte cap, entry cap, headers within both caps, malformed-pair skipping, and missing header.

Verification

$ rebar3 ct --suite=apps/opentelemetry_api/test/otel_baggage_SUITE,apps/opentelemetry_api/test/otel_propagators_SUITE,apps/opentelemetry_api/test/otel_propagator_baggage_SUITE
%%% otel_baggage_SUITE: ..
%%% otel_propagators_SUITE: .....
%%% otel_propagator_baggage_SUITE: ......
All 13 tests passed.

$ rebar3 xref
===> Running cross reference analysis...
(clean)

Run on erlang:27-alpine (Erlang/OTP 27) with rebar3 3.24.0, against the worktree at this PR's head.

`otel_propagator_baggage:extract/5` walked an attacker-controlled
`baggage` HTTP header through `string:lexemes/2` and `lists:foldl/3`
without any size or entry-count cap. The W3C Baggage specification
recommends 8192 bytes and 180 entries; the other OpenTelemetry SDKs
(Java SDK 1.62.0 `W3CBaggagePropagator`, Go `propagation/baggage.go`,
.NET `BaggagePropagator.cs`, C++ `baggage.h`) all enforce equivalent
caps. The Erlang implementation enforced neither, so a single inbound
request with an oversized `baggage` header could pin a BEAM scheduler
and inflate per-process heap.

This change:

- Rejects headers larger than `MAX_BAGGAGE_BYTES` (8192) before
  `string:lexemes/2` walks them.
- Stops decoding after `MAX_BAGGAGE_ENTRIES` (180) regardless of how
  many pairs `lexemes` produced.
- Replaces the non-exhaustive `[Key, Value] = string:split(Pair, "=")`
  match with a `case` that skips malformed pairs instead of crashing.

Adds `otel_propagator_baggage_SUITE` covering simple extract, the byte
and entry caps, headers within both caps, malformed-pair skipping, and
the missing-header path.

Signed-off-by: tonghuaroot <tonghuaroot@gmail.com>
@tonghuaroot
tonghuaroot requested a review from a team as a code owner May 27, 2026 01:34
terry-xiaoyu added a commit to emqx/opentelemetry-erlang that referenced this pull request Jul 8, 2026
otel_propagator_baggage:extract/5 previously walked the inbound
`baggage` header via string:lexemes/2 and lists:foldl/3 with no byte
or entry-count cap, and crashed on malformed pairs through
`[Key, Value] = string:split(Pair, "=")`.

Add ?MAX_BAGGAGE_BYTES (8192) and ?MAX_BAGGAGE_ENTRIES (180) limits
recommended by the W3C Baggage specification, dropping oversized
headers and stopping the decode loop after the entry cap. Malformed
pairs are now skipped instead of crashing. This brings the Erlang
implementation in line with the other OpenTelemetry SDKs and addresses
GHSA-64w2-whjg-q7q7.

Adds a CT suite covering simple extract, byte cap, entry cap,
within-cap, malformed-pair skipping, and missing header.

Backports open-telemetry#993.
terry-xiaoyu added a commit to emqx/opentelemetry-erlang that referenced this pull request Jul 9, 2026
otel_propagator_baggage:extract/5 previously walked the inbound
`baggage` header via string:lexemes/2 and lists:foldl/3 with no byte
or entry-count cap, and crashed on malformed pairs through
`[Key, Value] = string:split(Pair, "=")`.

Add ?MAX_BAGGAGE_BYTES (8192) and ?MAX_BAGGAGE_ENTRIES (180) limits
recommended by the W3C Baggage specification, dropping oversized
headers and stopping the decode loop after the entry cap. Malformed
pairs are now skipped instead of crashing. This brings the Erlang
implementation in line with the other OpenTelemetry SDKs and addresses
GHSA-64w2-whjg-q7q7.

Adds a CT suite covering simple extract, byte cap, entry cap,
within-cap, malformed-pair skipping, and missing header.

Backports open-telemetry#993.
terry-xiaoyu added a commit to emqx/opentelemetry-erlang that referenced this pull request Jul 9, 2026
otel_propagator_baggage:extract/5 previously walked the inbound
`baggage` header via string:lexemes/2 and lists:foldl/3 with no byte
or entry-count cap, and crashed on malformed pairs through
`[Key, Value] = string:split(Pair, "=")`.

Add ?MAX_BAGGAGE_BYTES (8192) and ?MAX_BAGGAGE_ENTRIES (180) limits
recommended by the W3C Baggage specification, dropping oversized
headers and stopping the decode loop after the entry cap. Malformed
pairs are now skipped instead of crashing. This brings the Erlang
implementation in line with the other OpenTelemetry SDKs and addresses
GHSA-64w2-whjg-q7q7.

Adds a CT suite covering simple extract, byte cap, entry cap,
within-cap, malformed-pair skipping, and missing header.

Backports open-telemetry#993.
terry-xiaoyu added a commit to emqx/opentelemetry-erlang that referenced this pull request Jul 9, 2026
otel_propagator_baggage:extract/5 previously walked the inbound
`baggage` header via string:lexemes/2 and lists:foldl/3 with no byte
or entry-count cap, and crashed on malformed pairs through
`[Key, Value] = string:split(Pair, "=")`.

Add ?MAX_BAGGAGE_BYTES (8192) and ?MAX_BAGGAGE_ENTRIES (180) limits
recommended by the W3C Baggage specification, dropping oversized
headers and stopping the decode loop after the entry cap. Malformed
pairs are now skipped instead of crashing. This brings the Erlang
implementation in line with the other OpenTelemetry SDKs and addresses
GHSA-64w2-whjg-q7q7.

Adds a CT suite covering simple extract, byte cap, entry cap,
within-cap, malformed-pair skipping, and missing header.

Backports open-telemetry#993.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

W3C Baggage extract has no size or entry-count cap

1 participant