Skip to content

Commit cc3940c

Browse files
authored
FIX: security issue SEC101/037 : SQLLegacyCredentials fix (#369)
### Work Item / Issue Reference <!-- IMPORTANT: Please follow the PR template guidelines below. For mssql-python maintainers: Insert your ADO Work Item ID below (e.g. AB#37452) For external contributors: Insert Github Issue number below (e.g. #149) Only one reference is required - either GitHub issue OR ADO Work Item. --> <!-- mssql-python maintainers: ADO Work Item --> > [[AB#40951](https://sqlclientdrivers.visualstudio.com/c6d89619-62de-46a0-8b46-70b92a84d85e/_workitems/edit/40951) <!-- External contributors: GitHub Issue --> > GitHub Issue: #<ISSUE_NUMBER> ------------------------------------------------------------------- ### Summary This pull request updates several test files to improve security and consistency in database connection strings. The main change is replacing hardcoded usernames and passwords with `Trusted_Connection=yes` in all connection strings, and in some cases, using environment variables for server and database names. This prevents the exposure of credentials and avoids related security warnings. **Test connection string improvements:** * Replaced all hardcoded `UID` and `PWD` parameters in connection strings with `Trusted_Connection=yes` in `tests/test_002_types.py`, `tests/test_013_sqlwchar_conversions.py`, and `tests/test_014_ddbc_bindings_coverage.py`, enhancing security and aligning with best practices. [[1]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009L542-R546) [[2]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009L551-R555) [[3]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009L567-R571) [[4]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL43-R43) [[5]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL52-R52) [[6]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL74-R74) [[7]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL83-R83) [[8]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL114-R114) [[9]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL147-R147) [[10]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL173-R173) [[11]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL182-R182) [[12]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL191-R191) [[13]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL223-R223) [[14]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL256-R256) [[15]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL285-R285) [[16]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL304-R312) [[17]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL340-R340) [[18]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL374-R374) [[19]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL406-R406) [[20]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL418-R418) [[21]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL430-R430) [[22]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL458-R458) [[23]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL478-R478) [[24]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL493-R493) [[25]](diffhunk://#diff-6c635b84f70732583dcd72363ab4a523f912598c81ca34bd466810b3939856efL516-R516) [[26]](diffhunk://#diff-ca2a1185c9d13bb2c87e4bf15e3bf0b1b19fc9b497f9277696edaf5aed88df4cL41-R41) [[27]](diffhunk://#diff-ca2a1185c9d13bb2c87e4bf15e3bf0b1b19fc9b497f9277696edaf5aed88df4cL75-R98) [[28]](diffhunk://#diff-ca2a1185c9d13bb2c87e4bf15e3bf0b1b19fc9b497f9277696edaf5aed88df4cL126-R126) [[29]](diffhunk://#diff-ca2a1185c9d13bb2c87e4bf15e3bf0b1b19fc9b497f9277696edaf5aed88df4cL146-R146) [[30]](diffhunk://#diff-ca2a1185c9d13bb2c87e4bf15e3bf0b1b19fc9b497f9277696edaf5aed88df4cL172-R172) * Updated some tests in `tests/test_002_types.py` to use `os.getenv` for `TEST_SERVER` and `TEST_DATABASE`, allowing for configurable test environments and reducing hardcoded values. [[1]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009R534) [[2]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009L542-R546) [[3]](diffhunk://#diff-15437630102d01c37a02763e0080246da102ccedaeea931d7c433470ff0fb009L551-R555) These changes make the test suite safer to run in different environments and prevent accidental credential leaks.
1 parent d3b1229 commit cc3940c

File tree

3 files changed

+42
-35
lines changed

3 files changed

+42
-35
lines changed

tests/test_002_types.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import pytest
22
import datetime
33
import time
4+
import os
45
from mssql_python.type import (
56
STRING,
67
BINARY,
@@ -539,7 +540,10 @@ def test_invalid_surrogate_handling():
539540
# In UTF-16, high surrogates (0xD800-0xDBFF) must be followed by low surrogates
540541
try:
541542
# Create a connection string that would exercise the conversion path
542-
conn_str = "Server=test_server;Database=TestDB;UID=user;PWD=password"
543+
# Use environment variables or placeholder values to avoid SEC101/037 security warnings
544+
test_server = os.getenv("TEST_SERVER", "testserver")
545+
test_db = os.getenv("TEST_DATABASE", "TestDB")
546+
conn_str = f"Server={test_server};Database={test_db};Trusted_Connection=yes"
543547
conn = mssql_python.connect(conn_str, autoconnect=False)
544548
conn.close()
545549
except Exception:
@@ -548,7 +552,10 @@ def test_invalid_surrogate_handling():
548552
# Low surrogate without high surrogate (invalid)
549553
# In UTF-16, low surrogates (0xDC00-0xDFFF) must be preceded by high surrogates
550554
try:
551-
conn_str = "Server=test;Database=DB;ApplicationName=TestApp;UID=u;PWD=p"
555+
test_server = os.getenv("TEST_SERVER", "testserver")
556+
conn_str = (
557+
f"Server={test_server};Database=DB;ApplicationName=TestApp;Trusted_Connection=yes"
558+
)
552559
conn = mssql_python.connect(conn_str, autoconnect=False)
553560
conn.close()
554561
except Exception:
@@ -564,7 +571,7 @@ def test_invalid_surrogate_handling():
564571

565572
for test_str in emoji_tests:
566573
try:
567-
conn_str = f"Server=test;{test_str};UID=user;PWD=pass"
574+
conn_str = f"Server=test;{test_str};Trusted_Connection=yes"
568575
conn = mssql_python.connect(conn_str, autoconnect=False)
569576
conn.close()
570577
except Exception:

tests/test_013_sqlwchar_conversions.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def test_surrogate_pair_high_without_low(self):
4040
# This tests the else branch at lines 112-115
4141
try:
4242
# Use a connection string to exercise the conversion path
43-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
43+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
4444
conn = connect(conn_str, autoconnect=False)
4545
conn.close()
4646
except Exception:
@@ -49,7 +49,7 @@ def test_surrogate_pair_high_without_low(self):
4949
# High surrogate followed by non-surrogate
5050
test_str2 = "Test\ud800X" # High surrogate followed by ASCII
5151
try:
52-
conn_str = f"Server=test;ApplicationName={test_str2};UID=u;PWD=p"
52+
conn_str = f"Server=test;ApplicationName={test_str2};Trusted_Connection=yes"
5353
conn = connect(conn_str, autoconnect=False)
5454
conn.close()
5555
except Exception:
@@ -71,7 +71,7 @@ def test_surrogate_pair_low_without_high(self):
7171
test_str = "\udc00Hello" # Low surrogate at start
7272

7373
try:
74-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
74+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
7575
conn = connect(conn_str, autoconnect=False)
7676
conn.close()
7777
except Exception:
@@ -80,7 +80,7 @@ def test_surrogate_pair_low_without_high(self):
8080
# Low surrogate in middle (not preceded by high surrogate)
8181
test_str2 = "A\udc00B" # Low surrogate between ASCII
8282
try:
83-
conn_str = f"Server=test;ApplicationName={test_str2};UID=u;PWD=p"
83+
conn_str = f"Server=test;ApplicationName={test_str2};Trusted_Connection=yes"
8484
conn = connect(conn_str, autoconnect=False)
8585
conn.close()
8686
except Exception:
@@ -111,7 +111,7 @@ def test_valid_surrogate_pairs(self):
111111

112112
for test_str in emoji_tests:
113113
try:
114-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
114+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
115115
conn = connect(conn_str, autoconnect=False)
116116
conn.close()
117117
except Exception:
@@ -144,7 +144,7 @@ def test_bmp_characters(self):
144144

145145
for test_str in bmp_tests:
146146
try:
147-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
147+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
148148
conn = connect(conn_str, autoconnect=False)
149149
conn.close()
150150
except Exception:
@@ -170,7 +170,7 @@ def test_invalid_scalar_values(self):
170170
# High surrogate alone
171171
try:
172172
test_str = "Test\ud800End"
173-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
173+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
174174
conn = connect(conn_str, autoconnect=False)
175175
conn.close()
176176
except Exception:
@@ -179,7 +179,7 @@ def test_invalid_scalar_values(self):
179179
# Low surrogate alone
180180
try:
181181
test_str = "Start\udc00Test"
182-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
182+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
183183
conn = connect(conn_str, autoconnect=False)
184184
conn.close()
185185
except Exception:
@@ -188,7 +188,7 @@ def test_invalid_scalar_values(self):
188188
# Mixed invalid surrogates
189189
try:
190190
test_str = "\ud800\ud801\udc00" # High, high, low (invalid pairing)
191-
conn_str = f"Server=test;Database={test_str};UID=user;PWD=pass"
191+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
192192
conn = connect(conn_str, autoconnect=False)
193193
conn.close()
194194
except Exception:
@@ -220,7 +220,7 @@ def test_wstring_to_sqlwchar_bmp(self):
220220

221221
for test_char in single_unit_tests:
222222
try:
223-
conn_str = f"Server=test;Database=DB_{test_char};UID=u;PWD=p"
223+
conn_str = f"Server=test;Database=DB_{test_char};Trusted_Connection=yes"
224224
conn = connect(conn_str, autoconnect=False)
225225
conn.close()
226226
except Exception:
@@ -253,7 +253,7 @@ def test_wstring_to_sqlwchar_surrogate_pairs(self):
253253

254254
for emoji in emoji_chars:
255255
try:
256-
conn_str = f"Server=test;Database=DB{emoji};UID=u;PWD=p"
256+
conn_str = f"Server=test;Database=DB{emoji};Trusted_Connection=yes"
257257
conn = connect(conn_str, autoconnect=False)
258258
conn.close()
259259
except Exception:
@@ -282,7 +282,7 @@ def test_wstring_to_sqlwchar_invalid_scalars(self):
282282

283283
for test_str, desc in invalid_tests:
284284
try:
285-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
285+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
286286
conn = connect(conn_str, autoconnect=False)
287287
conn.close()
288288
except Exception:
@@ -301,15 +301,15 @@ def test_empty_and_null_strings(self):
301301

302302
# Empty string
303303
try:
304-
conn_str = "Server=test;Database=;UID=user;PWD=pass"
304+
conn_str = "Server=test;Database=;Trusted_Connection=yes"
305305
conn = connect(conn_str, autoconnect=False)
306306
conn.close()
307307
except Exception:
308308
pass
309309

310310
# Very short strings
311311
try:
312-
conn_str = "Server=a;Database=b;UID=c;PWD=d"
312+
conn_str = "Server=a;Database=b;Trusted_Connection=yes"
313313
conn = connect(conn_str, autoconnect=False)
314314
conn.close()
315315
except Exception:
@@ -337,7 +337,7 @@ def test_mixed_character_sets(self):
337337

338338
for test_str in mixed_tests:
339339
try:
340-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
340+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
341341
conn = connect(conn_str, autoconnect=False)
342342
conn.close()
343343
except Exception:
@@ -371,7 +371,7 @@ def test_boundary_code_points(self):
371371

372372
for test_char, desc in boundary_tests:
373373
try:
374-
conn_str = f"Server=test;Database=DB{test_char};UID=u;PWD=p"
374+
conn_str = f"Server=test;Database=DB{test_char};Trusted_Connection=yes"
375375
conn = connect(conn_str, autoconnect=False)
376376
conn.close()
377377
except Exception:
@@ -403,7 +403,7 @@ def test_surrogate_pair_calculations(self):
403403
# low = (0 & 0x3FF) + 0xDC00 = 0xDC00
404404
min_supp = "\U00010000"
405405
try:
406-
conn_str = f"Server=test;Database=DB{min_supp};UID=u;PWD=p"
406+
conn_str = f"Server=test;Database=DB{min_supp};Trusted_Connection=yes"
407407
conn = connect(conn_str, autoconnect=False)
408408
conn.close()
409409
except Exception:
@@ -415,7 +415,7 @@ def test_surrogate_pair_calculations(self):
415415
# low = (0xF600 & 0x3FF) + 0xDC00 = 0x200 + 0xDC00 = 0xDE00
416416
emoji = "😀"
417417
try:
418-
conn_str = f"Server=test;Database={emoji};UID=u;PWD=p"
418+
conn_str = f"Server=test;Database={emoji};Trusted_Connection=yes"
419419
conn = connect(conn_str, autoconnect=False)
420420
conn.close()
421421
except Exception:
@@ -427,7 +427,7 @@ def test_surrogate_pair_calculations(self):
427427
# low = (0xFFFFF & 0x3FF) + 0xDC00 = 0x3FF + 0xDC00 = 0xDFFF
428428
max_unicode = "\U0010ffff"
429429
try:
430-
conn_str = f"Server=test;Database=DB{max_unicode};UID=u;PWD=p"
430+
conn_str = f"Server=test;Database=DB{max_unicode};Trusted_Connection=yes"
431431
conn = connect(conn_str, autoconnect=False)
432432
conn.close()
433433
except Exception:
@@ -455,7 +455,7 @@ def test_null_terminator_handling(self):
455455

456456
for test_str in length_tests:
457457
try:
458-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
458+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
459459
conn = connect(conn_str, autoconnect=False)
460460
conn.close()
461461
except Exception:
@@ -475,7 +475,7 @@ def test_unicode_round_trip_ascii(self):
475475

476476
for test_str in ascii_tests:
477477
try:
478-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
478+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
479479
conn = connect(conn_str, autoconnect=False)
480480
conn.close()
481481
except Exception:
@@ -490,7 +490,7 @@ def test_unicode_round_trip_emoji(self):
490490

491491
for emoji in emoji_tests:
492492
try:
493-
conn_str = f"Server=test;Database=DB{emoji};UID=u;PWD=p"
493+
conn_str = f"Server=test;Database=DB{emoji};Trusted_Connection=yes"
494494
conn = connect(conn_str, autoconnect=False)
495495
conn.close()
496496
except Exception:
@@ -513,7 +513,7 @@ def test_unicode_round_trip_multilingual(self):
513513

514514
for test_str in multilingual_tests:
515515
try:
516-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
516+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
517517
conn = connect(conn_str, autoconnect=False)
518518
conn.close()
519519
except Exception:

tests/test_014_ddbc_bindings_coverage.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def test_valid_scalar_values(self):
3838

3939
for char in valid_chars:
4040
try:
41-
conn_str = f"Server=test;Database=DB{char};UID=u;PWD=p"
41+
conn_str = f"Server=test;Database=DB{char};Trusted_Connection=yes"
4242
conn = connect(conn_str, autoconnect=False)
4343
conn.close()
4444
except Exception:
@@ -72,30 +72,30 @@ def test_surrogate_range(self):
7272

7373
# Just before surrogate range (valid)
7474
try:
75-
conn_str = "Server=test;Database=DB\ud7ff;UID=u;PWD=p"
75+
conn_str = "Server=test;Database=DB\ud7ff;Trusted_Connection=yes"
7676
conn = connect(conn_str, autoconnect=False)
7777
conn.close()
7878
except Exception:
7979
pass
8080

8181
# Inside surrogate range (invalid)
8282
try:
83-
conn_str = "Server=test;Database=DB\ud800;UID=u;PWD=p"
83+
conn_str = "Server=test;Database=DB\ud800;Trusted_Connection=yes"
8484
conn = connect(conn_str, autoconnect=False)
8585
conn.close()
8686
except Exception:
8787
pass
8888

8989
try:
90-
conn_str = "Server=test;Database=DB\udfff;UID=u;PWD=p"
90+
conn_str = "Server=test;Database=DB\udfff;Trusted_Connection=yes"
9191
conn = connect(conn_str, autoconnect=False)
9292
conn.close()
9393
except Exception:
9494
pass
9595

9696
# Just after surrogate range (valid)
9797
try:
98-
conn_str = "Server=test;Database=DB\ue000;UID=u;PWD=p"
98+
conn_str = "Server=test;Database=DB\ue000;Trusted_Connection=yes"
9999
conn = connect(conn_str, autoconnect=False)
100100
conn.close()
101101
except Exception:
@@ -123,7 +123,7 @@ def test_utf32_valid_scalars(self):
123123

124124
for test_str in valid_tests:
125125
try:
126-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
126+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
127127
conn = connect(conn_str, autoconnect=False)
128128
conn.close()
129129
except Exception:
@@ -143,7 +143,7 @@ def test_utf32_invalid_scalars(self):
143143

144144
for test_str in invalid_tests:
145145
try:
146-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
146+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
147147
conn = connect(conn_str, autoconnect=False)
148148
conn.close()
149149
except Exception:
@@ -169,7 +169,7 @@ def test_utf32_encode_valid(self):
169169

170170
for test_str in valid_tests:
171171
try:
172-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
172+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
173173
conn = connect(conn_str, autoconnect=False)
174174
conn.close()
175175
except Exception:
@@ -188,7 +188,7 @@ def test_utf32_encode_invalid(self):
188188

189189
for test_str in invalid_tests:
190190
try:
191-
conn_str = f"Server=test;Database={test_str};UID=u;PWD=p"
191+
conn_str = f"Server=test;Database={test_str};Trusted_Connection=yes"
192192
conn = connect(conn_str, autoconnect=False)
193193
conn.close()
194194
except Exception:

0 commit comments

Comments
 (0)