Snowflake Python Connector vulnerable to Command Injection
Description
The Snowflake Connector for Python provides an interface for developing Python applications that can connect to Snowflake and perform all standard operations. Versions prior to 3.0.2 are vulnerable to command injection via single sign-on(SSO) browser URL authentication. In order to exploit the potential for command injection, an attacker would need to be successful in (1) establishing a malicious resource and (2) redirecting users to utilize the resource. The attacker could set up a malicious, publicly accessible server which responds to the SSO URL with an attack payload. If the attacker then tricked a user into visiting the maliciously crafted connection URL, the user’s local machine would render the malicious payload, leading to a remote code execution. This attack scenario can be mitigated through URL whitelisting as well as common anti-phishing resources. Version 3.0.2 contains a patch for this issue.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
snowflake-connector-pythonPyPI | < 3.0.2 | 3.0.2 |
Affected products
1- Range: < 3.0.2
Patches
11cdbd3b1403cSNOW-761004 Added URL Validator and URL escaping of strings (#1480)
8 files changed · +131 −9
DESCRIPTION.md+1 −0 modified@@ -12,6 +12,7 @@ Source code is also available at: https://github.com/snowflakedb/snowflake-conne - Fixed a memory leak in the logging module of the Cython extension. - Fixed a bug where the `put` command on AWS raised `AttributeError` when the file size was larger than 200M. + - Validate SSO URL before opening it in the browser for External browser authenticator. - v3.0.1(February 28, 2023)
.pre-commit-config.yaml+1 −0 modified@@ -93,6 +93,7 @@ repos: | ssd_internal_keys | test_util | util_text + | url_util | version ).py$ additional_dependencies:
setup.py+4 −3 modified@@ -49,11 +49,13 @@ _ABLE_TO_COMPILE_EXTENSIONS = True except ImportError: - warnings.warn("Cannot compile native C code, because of a missing build dependency") + warnings.warn( + "Cannot compile native C code, because of a missing build dependency", + stacklevel=1, + ) _ABLE_TO_COMPILE_EXTENSIONS = False if _ABLE_TO_COMPILE_EXTENSIONS: - pyarrow_version = tuple(int(x) for x in pyarrow.__version__.split(".")) extensions = cythonize( [ @@ -66,7 +68,6 @@ ) class MyBuildExt(build_ext): - # list of libraries that will be bundled with python connector, # this list should be carefully examined when pyarrow lib is # upgraded
src/snowflake/connector/auth/webbrowser.py+18 −5 modified@@ -23,6 +23,7 @@ ) from ..errorcode import ( ER_IDP_CONNECTION_ERROR, + ER_INVALID_VALUE, ER_NO_HOSTNAME_FOUND, ER_UNABLE_TO_OPEN_BROWSER, ) @@ -32,6 +33,7 @@ EXTERNAL_BROWSER_AUTHENTICATOR, PYTHON_CONNECTOR_USER_AGENT, ) +from ..url_util import is_valid_url from . import Auth from .by_plugin import AuthByPlugin, AuthType @@ -131,18 +133,29 @@ def prepare( socket_connection.listen(0) # no backlog callback_port = socket_connection.getsockname()[1] + logger.debug("step 1: query GS to obtain SSO url") + sso_url = self._get_sso_url( + conn, authenticator, service_name, account, callback_port, user + ) + + logger.debug("Validate SSO URL") + if not is_valid_url(sso_url): + self._handle_failure( + conn=conn, + ret={ + "code": ER_INVALID_VALUE, + "message": (f"The SSO URL provided {sso_url} is invalid"), + }, + ) + return + print( "Initiating login request with your identity provider. A " "browser window should have opened for you to complete the " "login. If you can't see it, check existing browser windows, " "or your OS settings. Press CTRL+C to abort and try again..." ) - logger.debug("step 1: query GS to obtain SSO url") - sso_url = self._get_sso_url( - conn, authenticator, service_name, account, callback_port, user - ) - logger.debug("step 2: open a browser") print(f"Going to open: {sso_url} to authenticate...") if not self._webbrowser.open_new(sso_url):
src/snowflake/connector/snow_logging.py+1 −1 modified@@ -67,7 +67,7 @@ def warn( # type: ignore[override] warnings.warn( "The 'warn' method is deprecated, " "use 'warning' instead", DeprecationWarning, - 2, + stacklevel=2, ) self.warning(msg, path_name, func_name, *args, **kwargs)
src/snowflake/connector/url_util.py+43 −0 added@@ -0,0 +1,43 @@ +# +# Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved. +# + +from __future__ import annotations + +import re +import urllib.parse +from logging import getLogger + +logger = getLogger(__name__) + + +URL_VALIDATOR = re.compile( + "^http(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z@:])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\&\\(\\)\\/\\\\\\+&%\\$#_=@]*)?$" +) + + +def is_valid_url(url: str) -> bool: + """Confirms if the provided URL is a valid HTTP/ HTTPs URL + + Args: + url: the URL that needs to be validated + + Returns: + true/ false depending on whether the URL is valid or not + """ + return bool(URL_VALIDATOR.match(url)) + + +def url_encode_str(target: str | None) -> str: + """Converts a target string into escaped URL safe string + + Args: + target: string to be URL encoded + + Returns: + URL encoded string + """ + if target is None: + logger.debug("The string to be URL encoded is None") + return "" + return urllib.parse.quote_plus(target, safe="")
test/unit/test_auth_webbrowser.py+37 −0 modified@@ -32,6 +32,7 @@ SERVICE_NAME = "" REF_PROOF_KEY = "MOCK_PROOF_KEY" REF_SSO_URL = "https://testsso.snowflake.net/sso" +INVALID_SSO_URL = "this is an invalid URL" def mock_webserver(target_instance, application, port): @@ -318,3 +319,39 @@ class StopExecuting(Exception): account="account", auth_class=auth_inst, ) + + +def test_auth_webbrowser_invalid_sso(monkeypatch): + """Authentication by WebBrowser with failed to start web browser case.""" + rest = _init_rest(INVALID_SSO_URL, REF_PROOF_KEY) + + # mock webbrowser + mock_webbrowser = MagicMock() + mock_webbrowser.open_new.return_value = False + + # mock socket + mock_socket_instance = MagicMock() + mock_socket_instance.getsockname.return_value = [None, 12345] + + mock_socket_client = MagicMock() + mock_socket_client.recv.return_value = ( + "\r\n".join(["GET /?token=MOCK_TOKEN HTTP/1.1", "User-Agent: snowflake-agent"]) + ).encode("utf-8") + mock_socket_instance.accept.return_value = (mock_socket_client, None) + mock_socket = Mock(return_value=mock_socket_instance) + + auth = AuthByWebBrowser( + application=APPLICATION, + webbrowser_pkg=mock_webbrowser, + socket_pkg=mock_socket, + ) + auth.prepare( + conn=rest._connection, + authenticator=AUTHENTICATOR, + service_name=SERVICE_NAME, + account=ACCOUNT, + user=USER, + password=PASSWORD, + ) + assert rest._connection.errorhandler.called # an error + assert auth.assertion_content is None
test/unit/test_url_util.py+26 −0 added@@ -0,0 +1,26 @@ +# +# Copyright (c) 2012-2023 Snowflake Computing Inc. All rights reserved. +# + +try: + from snowflake.connector.url_util import is_valid_url, url_encode_str +except ImportError: + + def is_valid_url(s): + return False + + +def test_url_validator(): + assert is_valid_url("https://ssoTestURL.okta.com") + assert is_valid_url("https://ssoTestURL.okta.com:8080") + assert is_valid_url("https://ssoTestURL.okta.com/testpathvalue") + + assert not is_valid_url("-a Calculator") + assert not is_valid_url("This is a random text") + assert not is_valid_url("file://TestForFile") + + +def test_encoder(): + assert url_encode_str("Hello @World") == "Hello+%40World" + assert url_encode_str("Test//String") == "Test%2F%2FString" + assert url_encode_str(None) == ""
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-5w5m-pfw9-c8fpghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2023-34233ghsaADVISORY
- github.com/pypa/advisory-database/tree/main/vulns/snowflake-connector-python/PYSEC-2023-88.yamlghsaWEB
- github.com/snowflakedb/snowflake-connector-python/commit/1cdbd3b1403c5ef520d7f4d9614fe35165e101acghsax_refsource_MISCWEB
- github.com/snowflakedb/snowflake-connector-python/pull/1480ghsax_refsource_MISCWEB
- github.com/snowflakedb/snowflake-connector-python/security/advisories/GHSA-5w5m-pfw9-c8fpghsax_refsource_CONFIRMWEB
News mentions
0No linked articles in our index yet.