Skip to content

Commit 733a83c

Browse files
RinZ27ashok672
andauthored
Security: Remove unsafe PowerShell fallback in WSL (#866)
* Security: Remove unsafe PowerShell fallback in WSL * Remove unnecessary blank lines in authcode.py --------- Co-authored-by: Ashok Kumar Ramakrishnan <83938949+ashok672@users.noreply.github.com>
1 parent d7e0e11 commit 733a83c

File tree

1 file changed

+26
-10
lines changed

1 file changed

+26
-10
lines changed

msal/oauth2cli/authcode.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,24 +68,42 @@ def is_wsl():
6868

6969
def _browse(auth_uri, browser_name=None): # throws ImportError, webbrowser.Error
7070
"""Browse uri with named browser. Default browser is customizable by $BROWSER"""
71+
try:
72+
parsed_uri = urlparse(auth_uri)
73+
if parsed_uri.scheme not in ("http", "https"):
74+
logger.warning("Invalid URI scheme for browser: %s", parsed_uri.scheme)
75+
return False
76+
except ValueError:
77+
logger.warning("Invalid URI: %s", auth_uri)
78+
return False
79+
if any(c in auth_uri for c in "\n\r\t"):
80+
logger.warning("Invalid characters in URI")
81+
return False
82+
7183
import webbrowser # Lazy import. Some distro may not have this.
7284
if browser_name:
7385
browser_opened = webbrowser.get(browser_name).open(auth_uri)
7486
else:
7587
# This one can survive BROWSER=nonexist, while get(None).open(...) can not
7688
browser_opened = webbrowser.open(auth_uri)
7789

78-
# In WSL which doesn't have www-browser, try launching browser with PowerShell
90+
# In WSL which doesn't have www-browser, try launching browser with explorer.exe
7991
if not browser_opened and is_wsl():
80-
try:
81-
import subprocess
82-
# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
83-
# Ampersand (&) should be quoted
84-
exit_code = subprocess.call(
85-
['powershell.exe', '-NoProfile', '-Command', 'Start-Process "{}"'.format(auth_uri)])
92+
import subprocess
93+
try: # Try wslview first, which is the recommended way on WSL
94+
# https://github.com/wslutilities/wslu
95+
exit_code = subprocess.call(['wslview', auth_uri])
8696
browser_opened = exit_code == 0
87-
except FileNotFoundError: # WSL might be too old
97+
except FileNotFoundError: # wslview might not be installed
8898
pass
99+
if not browser_opened:
100+
try:
101+
# Fallback to explorer.exe as recommended for WSL
102+
# Note: explorer.exe returns 1 on success in some WSL environments
103+
exit_code = subprocess.call(['explorer.exe', auth_uri])
104+
browser_opened = exit_code in (0, 1)
105+
except FileNotFoundError:
106+
pass
89107
return browser_opened
90108

91109

@@ -102,12 +120,10 @@ def _is_html(text):
102120
def _escape(key_value_pairs):
103121
return {k: escape(v) for k, v in key_value_pairs.items()}
104122

105-
106123
def _printify(text):
107124
# If an https request is sent to an http server, the text needs to be repr-ed
108125
return repr(text) if isinstance(text, str) and not text.isprintable() else text
109126

110-
111127
class _AuthCodeHandler(BaseHTTPRequestHandler):
112128
def do_GET(self):
113129
qs = parse_qs(urlparse(self.path).query)

0 commit comments

Comments
 (0)