Interactive Playground
Experiment with the vulnerable code and security rule below. Edit the code to see how the rule detects different vulnerability patterns.
pathfinder scan --ruleset python/PYTHON-DJANGO-SEC-080 --project .About This Rule
Understanding the vulnerability and how it is detected
This rule detects cases in Django applications where set_password() is called with an empty string literal ('') as the password argument, which creates user accounts with no password protection.
Django's set_password() stores a hashed version of the provided password in the database. When called with an empty string, it stores a valid hash of the empty string, meaning the account is accessible without providing any password. This is distinctly different from the correct way to create passwordless accounts: using None (which Django stores as an unusable password hash "!") or calling set_unusable_password() explicitly.
The rule uses both pattern matching (calls("*.set_password") audit) and taint analysis to catch cases where the empty string default value flows from request.POST.get('password', '') into set_password().
Security Implications
Potential attack scenarios if this vulnerability is exploited
Authentication Bypass via Empty Password
An account created with set_password('') allows anyone to log in by submitting an empty password field. Depending on the application's authentication flow, this may allow unauthorized access to admin accounts, service accounts, or user accounts created through automated workflows.
Privilege Escalation via Service Account Takeover
Service accounts or integration accounts sometimes have passwords set to empty strings during development or provisioning. If these accounts have elevated privileges (staff=True, is_superuser=True), an empty password creates a trivial privilege escalation vector for any authenticated or unauthenticated user.
Password Reset Flow Bypass
If a password reset workflow calls set_password('') as an intermediate step (e.g., to "clear" the password before sending a reset link), the account is unprotected during the time between clearing and the user setting a new password.
Automated Account Provisioning Vulnerability
Automated user provisioning scripts that create accounts with empty passwords as placeholders create a window of vulnerability. If a provisioning job runs but the user setup is never completed, the empty-password account remains accessible indefinitely.
How to Fix
Recommended remediation steps
- 1Never call set_password('') with an empty string; use set_unusable_password() when password-based login should be disabled.
- 2Use None as the password value when creating accounts that should not be accessible via password, as Django stores this as the unusable password marker.
- 3Always validate password input with validate_password() before calling set_password() to enforce minimum strength requirements.
- 4Use request.POST.get('password') without a default value (or default to None) so that missing passwords are caught as an error rather than silently set to empty.
- 5Add Django's built-in password validators in AUTH_PASSWORD_VALIDATORS settings to enforce complexity requirements application-wide.
Detection Scope
How Code Pathfinder analyzes your code for this vulnerability
This rule uses QueryType pattern matching on calls("*.set_password") to audit all set_password() call sites, specifically detecting calls where the argument is a literal empty string '' (tracked via .where() on the argument value). It also performs taint analysis to detect flows where request.POST.get('password', '') (the empty string default case) flows into set_password() without an intervening null/empty check. The .where() clause constrains matches to Python files in Django project structures.
Compliance & Standards
Industry frameworks and regulations that require detection of this vulnerability
References
External resources and documentation
Similar Rules
Explore related security rules for Python
Frequently Asked Questions
Common questions about Django Empty Password in set_password()
New feature
Get these findings posted directly on your GitHub pull requests
The Django Empty Password in set_password() rule runs in CI and posts inline review comments on the exact lines — no dashboard, no SARIF viewer.