🛡️ Security
Everyone who can log in to the admin can change your content. This page describes what Content Studio protects out of the box and what your deployment has to take care of.
What Content Studio does
- Staff only. Like the classic Django admin, only active staff users can log in, and every request checks this again. Deactivating a user or revoking their staff status ends their access immediately. What an editor may see and do is decided by the permission hooks.
- Short sessions. Sessions renew themselves while an editor works and end after a week without use. Changing or resetting a password logs the user out everywhere (authentication).
- Limited login and password reset attempts, per IP address
(
LOGIN_THROTTLE_RATE,PASSWORD_RESET_THROTTLE_RATE). Five wrong reset codes lock an email address out, and new passwords must passAUTH_PASSWORD_VALIDATORS. - Sanitized rich text.
HTMLFieldcleans its value on save with an allowlist sanitizer (HTML_SANITIZER). - Checked uploads. The media library accepts a list of file types up to
a maximum size, and rejects markup such as HTML and SVG
(
MEDIA_LIBRARY_ALLOWED_EXTENSIONS). - Nothing public but the login pages. Before logging in, the admin only receives what it needs to show the login form.
Deployment checklist
- Serve the admin over HTTPS. The session cookie is marked
SecurewheneverDEBUGis off (REFRESH_COOKIE_SECURE). Behind a proxy that terminates TLS, also set Django'sSECURE_PROXY_SSL_HEADER. - Configure a shared cache, such as Redis, Memcached or the database cache. The login and password reset limits are counted in the cache; with the default per-process cache, every worker counts separately.
- Pass on the client's IP address. The limits count per IP address.
Behind a proxy, set
NUM_PROXIESin the Django REST Framework settings to the number of proxies in front of your application. - Serve uploads from a separate domain when you can, such as a CDN or an object storage bucket. Even with the upload checks, a file served from your own domain runs with your site's privileges if a browser renders it.
- Configure a task backend that runs Django tasks in a worker. Password reset emails are then sent outside the request, so its duration does not reveal whether an address has an account (password reset).
- Keep
DEBUGoff in production, and keep Django, Content Studio and your other dependencies up to date. - Use Django's security middleware and settings:
SecurityMiddlewarewith HSTS,XFrameOptionsMiddleware, andSESSION_COOKIE_SECUREandCSRF_COOKIE_SECUREfor the rest of your site.manage.py check --deploylists what is missing. - Keep
SECRET_KEYstrong and secret, or set a separateTOKEN_SIGNING_KEY: it signs the sessions.
Reporting a vulnerability
Report security problems privately, through GitHub's private vulnerability reporting or by email; see SECURITY.md.