diff --git a/meta-python/recipes-devtools/python/files/CVE-2026-102267.patch b/meta-python/recipes-devtools/python/files/CVE-2026-102267.patch
new file mode 100644
index 0000000000..97dfd88364
--- /dev/null
+++ b/meta-python/recipes-devtools/python/files/CVE-2026-102267.patch
@@ -0,0 +1,223 @@
+From 0a795b8e1f6ef08f634aa7086fc41cc6d5ce3e56 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jos=C3=A9=20Padilla?= <jpadilla@users.noreply.github.com>
+Date: Wed, 9 Sep 2026 20:20:46 -0400
+Subject: [PATCH] Reject redirects in PyJWKClient fetches
+
+CVE: CVE-2026-102267
+Upstream-Status: Backport [https://github.com/jpadilla/pyjwt/commit/0a795b8e1f6ef08f634aa7086fc41cc6d5ce3e56]
+
+(cherry picked from commit 0a795b8e1f6ef08f634aa7086fc41cc6d5ce3e56)
+Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
+---
+ jwt/jwks_client.py        | 21 +++++++--
+ tests/test_jwks_client.py | 91 ++++++++++++++++++++++++++++++++++-----
+ 2 files changed, 99 insertions(+), 13 deletions(-)
+
+diff --git a/jwt/jwks_client.py b/jwt/jwks_client.py
+index 41f333a..cfc9003 100644
+--- a/jwt/jwks_client.py
++++ b/jwt/jwks_client.py
+@@ -14,6 +14,19 @@ from .exceptions import PyJWKClientConnectionError, PyJWKClientError
+ from .jwk_set_cache import JWKSetCache
+ 
+ 
++class _NoRedirectHandler(urllib.request.HTTPRedirectHandler):
++    def redirect_request(
++        self,
++        req: urllib.request.Request,
++        fp: Any,
++        code: int,
++        msg: str,
++        headers: Any,
++        newurl: str,
++    ) -> None:
++        return None
++
++
+ class PyJWKClient:
+     def __init__(
+         self,
+@@ -115,9 +128,11 @@ class PyJWKClient:
+         """
+         try:
+             r = urllib.request.Request(url=self.uri, headers=self.headers)
+-            with urllib.request.urlopen(
+-                r, timeout=self.timeout, context=self.ssl_context
+-            ) as response:
++            handlers: list[Any] = [_NoRedirectHandler()]
++            if self.ssl_context is not None:
++                handlers.append(urllib.request.HTTPSHandler(context=self.ssl_context))
++            opener = urllib.request.build_opener(*handlers)
++            with opener.open(r, timeout=self.timeout) as response:
+                 jwk_set = json.load(response)
+         except (URLError, TimeoutError) as e:
+             if isinstance(e, HTTPError):
+diff --git a/tests/test_jwks_client.py b/tests/test_jwks_client.py
+index da68664..49471ac 100644
+--- a/tests/test_jwks_client.py
++++ b/tests/test_jwks_client.py
+@@ -2,8 +2,10 @@ import contextlib
+ import io
+ import json
+ import ssl
++import threading
+ import time
+ from collections.abc import Iterator
++from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
+ from unittest import mock
+ from urllib.error import HTTPError, URLError
+ from email.message import Message
+@@ -12,6 +14,7 @@ import pytest
+ 
+ import jwt
+ from jwt import PyJWKClient
++from jwt.jwks_client import _NoRedirectHandler
+ from jwt.api_jwk import PyJWK
+ from jwt.exceptions import PyJWKClientConnectionError, PyJWKClientError
+ 
+@@ -50,7 +53,10 @@ RESPONSE_DATA_NO_MATCHING_KID = {
+ 
+ @contextlib.contextmanager
+ def mocked_success_response(data: object) -> Iterator[mock.Mock]:
+-    with mock.patch("urllib.request.urlopen") as urlopen_mock:
++    with mock.patch("urllib.request.build_opener") as build_opener_mock:
++        opener = mock.Mock()
++        build_opener_mock.return_value = opener
++        urlopen_mock = opener.open
+         response = mock.Mock()
+         response.__enter__ = mock.Mock(return_value=response)
+         response.__exit__ = mock.Mock()
+@@ -61,7 +67,10 @@ def mocked_success_response(data: object) -> Iterator[mock.Mock]:
+ 
+ @contextlib.contextmanager
+ def mocked_failed_response() -> Iterator[mock.Mock]:
+-    with mock.patch("urllib.request.urlopen") as urlopen_mock:
++    with mock.patch("urllib.request.build_opener") as build_opener_mock:
++        opener = mock.Mock()
++        build_opener_mock.return_value = opener
++        urlopen_mock = opener.open
+         urlopen_mock.side_effect = URLError("Fail to process the request.")
+         yield urlopen_mock
+ 
+@@ -70,7 +79,10 @@ def mocked_failed_response() -> Iterator[mock.Mock]:
+ def mocked_first_call_wrong_kid_second_call_correct_kid(
+     response_data_one: object, response_data_two: object
+ ) -> Iterator[mock.Mock]:
+-    with mock.patch("urllib.request.urlopen") as urlopen_mock:
++    with mock.patch("urllib.request.build_opener") as build_opener_mock:
++        opener = mock.Mock()
++        build_opener_mock.return_value = opener
++        urlopen_mock = opener.open
+         response = mock.Mock()
+         response.__enter__ = mock.Mock(return_value=response)
+         response.__exit__ = mock.Mock()
+@@ -84,14 +96,20 @@ def mocked_first_call_wrong_kid_second_call_correct_kid(
+ 
+ @contextlib.contextmanager
+ def mocked_timeout() -> Iterator[mock.Mock]:
+-    with mock.patch("urllib.request.urlopen") as urlopen_mock:
++    with mock.patch("urllib.request.build_opener") as build_opener_mock:
++        opener = mock.Mock()
++        build_opener_mock.return_value = opener
++        urlopen_mock = opener.open
+         urlopen_mock.side_effect = TimeoutError("timed out")
+         yield urlopen_mock
+ 
+ 
+ @contextlib.contextmanager
+ def mocked_http_error_response() -> Iterator[tuple[mock.Mock, HTTPError]]:
+-    with mock.patch("urllib.request.urlopen") as urlopen_mock:
++    with mock.patch("urllib.request.build_opener") as build_opener_mock:
++        opener = mock.Mock()
++        build_opener_mock.return_value = opener
++        urlopen_mock = opener.open
+         http_error = HTTPError(
+             url="https://example.com",
+             code=401,
+@@ -105,6 +123,50 @@ def mocked_http_error_response() -> Iterator[tuple[mock.Mock, HTTPError]]:
+ 
+ @crypto_required
+ class TestPyJWKClient:
++    def test_fetch_data_rejects_redirect_without_contacting_destination(self) -> None:
++        destination_requests = 0
++
++        class RedirectHandler(BaseHTTPRequestHandler):
++            def do_GET(self) -> None:  # noqa: N802 - stdlib handler API
++                nonlocal destination_requests
++                if self.path == "/start":
++                    self.send_response(302)
++                    self.send_header("Location", f"{base_url}/destination")
++                    self.end_headers()
++                else:
++                    destination_requests += 1
++                    self.send_response(200)
++                    self.end_headers()
++
++            def log_message(self, _format: str, *args: object) -> None:
++                return
++
++        server = ThreadingHTTPServer(("127.0.0.1", 0), RedirectHandler)
++        base_url = f"http://127.0.0.1:{server.server_port}"
++        thread = threading.Thread(target=server.serve_forever, daemon=True)
++        thread.start()
++        try:
++            client = PyJWKClient(
++                f"{base_url}/start", headers={"Authorization": "secret"}
++            )
++            with pytest.raises(PyJWKClientConnectionError):
++                client.fetch_data()
++            assert destination_requests == 0
++        finally:
++            server.shutdown()
++            server.server_close()
++            thread.join()
++
++    def test_redirect_handler_does_not_follow_redirects(self) -> None:
++        handler = _NoRedirectHandler()
++
++        assert (
++            handler.redirect_request(
++                mock.Mock(), mock.Mock(), 302, "Found", {}, "https://other.test"
++            )
++            is None
++        )
++
+     def test_fetch_data_forwards_headers_to_correct_url(self) -> None:
+         url = "https://dev-87evx9ru.auth0.com/.well-known/jwks.json"
+ 
+@@ -401,10 +463,19 @@ class TestPyJWKClient:
+         ssl_ctx = ssl.create_default_context()
+         jwks_client = PyJWKClient(url, ssl_context=ssl_ctx)
+ 
+-        with mocked_success_response(RESPONSE_DATA_WITH_MATCHING_KID) as mock_request:
++        with mock.patch("urllib.request.build_opener") as build_opener_mock:
++            opener = mock.Mock()
++            build_opener_mock.return_value = opener
++            response = mock.Mock()
++            response.__enter__ = mock.Mock(return_value=response)
++            response.__exit__ = mock.Mock()
++            response.read.return_value = json.dumps(RESPONSE_DATA_WITH_MATCHING_KID)
++            opener.open.return_value = response
+             jwk_set = jwks_client.get_jwk_set()
+-            request_call = mock_request.call_args
+-            assert request_call[1].get("context") is ssl_ctx
++            handlers = build_opener_mock.call_args.args
++            assert any(
++                getattr(handler, "_context", None) is ssl_ctx for handler in handlers
++            )
+ 
+         assert jwk_set is not None
+ 
+@@ -414,8 +485,8 @@ class TestPyJWKClient:
+             url, ssl_context=ssl.SSLContext(protocol=ssl.PROTOCOL_TLS_CLIENT)
+         )
+ 
+-        with mock.patch("urllib.request.urlopen") as urlopen_mock:
+-            urlopen_mock.side_effect = URLError(
++        with mock.patch("urllib.request.build_opener") as build_opener_mock:
++            build_opener_mock.return_value.open.side_effect = URLError(
+                 ssl.SSLCertVerificationError("certificate verify failed")
+             )
+             with pytest.raises(PyJWKClientError):
+-- 
+2.35.6
diff --git a/meta-python/recipes-devtools/python/python3-pyjwt_2.12.1.bb b/meta-python/recipes-devtools/python/python3-pyjwt_2.12.1.bb
index a159f2fbbb..f7134a1367 100644
--- a/meta-python/recipes-devtools/python/python3-pyjwt_2.12.1.bb
+++ b/meta-python/recipes-devtools/python/python3-pyjwt_2.12.1.bb
@@ -13,6 +13,7 @@ SRC_URI += "file://CVE-2026-48522.patch \
            file://CVE-2026-103001.patch \
            file://CVE-2026-102274.patch \
            file://CVE-2026-102269.patch \
+           file://CVE-2026-102267.patch \
            "
 
 SRC_URI[sha256sum] = "c74a7a2adf861c04d002db713dd85f84beb242228e671280bf709d765b03672b"
