Security
Django includes robust protections against common web vulnerabilities. Most are enabled by default but require correct configuration in production.
Cross-Site Scripting (XSS)
Django automatically escapes HTML in templates (< becomes <), preventing injected scripts from running.
- Bypassing safely: Only use
{{ var|safe }}ormark_safe()if you have sanitized the input yourself (e.g., viableach). - Contexts escaping doesn't cover: Beware of unquoted attributes (
class={{ var }}) or<script>tags. Use thejson_scriptfilter to pass data to JavaScript safely.
Cross-Site Request Forgery (CSRF)
CsrfViewMiddleware requires a token for all POST/PUT/DELETE requests to stop attackers from forging actions on a logged-in user's behalf.
- HTML Forms: Always include
{% csrf_token %}inside your<form>. - AJAX/Fetch: Read the token from the
csrftokencookie and send it in theX-CSRFTokenheader. - Cross-Origin: If submitting from a different frontend domain or subdomain, add it to
CSRF_TRUSTED_ORIGINS.
SQL Injection
Django's ORM parameterizes all queries automatically, neutralizing injection attempts.
Raw SQL Danger: Never use string formatting (
%orf-strings) to build SQL queries. Always pass variables as parameters:python# SAFE User.objects.raw("SELECT * FROM auth_user WHERE username = %s", [name])
Clickjacking
XFrameOptionsMiddleware blocks your site from being loaded in an invisible iframe via the X_FRAME_OPTIONS = "DENY" setting. If framing is explicitly required for a specific view, use the @xframe_options_exempt decorator.
HTTPS & Host Validation
Encrypting traffic is critical to protect session cookies and CSRF tokens from network snooping.
- HTTPS Enforcement: Set
SECURE_SSL_REDIRECT = True,SESSION_COOKIE_SECURE = True, andCSRF_COOKIE_SECURE = True. - HSTS: Enable
SECURE_HSTS_SECONDSto force browsers to always use HTTPS for your domain (start with a small value before increasing). - Proxies: If behind a load balancer terminating TLS, set
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")so Django knows the original request was secure. - Host Header:
ALLOWED_HOSTSis mandatory whenDEBUG = Falseto prevent host-header poisoning.
Content Security Policy (CSP)
Use django.middleware.csp.ContentSecurityPolicyMiddleware to restrict where scripts and resources can load from, providing a second line of defence against XSS.
from django.utils.csp import CSP
SECURE_CSP = {
"default-src": [CSP.SELF],
"script-src": [CSP.SELF, CSP.NONCE], # Allows inline scripts with a valid nonce
}Cryptographic Signing
SECRET_KEY underpins session integrity, password reset tokens, and signed cookies. Keep it secret, load it from the environment, and use SECRET_KEY_FALLBACKS to rotate it safely.
You can use the same machinery for your own expiring links:
from django.core.signing import TimestampSigner
token = TimestampSigner().sign("[email protected]")Security Best Practices
- Uploads: Never execute user-uploaded files. Restrict extensions, sizes, and serve media from a separate domain.
- Admin: Protect the admin by moving it off the default
/admin/path, restricting IP access, and enabling Multi-Factor Authentication (MFA). - Checklist: Run
python manage.py check --deployto audit your production settings. Keep Django updated to receive security patches.
