These Django-specific OWASP security guidelines provide a practical framework for building secure web applications using the Django framework. Aligned with the OWASP Top 10, they highlight common security risks and demonstrate how Django’s built-in features and recommended best practices can be used to prevent vulnerabilities such as injection attacks, broken authentication, cross-site scripting, and security misconfiguration. Following these guidelines helps developers design, develop, and deploy Django applications that are secure, reliable, and compliant with modern web security standards.
Below are Django-specific OWASP security guidelines, mapped directly to Django features and best practices. This is suitable for real-world development, production hardening, and interviews.
1. Access Control (Broken Access Control)
Use Django permissions properly
-
Use
@login_required,@permission_required -
Enforce object-level permissions manually or via libraries (e.g., django-guardian)
-
Never trust client-side checks
@login_required
def view_invoice(request, id):
invoice = get_object_or_404(Invoice, id=id, user=request.user)
Best Practices
-
Deny by default
-
Avoid exposing primary keys directly (use UUIDs if possible)
2. Authentication & Session Security
Settings
AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
]
Session & Cookie Security
SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True SESSION_COOKIE_HTTPONLY = True
Recommendations
-
Use Django’s built-in authentication system
-
Implement MFA using packages like
django-otp -
Protect against brute force (rate limiting)
3. CSRF Protection
Enable CSRF middleware (default)
'django.middleware.csrf.CsrfViewMiddleware',
Templates
<form method="post">
{% csrf_token %}
</form>
For APIs
-
Use token-based auth (JWT)
-
Do not disable CSRF globally
4. SQL Injection Prevention
Use Django ORM
User.objects.filter(email=email)
Avoid
cursor.execute(f"SELECT * FROM users WHERE email='{email}'") # ❌
Raw SQL (only if needed)
cursor.execute("SELECT * FROM users WHERE email = %s", [email])
5. XSS Protection
Django auto-escapes templates
{{ user_input }} <!-- Safe by default -->
Avoid
{{ user_input|safe }} <!-- ❌ unless trusted -->
Security Headers
SECURE_BROWSER_XSS_FILTER = True X_FRAME_OPTIONS = 'DENY'
6. Secure File Uploads
Validate files
def validate_file_size(file):
if file.size > 5 * 1024 * 1024:
raise ValidationError("File too large")
Recommendations
-
Validate MIME type
-
Store uploads outside the web root
-
Never trust file extensions
7. Security Misconfiguration
Production Settings
DEBUG = False ALLOWED_HOSTS = ['example.com']
Environment Variables
SECRET_KEY = os.getenv('DJANGO_SECRET_KEY')
Remove
-
Debug pages
-
Test endpoints
-
Unused apps
8. HTTPS & Transport Security
SECURE_SSL_REDIRECT = True SECURE_HSTS_SECONDS = 31536000 SECURE_HSTS_INCLUDE_SUBDOMAINS = True
Use
-
Nginx + TLS
-
HSTS
-
Strong ciphers
9. Logging & Monitoring
LOGGING = {
'version': 1,
'handlers': {
'file': {
'class': 'logging.FileHandler',
'filename': '/var/log/django/security.log',
},
},
}
Log
-
Login attempts
-
Permission failures
-
Suspicious requests
Never log
-
Passwords
-
Tokens
-
Secrets
10. Dependency & Supply-Chain Security
Best Practices
-
Pin versions in
requirements.txt -
Use
pip-auditorsafety -
Update Django regularly
pip-audit
11. API Security (Django REST Framework)
Authentication
-
JWT (
SimpleJWT) -
Token expiration & rotation
Permissions
permission_classes = [IsAuthenticated]
Rate Limiting
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.UserRateThrottle',
],
'DEFAULT_THROTTLE_RATES': {
'user': '1000/day',
},
}
12. Prevent SSRF
-
Validate external URLs
-
Whitelist domains
-
Disable unnecessary outbound requests
Django Security Checklist (Quick)
-
DEBUG = False
-
CSRF enabled
-
HTTPS enforced
-
Secure cookies
-
ORM used
-
Permissions enforced
-
Secrets in env variables
-
Dependencies updated
-
Logging enabled