Skip to content

Commit 9c1bb99

Browse files
authored
Merge pull request #5212 from OWASP-BLT/copilot/remove-email-for-unknown-accounts
Fix: Prevent allauth from sending emails to unknown accounts during password reset
2 parents 091651b + fae255f commit 9c1bb99

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

blt/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,9 @@
345345
ACCOUNT_USERNAME_REQUIRED = True
346346
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
347347
ACCOUNT_FORMS = {"signup": "website.forms.SignupFormWithCaptcha"}
348+
# Security: Do not send emails to unknown accounts during password reset
349+
# This prevents account enumeration attacks
350+
ACCOUNT_EMAIL_UNKNOWN_ACCOUNTS = False
348351

349352
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
350353

website/tests/test_api.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,3 +239,57 @@ def test_get_userissues(self):
239239
for n in range(0, count):
240240
message = "Test is failed"
241241
self.assertTrue(response.data["results"][n].is_hidden, message)
242+
243+
244+
class TestPasswordResetUnknownEmail(APITestCase):
245+
"""Test password reset behavior for unknown email addresses"""
246+
247+
password_reset_url = "/auth/password/reset/"
248+
249+
def test_password_reset_unknown_email_no_email_sent(self):
250+
"""Test password reset with unknown email - should not send email"""
251+
# Clear the mail outbox
252+
mail.outbox = []
253+
254+
# Try to reset password for non-existent email
255+
response = self.client.post(self.password_reset_url, {"email": "nonexistent@example.com"})
256+
257+
print("\nTest: Password reset for unknown email")
258+
print(f"Response status: {response.status_code}")
259+
print(f"Response data: {response.json() if response.status_code == 200 else response.content}")
260+
print(f"Emails sent: {len(mail.outbox)}")
261+
262+
# The response should be 200 OK to not reveal account existence
263+
self.assertEqual(response.status_code, 200)
264+
265+
# But NO email should actually be sent for non-existent accounts
266+
self.assertEqual(len(mail.outbox), 0, "No email should be sent for unknown accounts")
267+
268+
print("✓ Correct: No email sent for unknown account")
269+
print("✓ Response still returns 200 OK (doesn't leak account existence)")
270+
271+
def test_password_reset_known_email_sends_email(self):
272+
"""Test password reset with known email - should send email"""
273+
# Create a user
274+
user = get_user_model().objects.create_user(
275+
username="testuser", email="testuser@example.com", password="testpass123"
276+
)
277+
278+
# Clear the mail outbox
279+
mail.outbox = []
280+
281+
# Try to reset password for existing email
282+
response = self.client.post(self.password_reset_url, {"email": "testuser@example.com"})
283+
284+
print("\nTest: Password reset for known email")
285+
print(f"Response status: {response.status_code}")
286+
print(f"Response data: {response.json() if response.status_code == 200 else response.content}")
287+
print(f"Emails sent: {len(mail.outbox)}")
288+
289+
# The response should be 200 OK
290+
self.assertEqual(response.status_code, 200)
291+
292+
# Email SHOULD be sent for existing accounts
293+
self.assertEqual(len(mail.outbox), 1, "Email should be sent for known accounts")
294+
295+
print("✓ Correct: Email sent for known account")

0 commit comments

Comments
 (0)