From 4f508f609c6217b44cfdc9160f8a53732851a608 Mon Sep 17 00:00:00 2001 From: Jon Froehlich Date: Thu, 18 Jun 2026 12:16:56 -0700 Subject: [PATCH] feat(security): enable SECURE_PROXY_SSL_HEADER on TEST/PROD (#1329) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Behind UW CSE's TLS-terminating Apache proxy, the Django container is reached over plain HTTP, so request.scheme reported "http" and request.is_secure() was False even though visitors arrive over HTTPS. Apache now sets X-Forwarded-Proto: https on test and prod (confirmed by UW CSE IT), and the backend binds to loopback only, so the header can't be spoofed by a direct client. Trust it via SECURE_PROXY_SSL_HEADER, gated to DJANGO_ENV in (PROD, TEST) — local dev has no such proxy and must not trust a client-supplied header. This is the framework-level fix behind #1236. The in-app site_scheme workaround is left in place for now and will be removed in a follow-up once verified on -test. Co-Authored-By: Claude Opus 4.8 (1M context) --- makeabilitylab/settings.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/makeabilitylab/settings.py b/makeabilitylab/settings.py index f338d005..dbb536eb 100644 --- a/makeabilitylab/settings.py +++ b/makeabilitylab/settings.py @@ -71,6 +71,20 @@ else: ALLOWED_HOSTS = ['*'] +# Trust the X-Forwarded-Proto header from UW CSE's TLS-terminating Apache proxy so +# request.scheme / request.is_secure() report the real (https) scheme (#1329). +# +# The deployed Django container is reached over plain HTTP from Apache, so without +# this Django thinks every request is http even though visitors arrive over https. +# This is ONLY safe because the proxy is trusted: Apache sets X-Forwarded-Proto and +# the backend binds to the host's loopback only, so a client can't reach Django +# directly to spoof the header (confirmed with UW CSE IT). Gated to the deployed +# environments — in local dev there is no such proxy, so we must NOT trust the +# header (a direct client could forge it). Supersedes the in-app site_scheme +# workaround from #1236, which we keep for now and remove once verified on -test. +if DJANGO_ENV in ('PROD', 'TEST'): + SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + # Makeability Lab Global Variables, including Makeability Lab version ML_WEBSITE_VERSION = "2.12.1" # Keep this updated with each release and also change the short description below ML_WEBSITE_VERSION_DESCRIPTION = "Patch: tighten meta descriptions (#1142/#1324). Home now uses a concise description mirroring the hero blurb; projects without a one-line summary fall back to a truncated About instead of the generic lab boilerplate; the last-resort default is trimmed to ~135 chars. Reduces duplicate/over-long descriptions flagged by social/OG inspectors. Template/view-only — no schema change."