Skip to content

Commit 965c6f7

Browse files
mandreeDaniel Engberg
authored andcommitted
lang/python314: Fix incomplete mitigation of webbrowser.open()
Cherry-pick fix to resolve Incomplete mitigation of CVE-2026-4519, %action expansion for command injection to webbrowser.open() Obtained from: GitHub repo python/cpython#148516 Security: CVE-2026-4786 cf75f572-378a-11f1-a119-e36228bfe7d4
1 parent 013edbc commit 965c6f7

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

‎lang/python314/Makefile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
PORTNAME= python
22
DISTVERSION= ${PYTHON_DISTVERSION} # see Makefile.version
3-
PORTREVISION= 1
3+
PORTREVISION= 2
44
CATEGORIES= lang python
55
MASTER_SITES= PYTHON/ftp/python/${DISTVERSION:C/[a-z].*//}
66
PKGNAMESUFFIX= ${PYTHON_SUFFIX}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
From f529b9470752c28ab69c96f31b0dbc10db69b404 Mon Sep 17 00:00:00 2001
2+
From: Stan Ulbrych <stan@python.org>
3+
Date: Mon, 13 Apr 2026 20:02:52 +0100
4+
Subject: [PATCH] gh-148169: Fix webbrowser `%action` substitution bypass of
5+
dash-prefix check (GH-148170) (cherry picked from commit
6+
d22922c8a7958353689dc4763dd72da2dea03fff)
7+
8+
Co-authored-by: Stan Ulbrych <stan@python.org>
9+
---
10+
Lib/test/test_webbrowser.py | 9 +++++++++
11+
Lib/webbrowser.py | 5 +++--
12+
.../2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst | 2 ++
13+
3 files changed, 14 insertions(+), 2 deletions(-)
14+
create mode 100644 Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst
15+
16+
diff --git a/Lib/test/test_webbrowser.py b/Lib/test/test_webbrowser.py
17+
index 404b3a31a5d2c9..bfbcf112b0b085 100644
18+
--- ./Lib/test/test_webbrowser.py
19+
+++ b/Lib/test/test_webbrowser.py
20+
@@ -119,6 +119,15 @@ def test_open_bad_new_parameter(self):
21+
arguments=[URL],
22+
kw=dict(new=999))
23+
24+
+ def test_reject_action_dash_prefixes(self):
25+
+ browser = self.browser_class(name=CMD_NAME)
26+
+ with self.assertRaises(ValueError):
27+
+ browser.open('%action--incognito')
28+
+ # new=1: action is "--new-window", so "%action" itself expands to
29+
+ # a dash-prefixed flag even with no dash in the original URL.
30+
+ with self.assertRaises(ValueError):
31+
+ browser.open('%action', new=1)
32+
+
33+
34+
class EdgeCommandTest(CommandTestMixin, unittest.TestCase):
35+
36+
diff --git a/Lib/webbrowser.py b/Lib/webbrowser.py
37+
index 0e0b5034e5f53d..97aad6eea509eb 100644
38+
--- ./Lib/webbrowser.py
39+
+++ b/Lib/webbrowser.py
40+
@@ -274,7 +274,6 @@ def _invoke(self, args, remote, autoraise, url=None):
41+
42+
def open(self, url, new=0, autoraise=True):
43+
sys.audit("webbrowser.open", url)
44+
- self._check_url(url)
45+
if new == 0:
46+
action = self.remote_action
47+
elif new == 1:
48+
@@ -288,7 +287,9 @@ def open(self, url, new=0, autoraise=True):
49+
raise Error("Bad 'new' parameter to open(); "
50+
f"expected 0, 1, or 2, got {new}")
51+
52+
- args = [arg.replace("%s", url).replace("%action", action)
53+
+ self._check_url(url.replace("%action", action))
54+
+
55+
+ args = [arg.replace("%action", action).replace("%s", url)
56+
for arg in self.remote_args]
57+
args = [arg for arg in args if arg]
58+
success = self._invoke(args, True, autoraise, url)
59+
diff --git a/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst b/Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst
60+
new file mode 100644
61+
index 00000000000000..45cdeebe1b6d64
62+
--- /dev/null
63+
+++ ./Misc/NEWS.d/next/Security/2026-03-31-09-15-51.gh-issue-148169.EZJzz2.rst
64+
@@ -0,0 +1,2 @@
65+
+A bypass in :mod:`webbrowser` allowed URLs prefixed with ``%action`` to pass
66+
+the dash-prefix safety check.

0 commit comments

Comments
 (0)