From 2fc4778cdd496fdb813a7c1d6b79df367da3c9a3 Mon Sep 17 00:00:00 2001 From: Akhil Narang Date: Wed, 15 Oct 2025 18:22:12 +0530 Subject: [PATCH] fix: tighten allowed referrer checks Signed-off-by: Akhil Narang --- frappe/auth.py | 9 ++++++--- frappe/tests/test_auth.py | 14 +++++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/frappe/auth.py b/frappe/auth.py index 03b28f0dc5..e631fa0c27 100644 --- a/frappe/auth.py +++ b/frappe/auth.py @@ -110,9 +110,12 @@ class HTTPRequest: ) # Check if the referrer or origin is in the allowed list - return (referrer and any(referrer.startswith(allowed) for allowed in allowed_referrers)) or ( - origin and any(origin == allowed for allowed in allowed_referrers) - ) + if referrer: + referrer_parsed = urlparse(referrer) + if any(referrer_parsed.netloc == urlparse(allowed).netloc for allowed in allowed_referrers): + return True + + return origin in allowed_referrers if origin else False class LoginManager: diff --git a/frappe/tests/test_auth.py b/frappe/tests/test_auth.py index 70399b0445..9ad7550baf 100644 --- a/frappe/tests/test_auth.py +++ b/frappe/tests/test_auth.py @@ -176,8 +176,10 @@ class TestAllowedReferrer(UnitTestCase): env = builder.get_environ() return Request(env) - # Test with valid referrer + # Set a single allowed referrer frappe.cache.set_value("allowed_referrers", ["https://example.com"]) + + # Test with valid referrer frappe.local.request = create_request({"Referer": "https://example.com/some/path"}) http_request = frappe.auth.HTTPRequest() self.assertTrue(http_request.is_allowed_referrer()) @@ -197,6 +199,16 @@ class TestAllowedReferrer(UnitTestCase): http_request = frappe.auth.HTTPRequest() self.assertFalse(http_request.is_allowed_referrer()) + # Test subdomain bypass prevention + frappe.local.request = create_request({"Referer": "https://example.com.evil.com"}) + http_request = frappe.auth.HTTPRequest() + self.assertFalse(http_request.is_allowed_referrer()) + + # Test exact domain match for referrer + frappe.local.request = create_request({"Referer": "https://example.com"}) + http_request = frappe.auth.HTTPRequest() + self.assertTrue(http_request.is_allowed_referrer()) + # Clean up frappe.cache.delete_value("allowed_referrers") frappe.local.request = None