diff mbox series

[meta-python,scarthgap,3/8] python3-pyjwt: fix CVE-2026-102268 and CVE-2026-102270

Message ID 20261105045614.2677776-3-hthakar@cisco.com
State New
Headers show
Series [meta-python,scarthgap,1/8] python3-pyjwt: fix CVE-2026-102269 | expand

Commit Message

From: Hetvi Thakar <hthakar@cisco.com>

This patch applies the shared upstream fix as referenced in [2] and [3],
using the commit shown in [1].

Use a bounded PEM marker scan to reject loader-accepted public-key
variants and avoid excessive regular-expression backtracking.

[1] https://github.com/jpadilla/pyjwt/commit/8b4e233a22206b34ec1186e912e75c0b2396ac07
[2] https://github.com/jpadilla/pyjwt/security/advisories/GHSA-ffc3-869f-jxw9
[3] https://github.com/advisories/GHSA-jwrc-g2q2-pq5p

Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
---
 .../CVE-2026-102268_CVE-2026-102270.patch     | 116 ++++++++++++++++++
 .../python/python3-pyjwt_2.8.0.bb             |   1 +
 2 files changed, 117 insertions(+)
 create mode 100644 meta-python/recipes-devtools/python/python3-pyjwt/CVE-2026-102268_CVE-2026-102270.patch
diff mbox series

Patch

diff --git a/meta-python/recipes-devtools/python/python3-pyjwt/CVE-2026-102268_CVE-2026-102270.patch b/meta-python/recipes-devtools/python/python3-pyjwt/CVE-2026-102268_CVE-2026-102270.patch
new file mode 100644
index 0000000000..ed7fd0949b
--- /dev/null
+++ b/meta-python/recipes-devtools/python/python3-pyjwt/CVE-2026-102268_CVE-2026-102270.patch
@@ -0,0 +1,116 @@ 
+From 5b3dab98c3a6c6cd64dca4895451c1dd11f04b08 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jos=C3=A9=20Padilla?= <jpadilla@users.noreply.github.com>
+Date: Wed, 14 Oct 2026 02:43:17 -0700
+Subject: [PATCH] fix: reject loader-accepted PEM variants
+
+CVE: CVE-2026-102268 CVE-2026-102270
+Upstream-Status: Backport [https://github.com/jpadilla/pyjwt/commit/8b4e233a22206b34ec1186e912e75c0b2396ac07]
+
+Backport Changes:
+- Retain the existing Any import when adding Callable to the PyJWT 2.8.0
+  regression tests; the upstream test suite imports Union instead.
+
+Signed-off-by: Hetvi Thakar <hthakar@cisco.com>
+---
+ jwt/utils.py             | 20 ++++++++++--------
+ tests/test_algorithms.py | 44 +++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 55 insertions(+), 9 deletions(-)
+
+diff --git a/jwt/utils.py b/jwt/utils.py
+index 81c5ee4..4e3ad3c 100644
+--- a/jwt/utils.py
++++ b/jwt/utils.py
+@@ -116,18 +116,22 @@ _PEMS = {
+     b"X509 CRL",
+ }
+ 
+-_PEM_RE = re.compile(
+-    b"----[- ]BEGIN ("
+-    + b"|".join(_PEMS)
+-    + b""")[- ]----\r?
+-.+?\r?
+-----[- ]END \\1[- ]----\r?\n?""",
+-    re.DOTALL,
++# Accept PEM formatting variants that the cryptography loader accepts, while
++# retaining the explicit asymmetric-key marker check.
++_PEM_MARKER_RE = re.compile(
++    b"(?=(----[- ](BEGIN|END) (" + b"|".join(_PEMS) + b")[- ]----))"
+ )
+ 
+ 
+ def is_pem_format(key: bytes) -> bool:
+-    return bool(_PEM_RE.search(key))
++    begin_markers: dict[bytes, int] = {}
++    for marker in _PEM_MARKER_RE.finditer(key):
++        marker_type, label = marker.group(2), marker.group(3)
++        if marker_type == b"BEGIN":
++            begin_markers[label] = marker.start(1) + len(marker.group(1))
++        elif label in begin_markers and begin_markers[label] < marker.start(1):
++            return True
++    return False
+ 
+ 
+ # Based on https://github.com/pyca/cryptography/blob/bcb70852d577b3f490f015378c75cba74986297b/src/cryptography/hazmat/primitives/serialization/ssh.py#L40-L46
+diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py
+index e5220c6..0fbffc9 100644
+--- a/tests/test_algorithms.py
++++ b/tests/test_algorithms.py
+@@ -1,6 +1,6 @@
+ import base64
+ import json
+-from typing import Any, cast
++from typing import Any, Callable, cast
+ 
+ import pytest
+ 
+@@ -82,6 +82,48 @@ class TestAlgorithms:
+             with open(key_path(key)) as keyfile:
+                 algo.prepare_key(keyfile.read())
+ 
++    @pytest.mark.parametrize(
++        "mutation",
++        [
++            lambda key: key.replace(b"-----END", b"\t-----END"),
++            lambda key: key.replace(b"\n", b"\r"),
++            lambda key: key.replace(b"\n", b""),
++        ],
++    )
++    def test_hmac_should_reject_loader_accepted_pem_mutations(
++        self, mutation: Callable[[bytes], bytes]
++    ) -> None:
++        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
++        with open(key_path("testkey2_rsa.pub.pem"), "rb") as keyfile:
++            mutated_key = mutation(keyfile.read())
++
++        with pytest.raises(InvalidKeyError):
++            algo.prepare_key(mutated_key)
++
++    def test_hmac_should_accept_incomplete_pem_marker(self) -> None:
++        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
++        key = b"-----BEGIN PUBLIC KEY-----" * 10000
++
++        assert algo.prepare_key(key) == key
++
++    def test_hmac_should_reject_a_later_pem_block(self) -> None:
++        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
++        with open(key_path("testkey2_rsa.pub.pem"), "rb") as keyfile:
++            key = b"-----BEGIN PUBLIC KEY-----" + keyfile.read()
++
++        with pytest.raises(InvalidKeyError):
++            algo.prepare_key(key)
++
++    def test_hmac_should_reject_a_pem_block_after_an_overlapping_end_marker(
++        self,
++    ) -> None:
++        algo = HMACAlgorithm(HMACAlgorithm.SHA256)
++        with open(key_path("testkey2_rsa.pub.pem"), "rb") as keyfile:
++            key = b"-----END CERTIFICATE" + keyfile.read()
++
++        with pytest.raises(InvalidKeyError):
++            algo.prepare_key(key)
++
+     def test_hmac_jwk_should_parse_and_verify(self):
+         algo = HMACAlgorithm(HMACAlgorithm.SHA256)
+ 
+-- 
+2.35.6
diff --git a/meta-python/recipes-devtools/python/python3-pyjwt_2.8.0.bb b/meta-python/recipes-devtools/python/python3-pyjwt_2.8.0.bb
index fa03d1e616..f62b8aa7bb 100644
--- a/meta-python/recipes-devtools/python/python3-pyjwt_2.8.0.bb
+++ b/meta-python/recipes-devtools/python/python3-pyjwt_2.8.0.bb
@@ -14,6 +14,7 @@  SRC_URI += " \
     file://CVE-2026-102269_p1.patch \
     file://CVE-2026-102269_p2.patch \
     file://CVE-2026-102267.patch \
+    file://CVE-2026-102268_CVE-2026-102270.patch \
 "
 SRC_URI[sha256sum] = "57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"