From b2f5edc5ea1d7a9bfb7d831bc9ae6126656845b5 Mon Sep 17 00:00:00 2001 From: Kiro Agent <244629292+kiro-agent@users.noreply.github.com> Date: Tue, 23 Jun 2026 11:39:07 +0000 Subject: [PATCH] feat: exclude dotted module paths from hardcoded credentials detection Strings matching the pattern of Python dotted module/class paths (e.g., 'django.contrib.auth.hashers.PBKDF2PasswordHasher') are not credentials. They are class references used in configuration settings like PASSWORD_HASHERS, AUTHENTICATION_BACKENDS, and MIDDLEWARE. --- .../Security/CWE-798/HardcodedCredentials.ql | 4 +++- .../test_module_paths.py | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test_module_paths.py diff --git a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql index 1e7b4452a9a6..a8deaafca0b3 100644 --- a/python/ql/src/Security/CWE-798/HardcodedCredentials.ql +++ b/python/ql/src/Security/CWE-798/HardcodedCredentials.ql @@ -64,7 +64,9 @@ predicate maybeCredential(ControlFlowNode f) { ) and not possible_reflective_name(str.getText()) and not capitalized_word(str) and - not format_string(str) + not format_string(str) and + /* Not a dotted Python module/class path (e.g., "django.contrib.auth.hashers.PBKDF2PasswordHasher") */ + not str.getText().regexpMatch("[a-zA-Z_][a-zA-Z0-9_]*(\\.[a-zA-Z_][a-zA-Z0-9_]*){2,}") ) or /* Or, an integer with over 32 bits */ diff --git a/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test_module_paths.py b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test_module_paths.py new file mode 100644 index 000000000000..fe4f5b1ee863 --- /dev/null +++ b/python/ql/test/query-tests/Security/CWE-798-HardcodedCredentials/test_module_paths.py @@ -0,0 +1,22 @@ +# Test that dotted module/class paths are not flagged as hardcoded credentials. +# These are commonly used in Django settings for PASSWORD_HASHERS, backends, etc. + +PASSWORD_HASHERS = [ + "django.contrib.auth.hashers.PBKDF2PasswordHasher", + "django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher", + "django.contrib.auth.hashers.Argon2PasswordHasher", +] + +AUTHENTICATION_BACKENDS = [ + "django.contrib.auth.backends.ModelBackend", + "allauth.account.auth_backends.AuthenticationBackend", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", +] + +# This should still be flagged - actual credential +def connect(): + client.connect(password="s3cr3t_passw0rd_12345") # this is a real credential