From 9f22fff4db819f48da5bb22f5e9b2e4f94211751 Mon Sep 17 00:00:00 2001 From: yurisich Date: Tue, 26 Sep 2023 15:08:58 -0400 Subject: [PATCH 1/2] Prevent sqlalchemy's lack of url encoding from leaking passwords Switches away from using `str(engine_instance.engine)` for rendering connection strings, in order to prevent passwords containing characters such as `#` from leaking. The name of the segment will contain the password if this character is used, likely others as well. See: https://bugs.python.org/issue18140 and encode/database#145 The code in question is here: sqlalchemy/sqlalchemy/blob/aea28a9/lib/sqlalchemy/engine/url.py#L597-L630 --- aws_xray_sdk/ext/sqlalchemy_core/patch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws_xray_sdk/ext/sqlalchemy_core/patch.py b/aws_xray_sdk/ext/sqlalchemy_core/patch.py index 0551fe2b..40bbdebe 100644 --- a/aws_xray_sdk/ext/sqlalchemy_core/patch.py +++ b/aws_xray_sdk/ext/sqlalchemy_core/patch.py @@ -14,7 +14,7 @@ def _sql_meta(engine_instance, args): try: metadata = {} - url = urlparse(str(engine_instance.engine.url)) + url = urlparse(engine_instance.engine.render_as_string()) # Add Scheme to uses_netloc or // will be missing from url. uses_netloc.append(url.scheme) if url.password is None: From 249db0581f43cb2fc2101d4134707a5dd45c0cbd Mon Sep 17 00:00:00 2001 From: yurisich Date: Tue, 26 Sep 2023 15:35:23 -0400 Subject: [PATCH 2/2] Revert usage of sqlalchemy>1.4.49 method `.render_as_string()` This uses the same technique of extracting the engine url from the correctly sanitized `__str__()` representation of the engine that the `ext.sqlalchemy.util.decorators.py` module relies on, which does not leak passwords in manner outlined in 9f22fff. --- aws_xray_sdk/ext/sqlalchemy_core/patch.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aws_xray_sdk/ext/sqlalchemy_core/patch.py b/aws_xray_sdk/ext/sqlalchemy_core/patch.py index 40bbdebe..af7b86af 100644 --- a/aws_xray_sdk/ext/sqlalchemy_core/patch.py +++ b/aws_xray_sdk/ext/sqlalchemy_core/patch.py @@ -1,4 +1,5 @@ import logging +import re import sys from urllib.parse import urlparse, uses_netloc @@ -14,7 +15,7 @@ def _sql_meta(engine_instance, args): try: metadata = {} - url = urlparse(engine_instance.engine.render_as_string()) + url = urlparse(re.match(r"Engine\((.*?)\)", str(engine_instance.engine)).group(1)) # Add Scheme to uses_netloc or // will be missing from url. uses_netloc.append(url.scheme) if url.password is None: