This commit is contained in:
2026-10-23 17:10:31 -04:00
parent fa1568b0bd
commit ae25026d9f
2 changed files with 22 additions and 1 deletions
+4 -1
View File
@@ -5,6 +5,9 @@ class SecurityHeaders:
def __call__(self, request):
response = self.get_response(request)
response["Cache-Control"] = "no-store"
response["Referrer-Policy"] = "no-referrer"
# HTTPS form posts need their same-site origin/referrer for Django's
# CSRF checks. no-referrer can produce Origin: null in browsers.
# same-origin still withholds verification URLs from external sites.
response["Referrer-Policy"] = "same-origin"
response["Content-Security-Policy"] = "default-src 'none'; style-src 'self'; img-src 'self'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'"
return response
@@ -109,6 +109,24 @@ class RegistrationTests(TestCase):
self.assertEqual(self.client.get("/members/login/").status_code, 405)
self.assertEqual(self.client.get("/members/checkout/supporter/").status_code, 405)
@patch("members.views.dex")
def test_same_origin_login_preserves_csrf_protection(self, dex):
from django.http import HttpResponseRedirect
strict = Client(enforce_csrf_checks=True)
response = strict.get("/members/", secure=True)
self.assertEqual(response.headers["Referrer-Policy"], "same-origin")
token = strict.cookies[settings.CSRF_COOKIE_NAME].value
dex.return_value.authorize_redirect.return_value = HttpResponseRedirect(settings.DEX_ISSUER + "/auth")
response = strict.post("/members/login/", {"csrfmiddlewaretoken": token}, secure=True, HTTP_ORIGIN="https://testserver")
self.assertEqual(response.status_code, 302)
dex.return_value.authorize_redirect.assert_called_once()
for origin in ("null", "https://attacker.example"):
response = strict.post("/members/login/", {"csrfmiddlewaretoken": token}, secure=True, HTTP_ORIGIN=origin)
self.assertEqual(response.status_code, 403)
response = strict.post("/members/login/", {"csrfmiddlewaretoken": token}, secure=True, HTTP_REFERER="https://testserver/members/")
self.assertEqual(response.status_code, 302)
@override_settings(MEMBERSHIP_TIERS=TIERS)
class IdentityTests(TestCase):