diff options
author | Peter Marko <peter.marko@siemens.com> | 2025-03-25 22:13:56 +0100 |
---|---|---|
committer | Steve Sakoman <steve@sakoman.com> | 2025-04-01 09:02:41 -0700 |
commit | d4bb2231fad79a64346c3add1de8d1dcdf8dd0fb (patch) | |
tree | c06300fff25a614706b8d5d1716a1a1d3282811e | |
parent | d4411e521d7bef26889b2f6bc63a6587ddf439da (diff) | |
download | poky-d4bb2231fad79a64346c3add1de8d1dcdf8dd0fb.tar.gz |
python3: patch CVE-2025-0938
Pick commit mentioned in NDV CVE report
https://github.com/python/cpython/commit/b8b4b713c5f8ec0958c7ef8d29d6711889bc94ab
which is on 3.10 branch.
(From OE-Core rev: 70036b4ea0ab968adab82fc632bb967f95203de2)
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
-rw-r--r-- | meta/recipes-devtools/python/python3/CVE-2025-0938.patch | 131 | ||||
-rw-r--r-- | meta/recipes-devtools/python/python3_3.10.16.bb | 1 |
2 files changed, 132 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python3/CVE-2025-0938.patch b/meta/recipes-devtools/python/python3/CVE-2025-0938.patch new file mode 100644 index 0000000000..5730008f4b --- /dev/null +++ b/meta/recipes-devtools/python/python3/CVE-2025-0938.patch | |||
@@ -0,0 +1,131 @@ | |||
1 | From b8b4b713c5f8ec0958c7ef8d29d6711889bc94ab Mon Sep 17 00:00:00 2001 | ||
2 | From: "Miss Islington (bot)" | ||
3 | <31488909+miss-islington@users.noreply.github.com> | ||
4 | Date: Wed, 19 Feb 2025 14:36:23 +0100 | ||
5 | Subject: [PATCH] [3.10] gh-105704: Disallow square brackets (`[` and `]`) in | ||
6 | domain names for parsed URLs (GH-129418) (#129529) | ||
7 | MIME-Version: 1.0 | ||
8 | Content-Type: text/plain; charset=UTF-8 | ||
9 | Content-Transfer-Encoding: 8bit | ||
10 | |||
11 | (cherry picked from commit d89a5f6a6e65511a5f6e0618c4c30a7aa5aba56a) | ||
12 | |||
13 | Co-authored-by: Seth Michael Larson <seth@python.org> | ||
14 | Co-authored-by: Peter Bierma <zintensitydev@gmail.com> | ||
15 | Co-authored-by: Ćukasz Langa <lukasz@langa.pl> | ||
16 | |||
17 | CVE: CVE-2025-0938 | ||
18 | Upstream-Status: Backport [https://github.com/python/cpython/commit/b8b4b713c5f8ec0958c7ef8d29d6711889bc94ab] | ||
19 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
20 | --- | ||
21 | Lib/test/test_urlparse.py | 37 ++++++++++++++++++- | ||
22 | Lib/urllib/parse.py | 20 +++++++++- | ||
23 | ...-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | 4 ++ | ||
24 | 3 files changed, 58 insertions(+), 3 deletions(-) | ||
25 | create mode 100644 Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | ||
26 | |||
27 | diff --git a/Lib/test/test_urlparse.py b/Lib/test/test_urlparse.py | ||
28 | index f2ffc452e5..280644ef0b 100644 | ||
29 | --- a/Lib/test/test_urlparse.py | ||
30 | +++ b/Lib/test/test_urlparse.py | ||
31 | @@ -1149,16 +1149,51 @@ class UrlParseTestCase(unittest.TestCase): | ||
32 | self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af::2309::fae7:1234]/Path?Query') | ||
33 | self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@[0439:23af:2309::fae7:1234:2342:438e:192.0.2.146]/Path?Query') | ||
34 | self.assertRaises(ValueError, urllib.parse.urlsplit, 'Scheme://user@]v6a.ip[/Path') | ||
35 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]') | ||
36 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix') | ||
37 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]/') | ||
38 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix/') | ||
39 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip]?') | ||
40 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip].suffix?') | ||
41 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]') | ||
42 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix') | ||
43 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]/') | ||
44 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix/') | ||
45 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]?') | ||
46 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix?') | ||
47 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a') | ||
48 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a') | ||
49 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:a1') | ||
50 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:a1') | ||
51 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:1a') | ||
52 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:1a') | ||
53 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:') | ||
54 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[::1].suffix:/') | ||
55 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[::1]:?') | ||
56 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@prefix.[v6a.ip]') | ||
57 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://user@[v6a.ip].suffix') | ||
58 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://[v6a.ip') | ||
59 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip]') | ||
60 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip[') | ||
61 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://]v6a.ip') | ||
62 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[') | ||
63 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix.[v6a.ip') | ||
64 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip].suffix') | ||
65 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip[suffix') | ||
66 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://prefix]v6a.ip') | ||
67 | + self.assertRaises(ValueError, urllib.parse.urlsplit, 'scheme://v6a.ip[suffix') | ||
68 | |||
69 | def test_splitting_bracketed_hosts(self): | ||
70 | - p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]/path?query') | ||
71 | + p1 = urllib.parse.urlsplit('scheme://user@[v6a.ip]:1234/path?query') | ||
72 | self.assertEqual(p1.hostname, 'v6a.ip') | ||
73 | self.assertEqual(p1.username, 'user') | ||
74 | self.assertEqual(p1.path, '/path') | ||
75 | + self.assertEqual(p1.port, 1234) | ||
76 | p2 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7%test]/path?query') | ||
77 | self.assertEqual(p2.hostname, '0439:23af:2309::fae7%test') | ||
78 | self.assertEqual(p2.username, 'user') | ||
79 | self.assertEqual(p2.path, '/path') | ||
80 | + self.assertIs(p2.port, None) | ||
81 | p3 = urllib.parse.urlsplit('scheme://user@[0439:23af:2309::fae7:1234:192.0.2.146%test]/path?query') | ||
82 | self.assertEqual(p3.hostname, '0439:23af:2309::fae7:1234:192.0.2.146%test') | ||
83 | self.assertEqual(p3.username, 'user') | ||
84 | diff --git a/Lib/urllib/parse.py b/Lib/urllib/parse.py | ||
85 | index 07e3248504..e1ee36d98e 100644 | ||
86 | --- a/Lib/urllib/parse.py | ||
87 | +++ b/Lib/urllib/parse.py | ||
88 | @@ -442,6 +442,23 @@ def _checknetloc(netloc): | ||
89 | raise ValueError("netloc '" + netloc + "' contains invalid " + | ||
90 | "characters under NFKC normalization") | ||
91 | |||
92 | +def _check_bracketed_netloc(netloc): | ||
93 | + # Note that this function must mirror the splitting | ||
94 | + # done in NetlocResultMixins._hostinfo(). | ||
95 | + hostname_and_port = netloc.rpartition('@')[2] | ||
96 | + before_bracket, have_open_br, bracketed = hostname_and_port.partition('[') | ||
97 | + if have_open_br: | ||
98 | + # No data is allowed before a bracket. | ||
99 | + if before_bracket: | ||
100 | + raise ValueError("Invalid IPv6 URL") | ||
101 | + hostname, _, port = bracketed.partition(']') | ||
102 | + # No data is allowed after the bracket but before the port delimiter. | ||
103 | + if port and not port.startswith(":"): | ||
104 | + raise ValueError("Invalid IPv6 URL") | ||
105 | + else: | ||
106 | + hostname, _, port = hostname_and_port.partition(':') | ||
107 | + _check_bracketed_host(hostname) | ||
108 | + | ||
109 | # Valid bracketed hosts are defined in | ||
110 | # https://www.rfc-editor.org/rfc/rfc3986#page-49 and https://url.spec.whatwg.org/ | ||
111 | def _check_bracketed_host(hostname): | ||
112 | @@ -505,8 +522,7 @@ def urlsplit(url, scheme='', allow_fragments=True): | ||
113 | (']' in netloc and '[' not in netloc)): | ||
114 | raise ValueError("Invalid IPv6 URL") | ||
115 | if '[' in netloc and ']' in netloc: | ||
116 | - bracketed_host = netloc.partition('[')[2].partition(']')[0] | ||
117 | - _check_bracketed_host(bracketed_host) | ||
118 | + _check_bracketed_netloc(netloc) | ||
119 | if allow_fragments and '#' in url: | ||
120 | url, fragment = url.split('#', 1) | ||
121 | if '?' in url: | ||
122 | diff --git a/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | ||
123 | new file mode 100644 | ||
124 | index 0000000000..bff1bc6b0d | ||
125 | --- /dev/null | ||
126 | +++ b/Misc/NEWS.d/next/Security/2025-01-28-14-08-03.gh-issue-105704.EnhHxu.rst | ||
127 | @@ -0,0 +1,4 @@ | ||
128 | +When using :func:`urllib.parse.urlsplit` and :func:`urllib.parse.urlparse` host | ||
129 | +parsing would not reject domain names containing square brackets (``[`` and | ||
130 | +``]``). Square brackets are only valid for IPv6 and IPvFuture hosts according to | ||
131 | +`RFC 3986 Section 3.2.2 <https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2>`__. | ||
diff --git a/meta/recipes-devtools/python/python3_3.10.16.bb b/meta/recipes-devtools/python/python3_3.10.16.bb index 48f845b089..932791f38d 100644 --- a/meta/recipes-devtools/python/python3_3.10.16.bb +++ b/meta/recipes-devtools/python/python3_3.10.16.bb | |||
@@ -37,6 +37,7 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \ | |||
37 | file://0001-Avoid-shebang-overflow-on-python-config.py.patch \ | 37 | file://0001-Avoid-shebang-overflow-on-python-config.py.patch \ |
38 | file://0001-test_storlines-skip-due-to-load-variability.patch \ | 38 | file://0001-test_storlines-skip-due-to-load-variability.patch \ |
39 | file://0001-gh-107811-tarfile-treat-overflow-in-UID-GID-as-failu.patch \ | 39 | file://0001-gh-107811-tarfile-treat-overflow-in-UID-GID-as-failu.patch \ |
40 | file://CVE-2025-0938.patch \ | ||
40 | " | 41 | " |
41 | 42 | ||
42 | SRC_URI:append:class-native = " \ | 43 | SRC_URI:append:class-native = " \ |