Skip to content

Commit 5b63c44

Browse files
committed
[py] Add test for warning when embedding user:pass in URL
Signed-off-by: Viet Nguyen Duc <[email protected]>
1 parent 9ae1d7b commit 5b63c44

File tree

3 files changed

+31
-19
lines changed

3 files changed

+31
-19
lines changed

py/selenium/webdriver/remote/client_config.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,10 @@ def auth_type(self) -> str:
209209
@auth_type.setter
210210
def auth_type(self, value: str) -> None:
211211
"""Sets the type of authentication to the remote server if it is not
212-
using basic with username and password."""
212+
using basic with username and password.
213+
214+
Support values: Bearer, X-API-Key. For others, please use `extra_headers` instead
215+
"""
213216
self._auth_type = value
214217

215218
@property
@@ -220,10 +223,7 @@ def token(self) -> str:
220223
@token.setter
221224
def token(self, value: str) -> None:
222225
"""Sets the token used for authentication to the remote server if
223-
auth_type is not basic.
224-
225-
Support values: Bearer, X-API-Key. For others, please use `extra_headers` instead.
226-
"""
226+
auth_type is not basic."""
227227
self._token = value
228228

229229
@property

py/selenium/webdriver/remote/remote_connection.py

+7-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from base64 import b64encode
2323
from typing import Optional
2424
from urllib import parse
25+
from urllib.parse import urlparse
2526

2627
import urllib3
2728

@@ -258,16 +259,14 @@ def get_remote_connection_headers(cls, parsed_url, keep_alive=False):
258259
return headers
259260

260261
def _identify_http_proxy_auth(self):
261-
url = self._proxy_url
262-
url = url[url.find(":") + 3 :]
263-
return "@" in url and len(url[: url.find("@")]) > 0
262+
parsed_url = urlparse(self._proxy_url)
263+
if parsed_url.username and parsed_url.password:
264+
return True
264265

265266
def _separate_http_proxy_auth(self):
266-
url = self._proxy_url
267-
protocol = url[: url.find(":") + 3]
268-
no_protocol = url[len(protocol) :]
269-
auth = no_protocol[: no_protocol.find("@")]
270-
proxy_without_auth = protocol + no_protocol[len(auth) + 1 :]
267+
parsed_url = urlparse(self._proxy_url)
268+
proxy_without_auth = f"{parsed_url.scheme}://{parsed_url.hostname}:{parsed_url.port}"
269+
auth = f"{parsed_url.username}:{parsed_url.password}"
271270
return proxy_without_auth, auth
272271

273272
def _get_connection_manager(self):

py/test/unit/selenium/webdriver/remote/remote_connection_tests.py

+19-6
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,13 @@ def test_get_remote_connection_headers_defaults():
6969

7070
def test_get_remote_connection_headers_adds_auth_header_if_pass():
7171
url = "http://user:pass@remote"
72-
headers = RemoteConnection.get_remote_connection_headers(parse.urlparse(url))
72+
with pytest.warns(None) as record:
73+
headers = RemoteConnection.get_remote_connection_headers(parse.urlparse(url))
7374
assert headers.get("Authorization") == "Basic dXNlcjpwYXNz"
75+
assert (
76+
record[0].message.args[0]
77+
== "Embedding username and password in URL could be insecure, use ClientConfig instead"
78+
)
7479

7580

7681
def test_get_remote_connection_headers_adds_keep_alive_if_requested():
@@ -126,13 +131,15 @@ def test_get_proxy_url_https_via_client_config():
126131
proxy=Proxy({"proxyType": ProxyType.MANUAL, "sslProxy": "https://admin:admin@http_proxy.com:8080"}),
127132
)
128133
remote_connection = RemoteConnection(client_config=client_config)
129-
proxy_url = remote_connection._client_config.get_proxy_url()
130-
assert proxy_url == "https://admin:admin@http_proxy.com:8080"
134+
conn = remote_connection._get_connection_manager()
135+
assert isinstance(conn, urllib3.ProxyManager)
136+
conn.proxy_url = "https://http_proxy.com:8080"
137+
conn.connection_pool_kw["proxy_headers"] = urllib3.make_headers(proxy_basic_auth="admin:admin")
131138

132139

133140
def test_get_proxy_url_http_via_client_config():
134141
client_config = ClientConfig(
135-
remote_server_addr="https://localhost:4444",
142+
remote_server_addr="http://localhost:4444",
136143
proxy=Proxy(
137144
{
138145
"proxyType": ProxyType.MANUAL,
@@ -142,15 +149,19 @@ def test_get_proxy_url_http_via_client_config():
142149
),
143150
)
144151
remote_connection = RemoteConnection(client_config=client_config)
145-
proxy_url = remote_connection._client_config.get_proxy_url()
146-
assert proxy_url == "https://admin:admin@http_proxy.com:8080"
152+
conn = remote_connection._get_connection_manager()
153+
assert isinstance(conn, urllib3.ProxyManager)
154+
conn.proxy_url = "http://http_proxy.com:8080"
155+
conn.connection_pool_kw["proxy_headers"] = urllib3.make_headers(proxy_basic_auth="admin:admin")
147156

148157

149158
def test_get_proxy_direct_via_client_config():
150159
client_config = ClientConfig(
151160
remote_server_addr="http://localhost:4444", proxy=Proxy({"proxyType": ProxyType.DIRECT})
152161
)
153162
remote_connection = RemoteConnection(client_config=client_config)
163+
conn = remote_connection._get_connection_manager()
164+
assert isinstance(conn, urllib3.PoolManager)
154165
proxy_url = remote_connection._client_config.get_proxy_url()
155166
assert proxy_url is None
156167

@@ -162,6 +173,8 @@ def test_get_proxy_system_matches_no_proxy_via_client_config():
162173
remote_server_addr="http://localhost:4444", proxy=Proxy({"proxyType": ProxyType.SYSTEM})
163174
)
164175
remote_connection = RemoteConnection(client_config=client_config)
176+
conn = remote_connection._get_connection_manager()
177+
assert isinstance(conn, urllib3.PoolManager)
165178
proxy_url = remote_connection._client_config.get_proxy_url()
166179
assert proxy_url is None
167180
os.environ.pop("HTTP_PROXY")

0 commit comments

Comments
 (0)