Skip to content

Commit e9c86f4

Browse files
authored
PYTHON-4463 Disallow comma character in authMechanismProperties connection string value (#1646)
1 parent 42d30b3 commit e9c86f4

File tree

6 files changed

+48
-16
lines changed

6 files changed

+48
-16
lines changed

pymongo/common.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,11 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
454454
return props
455455

456456
value = validate_string(option, value)
457+
value = unquote_plus(value)
457458
for opt in value.split(","):
458459
key, _, val = opt.partition(":")
460+
if not val:
461+
raise ValueError("Malformed auth mechanism properties")
459462
if key not in _MECHANISM_PROPS:
460463
# Try not to leak the token.
461464
if "AWS_SESSION_TOKEN" in key:
@@ -473,7 +476,7 @@ def validate_auth_mechanism_properties(option: str, value: Any) -> dict[str, Uni
473476
if key == "CANONICALIZE_HOST_NAME":
474477
props[key] = validate_boolean_or_string(key, val)
475478
else:
476-
props[key] = unquote_plus(val)
479+
props[key] = val
477480

478481
return props
479482

pymongo/uri_parser.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -494,16 +494,11 @@ def parse_uri(
494494
collection = None
495495
options = _CaseInsensitiveDictionary()
496496

497-
host_part, _, path_part = scheme_free.partition("/")
498-
if not host_part:
499-
host_part = path_part
500-
path_part = ""
501-
502-
if path_part:
503-
dbase, _, opts = path_part.partition("?")
497+
host_plus_db_part, _, opts = scheme_free.partition("?")
498+
if "/" in host_plus_db_part:
499+
host_part, _, dbase = host_plus_db_part.partition("/")
504500
else:
505-
# There was no slash in scheme_free, check for a sole "?".
506-
host_part, _, opts = host_part.partition("?")
501+
host_part = host_plus_db_part
507502

508503
if dbase:
509504
dbase = unquote_plus(dbase)

test/auth/legacy/connection-string.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@
559559
},
560560
{
561561
"description": "should handle a complicated url-encoded TOKEN_RESOURCE (MONGODB-OIDC)",
562-
"uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abc%2Cd%25ef%3Ag%26hi",
562+
"uri": "mongodb://user@localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:azure,TOKEN_RESOURCE:abcd%25ef%3Ag%26hi",
563563
"valid": true,
564564
"credential": {
565565
"username": "user",
@@ -568,7 +568,7 @@
568568
"mechanism": "MONGODB-OIDC",
569569
"mechanism_properties": {
570570
"ENVIRONMENT": "azure",
571-
"TOKEN_RESOURCE": "abc,d%ef:g&hi"
571+
"TOKEN_RESOURCE": "abcd%ef:g&hi"
572572
}
573573
}
574574
},

test/connection_string/test/valid-options.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,25 @@
3737
"options": {
3838
"tls": true
3939
}
40+
},
41+
{
42+
"description": "Colon in a key value pair",
43+
"uri": "mongodb://example.com?authMechanismProperties=TOKEN_RESOURCE:mongodb://test-cluster",
44+
"valid": true,
45+
"warning": false,
46+
"hosts": [
47+
{
48+
"type": "hostname",
49+
"host": "example.com",
50+
"port": null
51+
}
52+
],
53+
"auth": null,
54+
"options": {
55+
"authmechanismProperties": {
56+
"TOKEN_RESOURCE": "mongodb://test-cluster"
57+
}
58+
}
4059
}
4160
]
4261
}

test/connection_string/test/valid-warnings.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,21 @@
9393
],
9494
"auth": null,
9595
"options": null
96+
},
97+
{
98+
"description": "Comma in a key value pair causes a warning",
99+
"uri": "mongodb://example.com?authMechanismProperties=TOKEN_RESOURCE:mongodb://host1%2Chost2",
100+
"valid": true,
101+
"warning": true,
102+
"hosts": [
103+
{
104+
"type": "hostname",
105+
"host": "example.com",
106+
"port": null
107+
}
108+
],
109+
"auth": null,
110+
"options": null
96111
}
97112
]
98113
}

test/test_uri_parser.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -474,9 +474,9 @@ def test_normalize_options(self):
474474
res = {"tls": True, "appname": "myapp"}
475475
self.assertEqual(res, parse_uri(uri)["options"])
476476

477-
def test_unquote_after_parsing(self):
478-
quoted_val = "val%21%40%23%24%25%5E%26%2A%28%29_%2B%2C%3A+etc"
479-
unquoted_val = "val!@#$%^&*()_+,: etc"
477+
def test_unquote_during_parsing(self):
478+
quoted_val = "val%21%40%23%24%25%5E%26%2A%28%29_%2B%3A+etc"
479+
unquoted_val = "val!@#$%^&*()_+: etc"
480480
uri = (
481481
"mongodb://user:password@localhost/?authMechanism=MONGODB-AWS"
482482
"&authMechanismProperties=AWS_SESSION_TOKEN:" + quoted_val
@@ -511,7 +511,7 @@ def test_redact_AWS_SESSION_TOKEN(self):
511511
)
512512
with self.assertRaisesRegex(
513513
ValueError,
514-
"auth mechanism properties must be key:value pairs like AWS_SESSION_TOKEN:<token>",
514+
"Malformed auth mechanism properties",
515515
):
516516
parse_uri(uri)
517517

0 commit comments

Comments
 (0)