By framework
Django security — DEBUG, SECRET_KEY, and authorization
Django has safe defaults, but incidents come from settings: DEBUG=True in production (settings/secret exposure), a leaked SECRET_KEY, and thin authorization. Set DEBUG=False, load SECRET_KEY from the environment, authorize explicitly. Defensive, no attack steps.
For: anyone running a Django app. No attack steps here — just keeping the safe defaults working while closing the gaps settings open. For the full picture, see the security-by-framework hub.
The big three pitfalls (they open in settings)
Django's defaults are excellent, but these three are yours to guard in settings and code.
① DEBUG=True in production
Error page exposes settings, env vars, secrets. Extracted via deliberate errors.
② Leaked SECRET_KEY
Basis for signing/sessions/CSRF. Leaks risk forging and tampering.
③ Thin authorization
Authenticated but missing permission/owner checks. ID swap reveals others' data.
Also watch for SQLi via raw()/extra() or string interpolation, unsafe deserialization (pickle), unset ALLOWED_HOSTS, and unpatched dependency (pip) CVEs.
How to close them (3 steps)
DEBUG=False + ALLOWED_HOSTS in production
ALLOWED_HOSTS correctly. Stop detailed errors from showing externally and configure static/media serving for production. Bake it into deploy and verify every time.Load SECRET_KEY from the environment, keep it private
SECRET_KEY in code/repo — load it from an environment variable or secret manager. Keep it off public directories and DEBUG pages, and rotate promptly if leaked (→ keep secrets out of public directories).Make authorization explicit and cut dangerous input paths
raw(), and don't restore untrusted data with pickle. Keep dependencies (pip) CVE-monitored + patched fast (→ what IDOR is).Common (dangerous)
- production left at
DEBUG=True SECRET_KEYhardcoded in code/repo- no authorization — "logged in = can view"
raw()string interpolation ·pickleon untrusted data
Correct
- production DEBUG=False + ALLOWED_HOSTS
-
SECRET_KEYfrom env, kept private - explicit authorization (permission/owner scope)
- ORM/placeholders, no untrusted deserialization
This site's view: batteries included, but settings and authorization are on you
Django guards a lot by default, but production settings (DEBUG/SECRET_KEY/ALLOWED_HOSTS) and authorization are things you must get right per environment and per app. The incidents we keep seeing are less elaborate attacks than settings/operations patterns: "debug was open in production," "a secret was exposed," "there was no authorization." So the center of gravity is tightening production settings, keeping secrets private, and making authorization explicit. Not undoing the solid defaults is the crux of running Django.
Read next
- Hub: security by framework · Laravel security (similar production-DEBUG / secret-exposure)
- Secrets: keep secrets out of public directories · Practice: the vulnerability-response playbook
- Glossary: what IDOR is · what SQL injection is
FAQ
QIs Django a secure framework?
Django is 'batteries included' — ORM-based SQL protection, CSRF protection, template auto-escaping, and an auth system are standard. Configured correctly it's a solid framework, but incidents come not from the core but from settings. DEBUG=True in production, a leaked SECRET_KEY, and thin authorization recur less as Django-specific issues than as operational/settings problems.
QWhat's dangerous about leaving DEBUG=True in production?
With DEBUG on, the error page can show detailed internals — settings, environment variables, stack traces. An attacker can trigger errors on purpose to extract them. In production, always set DEBUG=False and configure ALLOWED_HOSTS correctly. Also stop detailed errors from being shown externally and review static/media serving for production.
QWhy is SECRET_KEY important?
SECRET_KEY is the key underpinning signed cookies and sessions, CSRF tokens, password resets, and more. A leak can lead to forging or tampering with those. Don't put SECRET_KEY in code or the repo — load it from an environment variable or secret manager, and rotate it promptly if it ever leaks. Also keep it from being exposed via a public directory or a DEBUG page.