From 9e8587fa26e1a2ba6d5d30656f181126691ced97 Mon Sep 17 00:00:00 2001 From: "eric.quintero@trailofbits.com" Date: Tue, 2 Jun 2026 16:26:15 +0000 Subject: [PATCH 1/2] Keep legacy 404 links on legacy host --- apps/cms/tests.py | 6 ++++++ apps/cms/views.py | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/cms/tests.py b/apps/cms/tests.py index dc57f828b..d1d65d7db 100644 --- a/apps/cms/tests.py +++ b/apps/cms/tests.py @@ -81,6 +81,12 @@ class Test404(TestCase): def test_legacy_path(self): self.assertEqual(legacy_path("/any/thing"), "http://legacy.python.org/any/thing") + def test_legacy_path_with_encoded_slash(self): + self.assertEqual(legacy_path("/%2Fevil.test/x"), "http://legacy.python.org/%2Fevil.test/x") + + def test_legacy_path_with_decoded_encoded_slash(self): + self.assertEqual(legacy_path("//evil.test/x"), "http://legacy.python.org//evil.test/x") + def test_custom_404(self): """Ensure custom 404 is set to 5 minutes""" response = self.client.get("/foo-bar/baz/9876") diff --git a/apps/cms/views.py b/apps/cms/views.py index b5570f439..faed382be 100644 --- a/apps/cms/views.py +++ b/apps/cms/views.py @@ -1,6 +1,6 @@ """Views for the cms app, including custom error handlers.""" -from urllib.parse import urljoin +from urllib.parse import quote from django.shortcuts import render from django.urls import reverse @@ -11,7 +11,9 @@ def legacy_path(path): """Build a path to the same path under the legacy.python.org domain.""" - return urljoin(LEGACY_PYTHON_DOMAIN, path) + if not path.startswith("/"): + path = f"/{path}" + return f"{LEGACY_PYTHON_DOMAIN}{quote(path, safe='/%')}" def custom_404(request, exception, template_name="404.html"): From 862ab0af20110f3fa17e0b3a65eb6acdeac57abb Mon Sep 17 00:00:00 2001 From: "eric.quintero@trailofbits.com" Date: Wed, 3 Jun 2026 14:31:35 +0000 Subject: [PATCH 2/2] Add test for relative legacy 404 paths --- apps/cms/tests.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/cms/tests.py b/apps/cms/tests.py index d1d65d7db..679aee28d 100644 --- a/apps/cms/tests.py +++ b/apps/cms/tests.py @@ -81,6 +81,9 @@ class Test404(TestCase): def test_legacy_path(self): self.assertEqual(legacy_path("/any/thing"), "http://legacy.python.org/any/thing") + def test_legacy_path_without_leading_slash(self): + self.assertEqual(legacy_path("any/thing"), "http://legacy.python.org/any/thing") + def test_legacy_path_with_encoded_slash(self): self.assertEqual(legacy_path("/%2Fevil.test/x"), "http://legacy.python.org/%2Fevil.test/x")