This checklist covers Django-specific security configurations, Python best practices, and Heroku deployment security for Django applications.
Expedited WAF for Django
Expedited WAF adds network level request filtering, preventing malicious attacks from ever touching your application. This enables true defense in depth for your Django app—even if your framework has a vulnerability or is improperly configured, Expedited WAF dynamically blocks threats before they reach your code.
From experience, we’ve seen many applications where attacks technically didn’t succeed, but burned through so many server resources that the application went down anyway. By filtering malicious requests at the network edge, Expedited WAF protects both your security and your availability.
New Security Features for Your Django App
These capabilities aren’t available out of the box with Django, but Expedited WAF adds them instantly:
- Block IP Addresses - Stop malicious actors by IP or CIDR range
- Block User Agents - Filter out bad bots and scrapers
- Block by Geolocation - Restrict traffic by country or region
- DDoS Protection - Stop attacks with CAPTCHA challenges
- Block Anonymous Proxies - Prevent traffic from VPNs and proxy networks
Django Framework Security
Set DEBUG = False in production
- Never deploy with
DEBUG = True - Configure
DEBUG = os.environ.get('DEBUG', 'False') == 'True' - Verify with
heroku config:get DEBUG
- Never deploy with
Configure SECRET_KEY securely
- Store in Heroku config vars:
heroku config:set SECRET_KEY='your-secret-key' - Never commit to version control
- Use cryptographically strong random string (50+ characters)
- Rotate periodically
- Store in Heroku config vars:
Set ALLOWED_HOSTS properly
- Add your Heroku app domain:
['yourapp.herokuapp.com'] - Include custom domains if configured
- Never use
ALLOWED_HOSTS = ['*']in production
- Add your Heroku app domain:
Enable CSRF protection
- Ensure
django.middleware.csrf.CsrfViewMiddlewareis enabled - Use
{% csrf_token %}in all forms - Configure
CSRF_COOKIE_SECURE = Truefor HTTPS - Set
CSRF_COOKIE_HTTPONLY = True
- Ensure
Configure secure session cookies
SESSION_COOKIE_SECURE = True # HTTPS only SESSION_COOKIE_HTTPONLY = True # No JavaScript access SESSION_COOKIE_SAMESITE = 'Strict' SESSION_COOKIE_AGE = 1209600 # 2 weeks maxEnable XSS protection middleware
SecurityMiddlewareshould be first in MIDDLEWARE- Set
SECURE_BROWSER_XSS_FILTER = True - Set
SECURE_CONTENT_TYPE_NOSNIFF = True
Configure HTTPS/SSL settings
SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_HSTS_SECONDS = 31536000 # 1 year SECURE_HSTS_INCLUDE_SUBDOMAINS = True SECURE_HSTS_PRELOAD = TrueImplement Content Security Policy (CSP)
- Install django-csp:
pip install django-csp - Configure restrictive CSP headers
- Test with report-only mode first
- Install django-csp:
Disable clickjacking
- Ensure
XFrameOptionsMiddlewareis enabled - Set
X_FRAME_OPTIONS = 'DENY'
- Ensure
Database Security
Use Heroku Postgres with SSL
- Configure
DATABASESto require SSL:
DATABASES['default'] = dj_database_url.config( conn_max_age=600, ssl_require=True )- Configure
Never log SQL queries in production
- Set appropriate logging levels
- Disable Django Debug Toolbar in production
Use parameterized queries
- Always use Django ORM or parameterized raw queries
- Never string concatenation for SQL
Implement database connection pooling
- Set
conn_max_age=600for persistent connections - Monitor connection usage
- Set
Authentication & Authorization
Use Django’s authentication system
- Don’t roll your own authentication
- Use
django.contrib.auth
Enforce strong password requirements
AUTH_PASSWORD_VALIDATORS = [ {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'}, {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 'OPTIONS': {'min_length': 12}}, {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'}, {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}, ]Implement rate limiting
- Install django-ratelimit:
pip install django-ratelimit - Apply to login, password reset, API endpoints
- How to Block User Agents on Heroku
- Install django-ratelimit:
Use Django’s permission system
- Implement proper
@permission_requireddecorators - Use
LoginRequiredMixinfor class-based views - Never rely on client-side authorization
- Implement proper
Configure password reset security
- Set short token expiration:
PASSWORD_RESET_TIMEOUT = 3600# 1 hour - Use HTTPS for reset emails
- Set short token expiration:
Static Files & Media
Serve static files securely
- Use WhiteNoise for static files:
pip install whitenoise - Configure in settings:
MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', # ... ] STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'- Use WhiteNoise for static files:
Store media files on S3/external storage
- Never store uploads on Heroku’s ephemeral filesystem
- Use django-storages with S3
- Validate file uploads (type, size, content)
Sanitize user uploads
- Validate file extensions and MIME types
- Scan for malware if possible
- Generate unique filenames
- Set appropriate permissions
Python Dependencies
Pin all dependency versions
- Use
requirements.txtwith exact versions - Run
pip freeze > requirements.txt - Review dependencies before updating
- Use
Scan for vulnerabilities
- Use
pip-auditorsafety:pip install pip-audit - Run
pip-auditin CI/CD pipeline - Keep dependencies updated
- Use
Remove unused dependencies
- Minimize attack surface
- Use
pipdeptreeto identify unused packages
Environment Variables & Secrets
Store all secrets in Heroku config vars
heroku config:set SECRET_KEY='...' heroku config:set DATABASE_URL='...' heroku config:set AWS_ACCESS_KEY_ID='...'Never commit secrets to Git
- Use
.gitignorefor local.envfiles - Use
python-decouplefor local development - Audit commits for leaked secrets
- Use
Rotate credentials regularly
- Database passwords
- API keys
- SECRET_KEY
Logging & Monitoring
Configure structured logging
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'root': { 'handlers': ['console'], 'level': 'INFO', }, }Log security events
- Failed login attempts
- Permission denials
- Suspicious activity
Never log sensitive data
- Passwords
- API keys
- Personal information
- Credit card numbers
Monitor application metrics
- Set up Heroku application metrics
- Configure alerts for anomalies
- Monitor error rates
Heroku Deployment
Configure Heroku runtime
- Specify Python version in
runtime.txt - Use supported Python versions only
- Keep runtime updated
- Specify Python version in
Use Procfile best practices
web: gunicorn myproject.wsgi --log-file -- Use production WSGI server (Gunicorn, uWSGI)
- Configure appropriate workers
- Enable access logs
API Security (Django REST Framework)
Implement authentication
- Use Token or JWT authentication
- Never rely on session auth for public APIs
- Rotate tokens regularly
Configure throttling
REST_FRAMEWORK = { 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ], 'DEFAULT_THROTTLE_RATES': { 'anon': '100/hour', 'user': '1000/hour' } }Validate all input
- Use serializers for validation
- Never trust client input
- Sanitize output
Implement CORS properly
- Install django-cors-headers
- Configure allowed origins explicitly
- Never use
CORS_ORIGIN_ALLOW_ALL = True
Compliance & Best Practices
Run Django’s security check
python manage.py check --deploy- Fix all warnings before deployment
Implement GDPR compliance
- Data retention policies
- User data export/deletion
- Privacy policy
- Cookie consent
Regular security audits
- Code reviews
- Dependency audits
- Penetration testing
Keep Django updated
- Subscribe to security mailing list
- Apply security patches promptly
- Test updates in staging first
Testing
Write security tests
- Test authentication/authorization
- Test CSRF protection
- Test input validation
- Test permission boundaries
Test on Heroku staging environment
- Create staging app:
heroku create myapp-staging - Test all security configurations
- Verify HTTPS enforcement
- Create staging app:
Additional Resources
- Django Security Documentation
- Django Deployment Checklist
- OWASP Django Security Cheat Sheet
- Heroku Django Documentation