Every CVE Search/ Get API key

CVE-2026-114603

OpenTelemetry Python: Unbounded tracestate parsing in opentelemetry-api

5.3 MediumFix available

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
None
Availability
Low

Exploit likelihood

0.49%Unchanged since Oct 23, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.3

OpenTelemetry Python: Unbounded tracestate parsing in opentelemetry-api

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
CVE-2026-114603
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weakness
CWE-400, CWE-1333
Updated
2026-11-02
EUVDEUVD-2026-108216 5.3

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
EUVD-2026-108216
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Updated
2026-11-02
GitHub AdvisoriesGHSA-xcq7-p3pf-p88h 5.3

OpenTelemetry Python: Unbounded tracestate parsing in opentelemetry-api

Summary

TraceState.from_header splits the inbound W3C tracestate header with a regular expression that starts with an unbounded optional-whitespace run, and no length limit is applied first. A run of spaces or tabs that is not followed by a comma costs O(N²) CPU. A single unauthenticated request with a ~100 KB tracestate keeps the handling worker busy for ~6 s (spaces) to ~12 s (tabs); under an asyncio server it blocks every other connection for that time.

Affected component / version

  • Package: opentelemetry-api (pip) — opentelemetry/trace/span.py (TraceState.from_header), reached from opentelemetry/trace/propagation/tracecontext.py (TraceContextTextMapPropagator.extract).
  • Confirmed in main (5e8083e8) and in the v1.44.0 and v1.45.0 tags; the same pattern is present back to v1.0.0 (introduced by #1599, March 2021). Not exhaustively verified against every release in between.
  • Reachable with the default propagators (OTEL_PROPAGATORS defaults to tracecontext,baggage) from any server instrumentation that calls propagate.extract(), for example opentelemetry-instrumentation-asgi.

Details

  1. The header reaches the parser without any length check:
# opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py:57
tracestate_headers = getter.get(carrier, self._TRACESTATE_HEADER_NAME)  # <-- attacker-controlled request header(s), any size
if tracestate_headers is None:
    tracestate = None
else:
    tracestate = TraceState.from_header(tracestate_headers)             # <-- no length check before parsing (line 61)
  1. The split pattern and the parser:
# opentelemetry-api/src/opentelemetry/trace/span.py:45
_TRACECONTEXT_MAXIMUM_TRACESTATE_KEYS = 32            # <-- only enforced later, in TraceState.__init__, after the split
_delimiter_pattern = re.compile(r"[ \t]*,[ \t]*")      # <-- (line 46) starts with an unbounded [ \t]*

# span.py:382
@classmethod
def from_header(cls, header_list: list[str]) -> TraceState:
    pairs = {}  # type: dict[str, str]
    for header in header_list:
        members: list[str] = re.split(_delimiter_pattern, header)   # <-- (line 400) VULNERABLE: O(N^2) on "a=b" + " " * N + "x"
        for member in members:
            if not member:
                continue
            match = _member_pattern.fullmatch(member)
            if not match:
                _logger.warning(                                    # <-- also logs the entire malformed member (up to the whole header)
                    "Member doesn't match the w3c identifiers format %s",
                    member,
                )
                return cls()
            ...

re.split tries the pattern at every offset. At each offset inside a whitespace run, [ \t]* consumes the rest of the run, finds no ,, backtracks and fails, then the engine moves one character forward and repeats. N characters × up to N steps each = O(N²). The 32-member limit never gets a chance to run because split has to finish first.

  1. The sibling propagator already has the missing guard:
# baggage/propagation/__init__.py:68
_MAX_HEADER_LENGTH = 8192
...
if len(header.encode()) > self._MAX_HEADER_LENGTH:   # <-- (line 93) rejected before any regex runs; tracestate has no equivalent
    _logger.warning(...)
    return context

A 16 KiB header costs ≈ 0.25 s and an 8 KiB header ≈ 0.07 s. Measured cost of extract() on one core (valid traceparent, tracestate: "a=b" + N spaces + "x"): the time quadruples each time N doubles (see the proof of concept). Roughly 0.06 s at 10,000 characters, 1 s at 40,000, 4 s at 80,000, 9 s at 100,000 (tabs are about 1.6× slower).

Whether a server lets such a header through (header-size limits, tested): gunicorn rejects ≥ 8190 bytes (response code 431); uvicorn --http h11 rejects above 16 KiB (400); waitress accepts up to 256 KiB (200 KB accepted, 300 KB rejected); uvicorn --http httptools — the default parser with…

Record
GHSA-xcq7-p3pf-p88h
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weakness
CWE-400, CWE-1333
Updated
2026-11-02
NVD 5.3

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
CVE-2026-114603
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weakness
CWE-400, CWE-1333
Updated
2026-11-02
OSV 5.3

OpenTelemetry Python: Unbounded tracestate parsing in opentelemetry-api

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
CVE-2026-114603
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weakness
CWE-1333, CWE-400
Updated
2026-11-04
OSVDEBIAN-CVE-2026-114603 5.3

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
DEBIAN-CVE-2026-114603
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Updated
2026-11-02
OSVGHSA-xcq7-p3pf-p88h 5.3

OpenTelemetry Python: Unbounded tracestate parsing in opentelemetry-api

Summary

TraceState.from_header splits the inbound W3C tracestate header with a regular expression that starts with an unbounded optional-whitespace run, and no length limit is applied first. A run of spaces or tabs that is not followed by a comma costs O(N²) CPU. A single unauthenticated request with a ~100 KB tracestate keeps the handling worker busy for ~6 s (spaces) to ~12 s (tabs); under an asyncio server it blocks every other connection for that time.

Affected component / version

  • Package: opentelemetry-api (pip) — opentelemetry/trace/span.py (TraceState.from_header), reached from opentelemetry/trace/propagation/tracecontext.py (TraceContextTextMapPropagator.extract).
  • Confirmed in main (5e8083e8) and in the v1.44.0 and v1.45.0 tags; the same pattern is present back to v1.0.0 (introduced by #1599, March 2021). Not exhaustively verified against every release in between.
  • Reachable with the default propagators (OTEL_PROPAGATORS defaults to tracecontext,baggage) from any server instrumentation that calls propagate.extract(), for example opentelemetry-instrumentation-asgi.

Details

  1. The header reaches the parser without any length check:
# opentelemetry-api/src/opentelemetry/trace/propagation/tracecontext.py:57
tracestate_headers = getter.get(carrier, self._TRACESTATE_HEADER_NAME)  # <-- attacker-controlled request header(s), any size
if tracestate_headers is None:
    tracestate = None
else:
    tracestate = TraceState.from_header(tracestate_headers)             # <-- no length check before parsing (line 61)
  1. The split pattern and the parser:
# opentelemetry-api/src/opentelemetry/trace/span.py:45
_TRACECONTEXT_MAXIMUM_TRACESTATE_KEYS = 32            # <-- only enforced later, in TraceState.__init__, after the split
_delimiter_pattern = re.compile(r"[ \t]*,[ \t]*")      # <-- (line 46) starts with an unbounded [ \t]*

# span.py:382
@classmethod
def from_header(cls, header_list: list[str]) -> TraceState:
    pairs = {}  # type: dict[str, str]
    for header in header_list:
        members: list[str] = re.split(_delimiter_pattern, header)   # <-- (line 400) VULNERABLE: O(N^2) on "a=b" + " " * N + "x"
        for member in members:
            if not member:
                continue
            match = _member_pattern.fullmatch(member)
            if not match:
                _logger.warning(                                    # <-- also logs the entire malformed member (up to the whole header)
                    "Member doesn't match the w3c identifiers format %s",
                    member,
                )
                return cls()
            ...

re.split tries the pattern at every offset. At each offset inside a whitespace run, [ \t]* consumes the rest of the run, finds no ,, backtracks and fails, then the engine moves one character forward and repeats. N characters × up to N steps each = O(N²). The 32-member limit never gets a chance to run because split has to finish first.

  1. The sibling propagator already has the missing guard:
# baggage/propagation/__init__.py:68
_MAX_HEADER_LENGTH = 8192
...
if len(header.encode()) > self._MAX_HEADER_LENGTH:   # <-- (line 93) rejected before any regex runs; tracestate has no equivalent
    _logger.warning(...)
    return context

A 16 KiB header costs ≈ 0.25 s and an 8 KiB header ≈ 0.07 s. Measured cost of extract() on one core (valid traceparent, tracestate: "a=b" + N spaces + "x"): the time quadruples each time N doubles (see the proof of concept). Roughly 0.06 s at 10,000 characters, 1 s at 40,000, 4 s at 80,000, 9 s at 100,000 (tabs are about 1.6× slower).

Whether a server lets such a header through (header-size limits, tested): gunicorn rejects ≥ 8190 bytes (response code 431); uvicorn --http h11 rejects above 16 KiB (400); waitress accepts up to 256 KiB (200 KB accepted, 300 KB rejected); uvicorn --http httptools — the default parser with…

Record
GHSA-xcq7-p3pf-p88h
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Weakness
CWE-1333, CWE-400
Updated
2026-11-02
OSVUBUNTU-CVE-2026-114603 5.3

OpenTelemetry Python provides the Python API and SDK for OpenTelemetry. Prior to 1.45.1, the opentelemetry-api function TraceState.from_header in opentelemetry/trace/span.py, reached through TraceContextTextMapPropagator.extract, parses inbound W3C tracestate headers with an unbounded optional-whitespace regular expression. A malformed header containing a long run of spaces or tabs without a following comma causes quadratic backtracking before the member-count limit is applied. Services using the default W3C Trace Context propagator can therefore spend excessive CPU time on one unauthenticated request when the HTTP server, parser, gateway, or custom carrier accepts a sufficiently large header. The processing can occupy a synchronous worker or delay unrelated requests on the same asynchronous event loop. The impact is limited to availability and does not expose or modify telemetry data or allow code execution. This issue is fixed in version 1.45.1.

Record
UBUNTU-CVE-2026-114603
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:L
Updated
2026-11-02
OSVopenSUSE-SU-2026:12408-1 No score

python313-opentelemetry-api-1.45.1-1.1 on GA media

These are all security issues fixed in the python313-opentelemetry-api-1.45.1-1.1 package on the GA media of openSUSE Tumbleweed.

Record
openSUSE-SU-2026:12408-1
Updated
2026-11-04

Affected products

Affected packages

Affected packages
PackageAffectedFixed
opentelemetry-api
PyPI
through 1.45.0
1.45.1
python-opentelemetry
Debian:14
before 1.45.1-1, plus listed versions
1.35.0-21.38.0-11.38.0-21.39.1-11.39.1-2
Show 7 moreShow less
1.40.0-11.41.0-11.41.0-21.42.1-11.43.0-11.44.0-11.44.0-2
1.45.1-1
opentelemetry-api
PyPI
before 1.45.1, plus listed versions
0.10b00.11b00.12b00.13b00.14b0
Show 45 moreShow less
0.15b00.16b00.16b10.17b00.1a00.2a00.3a00.4a00.4a10.5b00.6b00.7b00.7b10.8b00.9b01.0.01.0.0rc11.1.01.10.01.10a01.11.01.11.11.12.01.12.0rc11.12.0rc21.13.01.14.01.15.01.16.01.17.01.18.01.19.01.2.01.20.01.21.01.22.01.23.01.24.01.25.01.26.01.27.01.28.01.28.11.28.21.29.0
1.45.1
python-opentelemetry
Ubuntu:26.10
All versions, plus listed versions
1.39.1-21.42.1-11.43.0-11.44.0-11.44.0-2
None known
python-opentelemetry
Ubuntu:26.04:LTS
All versions, plus listed versions
1.38.0-11.38.0-21.39.1-11.39.1-2
None known
python-opentelemetry-api
openSUSE:Tumbleweed
before 1.45.1-1.1
1.45.1-1.1

History

History
RecordedChangedSources
affected, aliases, facts, referencesOSV
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-114603 is a medium vulnerability (CVSS 5.3) in Open-telemetry Opentelemetry-python, published October 22, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.49%, the 42nd percentile. Fixed in opentelemetry-api 1.45.1.

References

Show 7 moreShow less
This page doesn't list everything

Left out here: 35 versions and the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open