Lion Cipher Lab
Harden a Django project for production: drive check --deploy to zero, and know what it cannot see
- AppSec / DevSecOps
- Intermediate
- ~75 min
- Free · no account required
Why it matters
Django is one of the most widely deployed Python web frameworks, and the most common way a Django site gets hurt is not an exotic bug: it is a project deployed with the development settings still on. DEBUG=True leaks source code and settings on every error page, a guessable SECRET_KEY lets an attacker forge signed data, and missing HTTPS settings send session cookies in clear text. Django ships a linter for exactly this, but most people never run it, and the ones who do often stop at 'zero warnings' and believe the app is secure. This lab teaches both halves: drive the linter to zero with…
What you'll learn
- running Django's built-in deployment linter (python manage.py check --deploy) and reading every finding ID it prints, from security.W004 to the Django 6.1 mail.E001 error
- explaining what each production setting does and the specific risk it addresses: DEBUG, SECRET_KEY, ALLOWED_HOSTS, SECURE_SSL_REDIRECT, SECURE_HSTS_*, SESSION_COOKIE_SECURE, CSRF_COOKIE_SECURE, X_FRAME_OPTIONS, SECURE_CONTENT_TYPE_NOSNIFF, SECURE_REFERRER_POLICY, SECURE_CROSS_ORIGIN_OPENER_POLICY
- splitting settings into base / dev / prod so development stays convenient while production reads secrets from environment variables and refuses to start without them
- measuring hardening instead of trusting it: a per-step finding count (7 warnings + 1 error down to 0) and the real response headers and cookie flags before vs after
- making the HSTS judgment: starting with a one-hour max-age, deciding on includeSubDomains, and deliberately NOT preloading, recorded in SILENCED_SYSTEM_CHECKS with a reason
- reproducing the SECURE_SSL_REDIRECT redirect loop behind a TLS-terminating proxy, fixing it with SECURE_PROXY_SSL_HEADER, and showing why that fix is only safe when the proxy overwrites X-Forwarded-Proto
- proving with canaries what the check cannot see: missing authorization, raw-SQL injection and mark_safe XSS all pass with zero findings, and a Content-Security-Policy is never requested
- adding a CI gate with --fail-level WARNING, because the default fail level (ERROR) lets a warnings-only regression exit 0
Steps in this lab
- What check --deploy is, and when you reach for it
- Install Django and record the version
- Create a project and lint the untouched defaults
- Split the settings: base, dev, prod
- Fix 1 to 3: DEBUG, SECRET_KEY, ALLOWED_HOSTS
- Fix 4 to 6: the HTTPS trio
- Fix 7: HSTS, and why the warning count goes UP
- The headers that are already right, and how to keep them right
- Fix 8: a real email backend (mail.E001)
- Measure it: the ladder from 8 findings to 0
- Run the real command against prod
- Measure the headers and cookies before vs after
- Behind a proxy: the redirect loop, the fix, and the trap in the fix
- What check --deploy cannot see: three broken views, zero findings
- Gate CI on warnings, not just errors
- How a pro uses this, and where to go next