CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/django-security-basics

Security essentials for Django — CSRF, CORS, security middleware, ALLOWED_HOSTS,

99

2.91x
Quality

99%

Does it follow best practices?

Impact

99%

2.91x

Average score across 2 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files
name:
django-security-basics
description:
Security essentials for Django — CSRF, CORS, security middleware, ALLOWED_HOSTS, secrets management, and common misconfigurations. Use when building or reviewing Django apps before production deployment, or when a security audit flags issues.
keywords:
django security, django csrf, django cors, django allowed hosts, django secret key, django security middleware, django production, django deployment, django security checklist, django-cors-headers
license:
MIT

Django Security Basics

Django has good security defaults, but they must be configured correctly for production.


Django's Built-in Security

Django includes these by default (don't disable them):

  • CSRF protection on POST/PUT/PATCH/DELETE
  • SQL injection prevention via ORM
  • XSS protection via template auto-escaping
  • Clickjacking protection via X-Frame-Options

Your job: configure what Django can't know — hosts, secrets, CORS, HTTPS.


1. ALLOWED_HOSTS (Critical)

# settings.py
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')

Empty ALLOWED_HOSTS in production = host header attacks. Django rejects requests with unrecognized Host headers, but only if this is set.


2. SECRET_KEY

SECRET_KEY = os.environ.get('SECRET_KEY')
if not SECRET_KEY and not DEBUG:
    raise ImproperlyConfigured('Set SECRET_KEY for production')

Never commit the secret key. Use env vars or a secrets manager.


3. CORS (django-cors-headers)

pip install django-cors-headers
INSTALLED_APPS = [..., 'corsheaders', ...]
MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...]  # Must be near top

CORS_ALLOWED_ORIGINS = os.environ.get('CORS_ORIGINS', 'http://localhost:5173').split(',')
# NOT: CORS_ALLOW_ALL_ORIGINS = True

4. Security Middleware Settings

# Production settings
SECURE_BROWSER_XSS_FILTER = True
SECURE_CONTENT_TYPE_NOSNIFF = True
SESSION_COOKIE_SECURE = True       # HTTPS only
SESSION_COOKIE_HTTPONLY = True      # Prevent JavaScript access to session cookie
CSRF_COOKIE_SECURE = True          # HTTPS only
SECURE_SSL_REDIRECT = True         # Redirect HTTP to HTTPS
SECURE_HSTS_SECONDS = 31536000     # 1 year HSTS
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
X_FRAME_OPTIONS = 'DENY'

# CSRF trusted origins — required when your frontend is on a different domain
CSRF_TRUSTED_ORIGINS = os.environ.get('CSRF_TRUSTED_ORIGINS', 'https://yourdomain.com').split(',')

For development, these should be False/0. Use separate settings or environment checks.

Always set CSRF_TRUSTED_ORIGINS when deploying behind a reverse proxy or when the frontend origin differs from the backend. Django 4.0+ requires this for cross-origin POST requests to succeed.


5. CSRF for APIs

For API-only backends (DRF with token auth), CSRF can be disabled on specific views:

from django.views.decorators.csrf import csrf_exempt

# Only exempt API views that use token authentication, not session auth

But if using session-based auth, keep CSRF enabled and include the token in API requests:

// Frontend: read CSRF token from cookie
const csrfToken = document.cookie.match(/csrftoken=([^;]+)/)?.[1];
fetch('/api/orders', {
  method: 'POST',
  headers: { 'X-CSRFToken': csrfToken, 'Content-Type': 'application/json' },
  body: JSON.stringify(data),
});

6. Security Check

Django has a built-in security checker:

python manage.py check --deploy

This warns about missing security settings. Run it before every deployment.


Checklist

  • ALLOWED_HOSTS set from environment (not ['*'])
  • SECRET_KEY from environment, not in settings.py
  • DEBUG = False in production
  • django-cors-headers with explicit origins
  • Security middleware settings configured for production
  • CSRF_TRUSTED_ORIGINS set from environment or explicit list
  • SESSION_COOKIE_SECURE = True and SESSION_COOKIE_HTTPONLY = True
  • python manage.py check --deploy passes
  • CSRF token included in frontend API requests (if using sessions)
  • No CORS_ALLOW_ALL_ORIGINS = True in production

Verifiers

  • django-security — Proactive security checks for Django projects (REST API settings, auth session security)
Workspace
tessl-labs
Visibility
Public
Created
Last updated
Publish Source
CLI
Badge
tessl-labs/django-security-basics badge