django-security

star 4

Django security best practices, authentication, authorization, CSRF protection, SQL injection prevention, XSS prevention, and secure deployment configurations.

lidge-jun By lidge-jun schedule Updated 6/8/2026

name: django-security description: Django security best practices, authentication, authorization, CSRF protection, SQL injection prevention, XSS prevention, and secure deployment configurations.

Django Security Best Practices

Security guidelines for Django applications covering common vulnerabilities and hardening practices.

When to Activate

  • Setting up Django authentication and authorization
  • Implementing user permissions and roles
  • Configuring production security settings
  • Reviewing Django application for security issues
  • Deploying Django applications to production

Core Security Settings

Set all of the following for production deployments:

DEBUG = False
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')

SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
SECURE_CONTENT_TYPE_NOSNIFF = True
X_FRAME_OPTIONS = 'DENY'
SESSION_COOKIE_HTTPONLY = True
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SAMESITE = 'Lax'

See references/code-examples.md § Production Settings for complete configuration including password validators.

Authentication

  • Custom User Model: Extend AbstractUser with USERNAME_FIELD = 'email'. Set AUTH_USER_MODEL in settings. Define early — changing later requires migration surgery.
  • Password Hashing: Use Argon2 as primary hasher (django.contrib.auth.hashers.Argon2PasswordHasher).
  • Session Management: Use cache-backed sessions (SESSION_ENGINE = 'django.contrib.sessions.backends.cache'), set reasonable SESSION_COOKIE_AGE.

See references/code-examples.md § Custom User Model and § Password Hashing.

Authorization

Django Permissions

Use LoginRequiredMixin and PermissionRequiredMixin for class-based views. Define custom permissions in Meta.permissions:

class Meta:
    permissions = [
        ('can_publish', 'Can publish posts'),
        ('can_edit_others', 'Can edit posts of others'),
    ]

DRF Permissions

Create custom BasePermission subclasses for API authorization:

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.author == request.user

Role-Based Access Control

Add a role field to the User model with choices like admin/moderator/user. Create mixins like AdminRequiredMixin for view-level enforcement.

See references/code-examples.md § Authorization for complete permission, RBAC, and mixin examples.

SQL Injection Prevention

The Django ORM automatically parameterizes queries. Follow these rules:

# Preferred: ORM methods are safe
User.objects.get(username=username)
User.objects.filter(email__iexact=email)

# Preferred: parameterized raw queries
User.objects.raw('SELECT * FROM users WHERE username = %s', [query])

# Avoid: string interpolation in raw queries (vulnerable)
User.objects.raw(f'SELECT * FROM users WHERE username = {username}')

Use Q objects for complex queries — they are also safe from injection.

XSS Prevention

Template Escaping

Django auto-escapes template variables by default:

{{ user_input }}              {# auto-escaped — safe #}
{{ trusted_html|safe }}       {# not escaped — use only for trusted content #}
{{ user_input|striptags }}    {# removes all HTML tags #}

<script>
    var username = {{ username|escapejs }};
</script>

Safe String Handling

Use format_html() instead of mark_safe() for HTML with variables. If using mark_safe(), always escape() user input first. See references/code-examples.md § XSS Prevention.

Security Headers

Set SECURE_CONTENT_TYPE_NOSNIFF, X_FRAME_OPTIONS = 'DENY', and add a Content-Security-Policy header via middleware. See references/code-examples.md § Security Headers Middleware.

CSRF Protection

CSRF protection is enabled by default. Key settings:

CSRF_COOKIE_SECURE = True
CSRF_COOKIE_HTTPONLY = True
CSRF_COOKIE_SAMESITE = 'Lax'
CSRF_TRUSTED_ORIGINS = ['https://example.com']

In templates, include {% csrf_token %} in every <form method="post">. For AJAX requests, read the csrftoken cookie and send it as X-CSRFToken header. See references/code-examples.md § CSRF for the JavaScript helper.

Use @csrf_exempt sparingly — only for webhooks from external services.

File Upload Security

Validate file extension and size before accepting uploads. Use validators on FileField:

  • Restrict extensions to an allowlist (e.g., .jpg, .png, .pdf)
  • Enforce a maximum file size (e.g., 5 MB)
  • Serve user uploads from a separate domain or CDN, not directly from the app

See references/code-examples.md § File Upload Validation.

API Security

Rate Limiting

Configure DRF throttle classes to protect against abuse:

  • AnonRateThrottle: 100/day for unauthenticated users
  • UserRateThrottle: 1000/day for authenticated users
  • Custom scopes for sensitive endpoints (e.g., upload: 10/hour)

Authentication

Use token-based or JWT authentication for APIs. Set DEFAULT_PERMISSION_CLASSES to IsAuthenticated.

See references/code-examples.md § API Rate Limiting and § API Authentication.

Environment Variables

Use django-environ or python-decouple to load secrets from .env files. Store SECRET_KEY, DATABASE_URL, and ALLOWED_HOSTS as environment variables. Ensure .env is in .gitignore.

See references/code-examples.md § Environment Variables.

Logging Security Events

Configure Django's django.security and django.request loggers to write warnings and errors to dedicated log files.

See references/code-examples.md § Logging Security Events.

Quick Security Checklist

Check Description
DEBUG = False Set False for production
HTTPS only Force SSL, secure cookies
Strong secrets Use environment variables for SECRET_KEY
Password validation Enable all password validators
CSRF protection Enabled by default — keep it active
XSS prevention Django auto-escapes; avoid `
SQL injection Use ORM; avoid string concatenation in queries
File uploads Validate file type and size
Rate limiting Throttle API endpoints
Security headers CSP, X-Frame-Options, HSTS
Logging Log security events
Updates Keep Django and dependencies updated

Security is a continuous process. Review and update practices regularly.

Django Security Version Notes (June 2026)

Current: Django 6.0.6. Key security additions:

  • Native CSP support: Built-in Content Security Policy with nonce functionality (no more third-party CSP packages)
  • Security patch 6.0.6: Fixes signed cookie salt collision, potential unencrypted email transmission
  • Python: Requires 3.12+ (3.10/3.11 dropped — ensure CI/CD updates)
Install via CLI
npx skills add https://github.com/lidge-jun/cli-jaw-skills --skill django-security
Repository Details
star Stars 4
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator