Skip to content

Commit 65fd98c

Browse files
committed
Add test_logging_security.py (from PR tortoise#1997)
1 parent ebc28bf commit 65fd98c

1 file changed

Lines changed: 100 additions & 0 deletions

File tree

tests/test_logging_security.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
"""Test that sensitive data is not exposed in debug logging."""
2+
3+
import logging
4+
from io import StringIO
5+
6+
from tests.testmodels import User
7+
from tortoise.contrib.test import TestCase
8+
9+
10+
class TestLoggingSecurity(TestCase):
11+
"""Test cases for ensuring sensitive data is not logged by Tortoise ORM."""
12+
13+
async def test_query_parameters_not_logged_in_tortoise_db_client(self):
14+
"""Test that query parameters are not logged by tortoise.db_client logger."""
15+
# Create a string IO to capture log output
16+
log_capture = StringIO()
17+
18+
# Get the tortoise db_client logger and add our handler
19+
logger = logging.getLogger("tortoise.db_client")
20+
original_level = logger.level
21+
handler = logging.StreamHandler(log_capture)
22+
handler.setLevel(logging.DEBUG)
23+
formatter = logging.Formatter("%(name)s:%(levelname)s:%(message)s")
24+
handler.setFormatter(formatter)
25+
26+
# Set up logging
27+
logger.setLevel(logging.DEBUG)
28+
logger.addHandler(handler)
29+
30+
try:
31+
# Create a user with potentially sensitive data
32+
sensitive_email = "admin@secret-company.com"
33+
sensitive_username = "admin_with_secret_key_123"
34+
sensitive_bio = "bio with password: my_secret_password_123"
35+
36+
user = await User.create(
37+
username=sensitive_username, mail=sensitive_email, bio=sensitive_bio
38+
)
39+
40+
# Get the captured log output
41+
log_output = log_capture.getvalue()
42+
43+
# Verify that the SQL query structure is still logged
44+
self.assertIn("INSERT INTO", log_output)
45+
self.assertIn("user", log_output.lower())
46+
47+
# Verify that sensitive data is NOT in the log output
48+
self.assertNotIn(
49+
sensitive_email, log_output, f"Sensitive email found in log output: {log_output}"
50+
)
51+
self.assertNotIn(
52+
sensitive_username,
53+
log_output,
54+
f"Sensitive username found in log output: {log_output}",
55+
)
56+
self.assertNotIn(
57+
sensitive_bio, log_output, f"Sensitive bio found in log output: {log_output}"
58+
)
59+
self.assertNotIn(
60+
"my_secret_password_123",
61+
log_output,
62+
f"Sensitive password found in log output: {log_output}",
63+
)
64+
65+
# Test UPDATE operation
66+
log_capture.seek(0) # Reset the capture
67+
log_capture.truncate(0)
68+
69+
new_sensitive_email = "super_secret_admin@classified.gov"
70+
user.mail = new_sensitive_email
71+
await user.save()
72+
73+
log_output = log_capture.getvalue()
74+
self.assertNotIn(
75+
new_sensitive_email,
76+
log_output,
77+
f"Sensitive email found in UPDATE log: {log_output}",
78+
)
79+
80+
# Test SELECT operation
81+
log_capture.seek(0) # Reset the capture
82+
log_capture.truncate(0)
83+
84+
await User.filter(username=sensitive_username).first()
85+
86+
log_output = log_capture.getvalue()
87+
self.assertNotIn(
88+
sensitive_username,
89+
log_output,
90+
f"Sensitive username found in SELECT log: {log_output}",
91+
)
92+
93+
# Clean up
94+
await user.delete()
95+
96+
finally:
97+
# Restore original logging setup
98+
logger.removeHandler(handler)
99+
logger.setLevel(original_level)
100+
handler.close()

0 commit comments

Comments
 (0)