Django security best practices, authentication, authorization, CSRF protection, SQL injection prevention, XSS prevention, and secure deployment configurations.
Scanned 6/4/2026
Install to Claude Code
npx -y skills add lidge-jun/cli-jaw-skills --skill django-security --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Django Security?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/lidge-jun-django-security)More formats (shields.io, HTML) on the badges page.
---
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:
```python
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`:
```python
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:
```python
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:
```python
# 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:
```django
{{ 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:
```python
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 `|safe` with user input |
| 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.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!