diff options
| -rw-r--r-- | django/contrib/auth/password_validation.py | 6 | ||||
| -rw-r--r-- | tests/auth_tests/test_validators.py | 10 |
2 files changed, 13 insertions, 3 deletions
diff --git a/django/contrib/auth/password_validation.py b/django/contrib/auth/password_validation.py index 1350dec9c8..4c26e88ac8 100644 --- a/django/contrib/auth/password_validation.py +++ b/django/contrib/auth/password_validation.py @@ -9,7 +9,7 @@ from django.core.exceptions import ( FieldDoesNotExist, ImproperlyConfigured, ValidationError, ) from django.utils.functional import lazy -from django.utils.html import format_html +from django.utils.html import format_html, format_html_join from django.utils.module_loading import import_string from django.utils.translation import gettext as _, ngettext @@ -81,8 +81,8 @@ def _password_validators_help_text_html(password_validators=None): in an <ul>. """ help_texts = password_validators_help_texts(password_validators) - help_items = [format_html('<li>{}</li>', help_text) for help_text in help_texts] - return '<ul>%s</ul>' % ''.join(help_items) if help_items else '' + help_items = format_html_join('', '<li>{}</li>', ((help_text,) for help_text in help_texts)) + return format_html('<ul>{}</ul>', help_items) if help_items else '' password_validators_help_text_html = lazy(_password_validators_help_text_html, str) diff --git a/tests/auth_tests/test_validators.py b/tests/auth_tests/test_validators.py index 068dec9981..d43efc6a3c 100644 --- a/tests/auth_tests/test_validators.py +++ b/tests/auth_tests/test_validators.py @@ -13,6 +13,7 @@ from django.core.exceptions import ValidationError from django.db import models from django.test import TestCase, override_settings from django.test.utils import isolate_apps +from django.utils.html import conditional_escape @override_settings(AUTH_PASSWORD_VALIDATORS=[ @@ -68,6 +69,15 @@ class PasswordValidationTest(TestCase): self.assertEqual(help_text.count('<li>'), 2) self.assertIn('12 characters', help_text) + def test_password_validators_help_text_html_escaping(self): + class AmpersandValidator: + def get_help_text(self): + return 'Must contain &' + help_text = password_validators_help_text_html([AmpersandValidator()]) + self.assertEqual(help_text, '<ul><li>Must contain &</li></ul>') + # help_text is marked safe and therefore unchanged by conditional_escape(). + self.assertEqual(help_text, conditional_escape(help_text)) + @override_settings(AUTH_PASSWORD_VALIDATORS=[]) def test_empty_password_validator_help_text_html(self): self.assertEqual(password_validators_help_text_html(), '') |
