CVE-2023-22451: Weak Password Requirements (CWE-521)
value: Kiwi TCMS is an open source test management system. In version 11.6 and prior, when users register new accounts and/or change passwords, there is no validation in place which would prevent them from picking an easy to guess password. This issue is resolved by providing defaults for the `AUTH_PASSWORD_VALIDATORS` configuration setting. As of version 11.7, the password can’t be too similar to other personal information, must contain at least 10 characters, can’t be a commonly used password, and can’t be entirely numeric. As a workaround, an administrator may reset all passwords in Kiwi TCMS if they think a weak password may have been chosen.
CWE description: The product does not require that users should have strong passwords, which makes it easier for attackers to compromise user accounts.
CVSS v3 base score: 8.8
Published: 2023-01-02T16:15Z
Repository: https://github.com/kiwitcms/Kiwi
Language: Python
Files changed: tcms/kiwi_auth/tests/__init__.py, tcms/kiwi_auth/tests/test_admin.py, tcms/kiwi_auth/tests/test_forms.py, tcms/kiwi_auth/tests/test_views.py
Commit date: 2023-01-01 13:00:15 +0000
Commit message: Update tests to use a stronger password

Diff: diff --git a/tcms/kiwi_auth/tests/__init__.py b/tcms/kiwi_auth/tests/__init__.py
index e69de29b..189ba95a 100644
--- a/tcms/kiwi_auth/tests/__init__.py
+++ b/tcms/kiwi_auth/tests/__init__.py
@@ -0,0 +1 @@
+__FOR_TESTING__ = "5a5b6e17f9c34025a75b052fc06c50ab"
diff --git a/tcms/kiwi_auth/tests/test_admin.py b/tcms/kiwi_auth/tests/test_admin.py
index fe16cc27..bfc8bf42 100644
--- a/tcms/kiwi_auth/tests/test_admin.py
+++ b/tcms/kiwi_auth/tests/test_admin.py
@@ -9,10 +9,12 @@ from django.utils.translation import gettext_lazy as _
 
 from tcms.kiwi_auth.admin import Group
 from tcms.tests import LoggedInTestCase, user_should_have_perm
 from tcms.tests.factories import GroupFactory, UserFactory
 
+from . import __FOR_TESTING__
+
 
 class TestUserAdmin(LoggedInTestCase):  # pylint: disable=too-many-public-methods
     @classmethod
     def setUpTestData(cls):
         # Note: by default the logged-in user is self.tester
