From 955cb732b5cecd6b752a58a2c765d3555b01752c Mon Sep 17 00:00:00 2001 From: pranaysb Date: Tue, 7 Jul 2026 13:03:00 +0530 Subject: [PATCH 1/2] opentelemetry-api: Fix Context in-place mutability bypass via inherited dict methods --- .changelog/context-immutability.fixed | 1 + .../src/opentelemetry/context/context.py | 21 +++++++++++++++++++ .../tests/context/test_context.py | 18 ++++++++++++++-- 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 .changelog/context-immutability.fixed diff --git a/.changelog/context-immutability.fixed b/.changelog/context-immutability.fixed new file mode 100644 index 00000000000..21a38f5b099 --- /dev/null +++ b/.changelog/context-immutability.fixed @@ -0,0 +1 @@ +`opentelemetry-api`: Prevent in-place mutation of `Context` via inherited `dict` methods diff --git a/opentelemetry-api/src/opentelemetry/context/context.py b/opentelemetry-api/src/opentelemetry/context/context.py index c8d87a422dd..984bf424d84 100644 --- a/opentelemetry-api/src/opentelemetry/context/context.py +++ b/opentelemetry-api/src/opentelemetry/context/context.py @@ -11,6 +11,27 @@ class Context(dict[str, object]): def __setitem__(self, key: str, value: object) -> None: raise ValueError + def __delitem__(self, key: str) -> None: + raise ValueError + + def setdefault(self, key: str, default: object = None) -> object: + raise ValueError + + def pop(self, key: str, *args: object) -> object: + raise ValueError + + def popitem(self) -> tuple[str, object]: + raise ValueError + + def clear(self) -> None: + raise ValueError + + def update(self, *args: object, **kwargs: object) -> None: + raise ValueError + + def __ior__(self, other: object) -> Context: + raise ValueError + class _RuntimeContext(ABC): """The RuntimeContext interface provides a wrapper for the different diff --git a/opentelemetry-api/tests/context/test_context.py b/opentelemetry-api/tests/context/test_context.py index ce5327d8680..10b32de363d 100644 --- a/opentelemetry-api/tests/context/test_context.py +++ b/opentelemetry-api/tests/context/test_context.py @@ -54,9 +54,23 @@ def test_set_value(self): self.assertEqual(None, context.get_value("a")) def test_context_is_immutable(self): + ctx = context.get_current() with self.assertRaises(ValueError): - # ensure a context - context.get_current()["test"] = "cant-change-immutable" + ctx["test"] = "cant-change-immutable" + with self.assertRaises(ValueError): + del ctx["test"] + with self.assertRaises(ValueError): + ctx.pop("test") + with self.assertRaises(ValueError): + ctx.popitem() + with self.assertRaises(ValueError): + ctx.clear() + with self.assertRaises(ValueError): + ctx.update({"test": "cant-change-immutable"}) + with self.assertRaises(ValueError): + ctx.setdefault("test", "cant-change-immutable") + with self.assertRaises(ValueError): + ctx |= {"test": "cant-change-immutable"} def test_set_current(self): context.attach(context.set_value("a", "yyy")) From 4eba9c93ae256b7ea5bb88223d90c0c432b07370 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Em=C3=ADdio=20Neto?= <9735060+emdneto@users.noreply.github.com> Date: Wed, 8 Jul 2026 14:52:18 -0300 Subject: [PATCH 2/2] Rename context-immutability.fixed to 5399.fixed --- .changelog/{context-immutability.fixed => 5399.fixed} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .changelog/{context-immutability.fixed => 5399.fixed} (100%) diff --git a/.changelog/context-immutability.fixed b/.changelog/5399.fixed similarity index 100% rename from .changelog/context-immutability.fixed rename to .changelog/5399.fixed