Django Security Checklist: 10 Steps to Bulletproof Your DjangoWeb App

I have been working with Django for the past five years, and my journey with it continues. Django is one of the most secure web frameworks…

Django Security Checklist: 10 Steps to Bulletproof Your DjangoWeb App
Photo by Velizar Ivanov on Unsplash

I have been working with Django for the past five years, and my journey with it continues. Django is one of the most secure web frameworks available. In this guide, we will dive deep into a 10-step security checklist that will help you strengthen your Django application against potential attacks.


1. Keep Your Django Version Up to Date

Django regularly releases security patches — ensure you’re always on the latest LTS (Long-Term Support) version.

Check your version:

python -m django --version
You can follow the official docs to get the latest version https://www.djangoproject.com/download/

2. Set DEBUG = False in Production

If you are leaving DEBUG = True in your settings file it can exposes sensitive error messages.

Update settings.py:

# settings.py 
DEBUG = False 
ALLOWED_HOSTS = ['yourdomain.com']

3. Secure Your Secret Key

The SECRET_KEY is critical for cryptographic signing—never hardcode it in your settings file.

Use environment variables or a .env file:

DJANGO_SECRET_KEY='your-secure-key'

Use django-environ to manage secrets easily:

pip install django-environ
# settings.py 
import environ 
import os 
 
env = environ.Env() 
 
SECRET_KEY = env('SECRET_KEY')

4. Use a Strong Password Hasher

The Default password hashing is PBKDF2, but Argon2 is more secure.

Update settings.py:

# settings.py 
PASSWORD_HASHERS = [ 
    'django.contrib.auth.hashers.Argon2PasswordHasher', 
]

5. Enable HTTPS with SECURE_* Settings

Always serve your app over HTTPS to prevent MITM attacks.

Update settings.py:

SECURE_SSL_REDIRECT = True 
SESSION_COOKIE_SECURE = True 
CSRF_COOKIE_SECURE = True

6. Protect Against Clickjacking & XSS Attacks

Use CSP headers and frame protection.

Update settings.py:

X_FRAME_OPTIONS = 'DENY' 
SECURE_BROWSER_XSS_FILTER = True 
CSP_DEFAULT_SRC = ("'self'",)

You can use django-csp for fine-grained CSP policies.

pip install django-csp
# settings.py 
from csp.constants import NONE, SELF 
 
INSTALLED_APPS = [ 
    "csp" 
] 
 
MIDDLEWARE = ( 
    "csp.middleware.CSPMiddleware", 
) 
 
# The CONTENT_SECURITY_POLICY setting is your enforceable policy. 
CONTENT_SECURITY_POLICY = { 
    "EXCLUDE_URL_PREFIXES": ["/excluded-path/"], 
    "DIRECTIVES": { 
        "default-src": [SELF, "cdn.example.net"], 
        "frame-ancestors": [SELF], 
        "form-action": [SELF], 
        "report-uri": "/csp-report/", 
    }, 
} 
 
# The CONTENT_SECURITY_POLICY_REPORT_ONLY setting is your report-only policy. 
# This policy is used to test the policy without breaking the site.  
# It is useful when setting this policy to be slightly more strict than  
# the default policy to see what would be blocked if the policy was enforced. 
 
CONTENT_SECURITY_POLICY_REPORT_ONLY = { 
    "EXCLUDE_URL_PREFIXES": ["/excluded-path/"], 
    "DIRECTIVES": { 
        "default-src": [NONE], 
        "connect-src": [SELF], 
        "img-src": [SELF], 
        "form-action": [SELF], 
        "frame-ancestors": [SELF], 
        "script-src": [SELF], 
        "style-src": [SELF], 
        "upgrade-insecure-requests": True, 
        "report-uri": "/csp-report/", 
    }, 
}

7. Prevent SQL Injection

Never concatenate raw SQL queries — always use Django ORM.

Safe query:

User.objects.filter(email=email).first()

Unsafe (Don’t do this!):

cursor.execute(f"SELECT * FROM users WHERE email = '{email}'")  # ❌ SQL Injection risk

8. Restrict File Uploads

Prevent malicious file uploads.

Update settings.py:

FILE_UPLOAD_PERMISSIONS = 0o640

Use django-storages for cloud-based storage.

9. Use Django’s Built-in Security Middleware

Django provides middleware for various security measures — ensure they are enabled.

Check settings.py:

# settings.py 
MIDDLEWARE = [ 
    'django.middleware.security.SecurityMiddleware', 
    'django.middleware.csrf.CsrfViewMiddleware', 
    'django.middleware.clickjacking.XFrameOptionsMiddleware', 
]

10. Enable Logging & Monitoring

Monitor your app for suspicious activity and security breaches.

Configure logging in settings.py:

# settings.py 
LOGGING = { 
    'version': 1, 
    'handlers': { 
        'file': { 
            'level': 'ERROR', 
            'class': 'logging.FileHandler', 
            'filename': 'django_errors.log', 
        }, 
    }, 
    'loggers': { 
        'django': { 
            'handlers': ['file'], 
            'level': 'ERROR', 
            'propagate': True, 
        }, 
    }, 
}

You can use Sentry for real-time error tracking.

Final Thoughts

Implementing these 10 security best practices will protect your Django app against common attacks and make your Django app bulletproof.

Next Steps:

Run Django’s security check before deployment:

python manage.py check --deploy

Use penetration testing tools like ZAP

Which security step do you always follow? Drop a comment below! 🚀