diff --git a/CHANGELOG.md b/CHANGELOG.md index 06e7bf0d..b75ead6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. ### Bug Fixes - Fix dark mode styling issues in Cron Syntax Cheatsheet - Fix a 403 when transferring a project to a read-only team member +- Security: fix allow_redirect function to reject absolute URLs ## v1.21.0 - 2020-07-02 diff --git a/hc/accounts/tests/test_login.py b/hc/accounts/tests/test_login.py index b7d3c338..fc966999 100644 --- a/hc/accounts/tests/test_login.py +++ b/hc/accounts/tests/test_login.py @@ -95,8 +95,14 @@ class LoginTestCase(BaseTestCase): def test_it_handles_bad_next_parameter(self): form = {"action": "login", "email": "alice@example.org", "password": "password"} - r = self.client.post("/accounts/login/?next=/evil/", form) - self.assertRedirects(r, self.checks_url) + samples = [ + "/evil/", + f"https://example.org/projects/{self.project.code}/checks/", + ] + + for sample in samples: + r = self.client.post("/accounts/login/?next=" + sample, form) + self.assertRedirects(r, self.checks_url) def test_it_handles_wrong_password(self): form = { diff --git a/hc/accounts/views.py b/hc/accounts/views.py index 8e21f8a6..e9a9b77d 100644 --- a/hc/accounts/views.py +++ b/hc/accounts/views.py @@ -54,6 +54,10 @@ def _allow_redirect(redirect_url): return False parsed = urlparse(redirect_url) + if parsed.netloc: + # Allow redirects only to relative URLs + return False + try: match = resolve(parsed.path) except Resolver404: