Agent Skill
2/7/2026

security-django

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

J
justinlevinedotme
6GitHub Stars
1Views
npx skills add justinlevinedotme/jalco-opencode

SKILL.md

Namesecurity-django
DescriptionReview 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

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

<overview>

Security audit patterns for Django applications covering critical settings, security middleware, CSRF protection, and common vulnerabilities.

</overview> <rules>

Critical Settings (settings.py)

SECRET_KEY

# CRITICAL: Hardcoded or committed - MUST NOT do this
SECRET_KEY = 'django-insecure-abc123...'
SECRET_KEY = 'my-super-secret-key'

# MUST load from environment
import os
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']

# MAY use django-environ
import environ
env = environ.Env()
SECRET_KEY = env('SECRET_KEY')

MUST check: Is SECRET_KEY in .env and .env is in .gitignore?

DEBUG

# CRITICAL: Debug in production - MUST NOT do this
DEBUG = True  # Exposes full stack traces, settings, SQL queries

# MUST be environment-controlled
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'

ALLOWED_HOSTS

# CRITICAL: Accept any host - MUST NOT do this
ALLOWED_HOSTS = ['*']

# HIGH: Empty in production (500 errors, but still bad)
ALLOWED_HOSTS = []

# MUST use explicit hosts
ALLOWED_HOSTS = ['example.com', 'www.example.com']

Security Middleware

Required Middleware

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',  # MUST be first!
    # ...
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

MUST check: Is SecurityMiddleware present and near the top?

Security Middleware Settings

# SHOULD enable these in production
SECURE_BROWSER_XSS_FILTER = True  # Deprecated but harmless
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_HSTS_SECONDS = 31536000  # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_SSL_REDIRECT = True  # Force HTTPS
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
</rules> <vulnerabilities>

CSRF Protection

Disabled CSRF (Critical)

# CRITICAL: Globally disabled - MUST NOT do this
MIDDLEWARE = [
    # 'django.middleware.csrf.CsrfViewMiddleware',  # Commented out!
]

# HIGH: Decorator abuse
@csrf_exempt
def payment_webhook(request):  # MAY be OK for webhooks with other auth
    ...

@csrf_exempt
def update_profile(request):  # MUST NOT do this!
    ...

Audit: MUST search for @csrf_exempt - each needs justification.

CSRF Trusted Origins (Django 4.0+)

# Too permissive - MUST NOT do this
CSRF_TRUSTED_ORIGINS = ['https://*']

# MUST be explicit
CSRF_TRUSTED_ORIGINS = ['https://example.com', 'https://admin.example.com']

Common Vulnerabilities

SQL Injection

# Raw SQL with string formatting - MUST NOT do this
User.objects.raw(f"SELECT * FROM users WHERE id = {user_id}")
cursor.execute(f"DELETE FROM logs WHERE date < '{date}'")

# MUST use parameterized queries
User.objects.raw("SELECT * FROM users WHERE id = %s", [user_id])
cursor.execute("DELETE FROM logs WHERE date < %s", [date])

# SHOULD use ORM (safe by default)
User.objects.filter(id=user_id)

Command Injection

# User input in subprocess - MUST NOT do this
import subprocess
subprocess.run(f"convert {user_filename} output.png", shell=True)
os.system(f"process {user_input}")

# MUST use arrays, avoid shell=True
subprocess.run(["convert", user_filename, "output.png"])

Path Traversal

# User-controlled path - MUST NOT do this
def download(request, filename):
    return FileResponse(open(f'uploads/{filename}', 'rb'))

# MUST validate path
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)

# No ownership check - MUST NOT do this
class DocumentView(View):
    def get(self, request, doc_id):
        doc = Document.objects.get(id=doc_id)
        return JsonResponse(doc.to_dict())

# MUST check ownership
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

# No auth required - MUST NOT do this
def admin_dashboard(request):
    return render(request, 'admin/dashboard.html', {'users': User.objects.all()})

# MUST require auth
@login_required
@user_passes_test(lambda u: u.is_staff)
def admin_dashboard(request):
    ...

Django REST Framework

# MUST check DRF settings
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # SessionAuth without CSRF = vulnerable
        'rest_framework.authentication.SessionAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        # Allow any by default - SHOULD NOT do this
        'rest_framework.permissions.AllowAny',
        # SHOULD require auth by default
        'rest_framework.permissions.IsAuthenticated',
    ],
}
</vulnerabilities> <commands>

Quick Audit Commands

# Check critical settings
rg "(SECRET_KEY|DEBUG|ALLOWED_HOSTS)" settings*.py

# Find csrf_exempt usage
rg "@csrf_exempt" . -g "*.py"

# Django deployment checklist (high signal)
python manage.py check --deploy

# Find raw SQL
rg "\.raw\(|cursor\.execute\(" . -g "*.py" -A 1

# Find subprocess/os.system
rg "(subprocess\.|os\.system|os\.popen)" . -g "*.py"

# Check for missing login_required
rg "^def " views.py | head -20  # Then check which have decorators

# Find shell=True
rg "shell\s*=\s*True" . -g "*.py"
</commands> <checklist>

Hardening Checklist

  • SECRET_KEY MUST be from environment, not hardcoded
  • DEBUG MUST be False in production
  • ALLOWED_HOSTS MUST be explicitly set (no wildcards)
  • SecurityMiddleware MUST be enabled and configured
  • CSRF middleware MUST be enabled
  • SECURE_SSL_REDIRECT SHOULD be True
  • SESSION_COOKIE_SECURE MUST be True
  • CSRF_COOKIE_SECURE MUST be True
  • MUST NOT have @csrf_exempt without justification
  • All views MUST have appropriate auth decorators
  • MUST NOT have raw SQL with string formatting
  • DRF SHOULD have IsAuthenticated as default permission
</checklist>
Skills Info
Original Name:security-djangoAuthor:justinlevinedotme