@@ -63,12 +65,12 @@ class TestUserAdmin(LoggedInTestCase):  # pylint: disable=too-many-public-method
 
         response = self.client.post(
             "/admin/auth/user/add/",
             {
                 "username": "added-by-admin",
-                "password1": "xo-xo-xo",
-                "password2": "xo-xo-xo",
+                "password1": __FOR_TESTING__,
+                "password2": __FOR_TESTING__,
             },
             follow=True,
         )
         self.assertEqual(HTTPStatus.OK, response.status_code)
         self.assertTrue(
@@ -223,12 +225,12 @@ class TestUserAdmin(LoggedInTestCase):  # pylint: disable=too-many-public-method
 
         response = self.client.post(
             "/admin/auth/user/add/",
             {
                 "username": "added-by-moderator",
-                "password1": "xo-xo-xo",
-                "password2": "xo-xo-xo",
+                "password1": __FOR_TESTING__,
+                "password2": __FOR_TESTING__,
             },
             follow=True,
         )
         self.assertEqual(HTTPStatus.OK, response.status_code)
         self.assertTrue(
@@ -371,12 +373,12 @@ class TestUserAdmin(LoggedInTestCase):  # pylint: disable=too-many-public-method
 
         response = self.client.post(
             "/admin/auth/user/add/",
             {
                 "username": "added-by-regular-user",
-                "password1": "xo-xo-xo",
-                "password2": "xo-xo-xo",
+                "password1": __FOR_TESTING__,
+                "password2": __FOR_TESTING__,
             },
             follow=True,
         )
         self.assertEqual(HTTPStatus.FORBIDDEN, response.status_code)
         self.assertFalse(
diff --git a/tcms/kiwi_auth/tests/test_forms.py b/tcms/kiwi_auth/tests/test_forms.py
index 72f3d5ab..ba26d8d2 100644
--- a/tcms/kiwi_auth/tests/test_forms.py
+++ b/tcms/kiwi_auth/tests/test_forms.py
@@ -3,17 +3,19 @@ import importlib
 from django.test import TestCase, override_settings
 from django.utils.translation import gettext_lazy as _
 
 from tcms.kiwi_auth import forms
 
+from . import __FOR_TESTING__
+
 
 class TestCaptchaField(TestCase):
     def setUp(self):
         self.data = {
             "username": "test_user",
-            "password1": "password",
-            "password2": "password",
+            "password1": __FOR_TESTING__,
+            "password2": __FOR_TESTING__,
             "email": "new-tester@example.com",
         }
 
     def test_captcha_required_when_enabled(self):
         importlib.reload(forms)
@@ -47,12 +49,12 @@ class TestCaptchaField(TestCase):
 @override_settings(USE_CAPTCHA=False)
 class TestRegistrationForm(TestCase):
     def setUp(self):
         self.data = {
             "username": "test_user",
-            "password1": "password",
-            "password2": "password",
+            "password1": __FOR_TESTING__,
+            "password2": __FOR_TESTING__,
             "email": "new-tester@example.com",
         }
 
     def test_user_not_created_when_commit(self):
         importlib.reload(forms)
diff --git a/tcms/kiwi_auth/tests/test_views.py b/tcms/kiwi_auth/tests/test_views.py
index 3a7a6c4f..6ec240cc 100644
--- a/tcms/kiwi_auth/tests/test_views.py
+++ b/tcms/kiwi_auth/tests/test_views.py
@@ -15,10 +15,12 @@ from mock import patch
 from tcms import signals
 from tcms.kiwi_auth import forms
 from tcms.kiwi_auth.models import UserActivationKey
 from tcms.tests.factories import UserFactory
 
+from . import __FOR_TESTING__
+
 User = get_user_model()  # pylint: disable=invalid-name
 
 
 class TestSetRandomKey(TestCase):
     """Test case for UserActivationKey.set_random_key_for_user"""
@@ -115,12 +117,12 @@ class TestRegistration(TestCase):
 
                 response = self.client.post(
                     self.register_url,
                     {
                         "username": username,
-                        "password1": "password",
-                        "password2": "password",
+                        "password1": __FOR_TESTING__,
+                        "password2": __FOR_TESTING__,
                         "email": "new-tester@example.com",
                         "captcha_0": "PASSED",
                         "captcha_1": "PASSED",
                     },
                     follow=follow,
@@ -252,12 +254,12 @@ To activate your account, click this link:
     def test_invalid_form(self):
         response = self.client.post(
             self.register_url,
             {
                 "username": "kiwi-tester",
-                "password1": "password-1",
-                "password2": "password-2",
+                "password1": __FOR_TESTING__,
+                "password2": f"000-{__FOR_TESTING__}",
                 "email": "new-tester@example.com",
             },
             follow=False,
         )
 
@@ -270,12 +272,12 @@ To activate your account, click this link:
 
         response = self.client.post(
             self.register_url,
             {
                 "username": "test_user",
-                "password1": "password",
-                "password2": "password",
+                "password1": __FOR_TESTING__,
+                "password2": __FOR_TESTING__,
                 "email": "new-tester@example.com",
             },
             follow=False,
         )
         self.assertContains(response, _("A user with that email already exists."))

Vulnerable code:                 "password1": "xo-xo-xo",
                "password2": "xo-xo-xo",
                "password1": "xo-xo-xo",
                "password2": "xo-xo-xo",
                "password1": "xo-xo-xo",
                "password2": "xo-xo-xo",
            "password1": "password",
            "password2": "password",
            "password1": "password",
            "password2": "password",
                        "password1": "password",
                        "password2": "password",
                "password1": "password-1",
                "password2": "password-2",
                "password1": "password",
                "password2": "password",
Fixed code: __FOR_TESTING__ = "5a5b6e17f9c34025a75b052fc06c50ab"
from . import __FOR_TESTING__

                "password1": __FOR_TESTING__,
                "password2": __FOR_TESTING__,
                "password1": __FOR_TESTING__,
                "password2": __FOR_TESTING__,
                "password1": __FOR_TESTING__,
                "password2": __FOR_TESTING__,
from . import __FOR_TESTING__

            "password1": __FOR_TESTING__,
            "password2": __FOR_TESTING__,
            "password1": __FOR_TESTING__,
            "password2": __FOR_TESTING__,
from . import __FOR_TESTING__

                        "password1": __FOR_TESTING__,
                        "password2": __FOR_TESTING__,
                "password1": __FOR_TESTING__,
                "password2": f"000-{__FOR_TESTING__}",
                "password1": __FOR_TESTING__,
                "password2": __FOR_TESTING__,