| name | security-django |
| description | Review Django security audit patterns for settings and middleware. Use for auditing SECRET_KEY, DEBUG, CSRF, and auth decorators. Use proactively when reviewing Django apps (settings.py or manage.py present).
Examples:
- user: "Audit my Django settings.py" → check SECRET_KEY, DEBUG, and ALLOWED_HOSTS
- user: "Check Django views for auth" → verify @login_required and permission classes
- user: "Review Django CSRF config" → check middleware and @csrf_exempt usage
- user: "Scan for SQL injection in Django" → find raw SQL usage instead of ORM
- user: "Audit Django REST framework config" → check default permissions and auth |
Security audit patterns for Django applications covering critical settings, security middleware, CSRF protection, and common vulnerabilities.
Critical Settings (settings.py)
SECRET_KEY
SECRET_KEY = 'django-insecure-abc123...'
SECRET_KEY = 'my-super-secret-key'
import os
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
import environ
env = environ.Env()
SECRET_KEY = env('SECRET_KEY')
Check: Is SECRET_KEY in .env and .env is in .gitignore?
DEBUG
DEBUG = True
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'
ALLOWED_HOSTS
ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = []
ALLOWED_HOSTS = ['example.com', 'www.example.com']
Security Middleware
Required Middleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Check: Is SecurityMiddleware present and near the top?
Security Middleware Settings
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
CSRF Protection
Disabled CSRF (Critical)
MIDDLEWARE = [
]
@csrf_exempt
def payment_webhook(request):
...
@csrf_exempt
def update_profile(request):
...
Audit: Search for @csrf_exempt - each needs justification.
CSRF Trusted Origins (Django 4.0+)
CSRF_TRUSTED_ORIGINS = ['https://*']
CSRF_TRUSTED_ORIGINS = ['https://example.com', 'https://admin.example.com']
Common Vulnerabilities
SQL Injection
User.objects.raw(f"SELECT * FROM users WHERE id = {user_id}")
cursor.execute(f"DELETE FROM logs WHERE date < '{date}'")
User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id])
cursor.execute("DELETE FROM logs WHERE date < %s", [date])
User.objects.filter(id=user_id)
Command Injection
import subprocess
subprocess.run(f"convert {user_filename} output.png", shell=True)
os.system(f"process {user_input}")
subprocess.run(["convert", user_filename, "output.png"])
Path Traversal
def download(request, filename):
return FileResponse(open(f'uploads/{filename}', 'rb'))
import os
def download(request, filename):
safe_name = os.path.basename(filename)
filepath = os.path.join(settings.UPLOAD_DIR, safe_name)
if not filepath.startswith(settings.UPLOAD_DIR):
raise Http404()
return FileResponse(open(filepath, 'rb'))
IDOR (Insecure Direct Object Reference)
class DocumentView(View):
def get(self, request, doc_id):
doc = Document.objects.get(id=doc_id)
return JsonResponse(doc.to_dict())
class DocumentView(LoginRequiredMixin, View):
def get(self, request, doc_id):
doc = Document.objects.get(id=doc_id, owner=request.user)
return JsonResponse(doc.to_dict())
Auth Decorators Missing
def admin_dashboard(request):
return render(request, 'admin/dashboard.html', {'users': User.objects.all()})
@login_required
@user_passes_test(lambda u: u.is_staff)
def admin_dashboard(request):
...
Django REST Framework
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
'rest_framework.permissions.IsAuthenticated',
],
}
Quick Audit Commands
rg "(SECRET_KEY|DEBUG|ALLOWED_HOSTS)" settings*.py
rg "@csrf_exempt" . -g "*.py"
python manage.py check --deploy
rg "\.raw\(|cursor\.execute\(" . -g "*.py" -A 1
rg "(subprocess\.|os\.system|os\.popen)" . -g "*.py"
rg "^def " views.py | head -20
rg "shell\s*=\s*True" . -g "*.py"
Hardening Checklist