[Python-modules-commits] [python-social-auth] 88/131: Multiple hosts in redirect sanitaion.

Wolfgang Borgert debacle at moszumanska.debian.org
Sat Dec 24 15:17:06 UTC 2016


This is an automated email from the git hooks/post-receive script.

debacle pushed a commit to tag v0.2.20
in repository python-social-auth.

commit ed274822027cac1c5be3cd98a129dba1a93c8d20
Author: murchik <murchik at protonmail.com>
Date:   Tue Jul 26 23:41:21 2016 +0800

    Multiple hosts in redirect sanitaion.
---
 social/actions.py          | 11 +++++++----
 social/tests/test_utils.py | 24 +++++++++++++++++-------
 social/utils.py            | 10 +++++-----
 3 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/social/actions.py b/social/actions.py
index a0e4e5b..0973219 100644
--- a/social/actions.py
+++ b/social/actions.py
@@ -19,8 +19,9 @@ def do_auth(backend, redirect_name='next'):
         # Check and sanitize a user-defined GET/POST next field value
         redirect_uri = data[redirect_name]
         if backend.setting('SANITIZE_REDIRECTS', True):
-            redirect_uri = sanitize_redirect(backend.strategy.request_host(),
-                                             redirect_uri)
+            allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + [
+                backend.strategy.request_host()]
+            redirect_uri = sanitize_redirect(allowed_hosts, redirect_uri)
         backend.strategy.session_set(
             redirect_name,
             redirect_uri or backend.setting('LOGIN_REDIRECT_URL')
@@ -91,8 +92,10 @@ def do_complete(backend, login, user=None, redirect_name='next',
                '{0}={1}'.format(redirect_name, redirect_value)
 
     if backend.setting('SANITIZE_REDIRECTS', True):
-        url = sanitize_redirect(backend.strategy.request_host(), url) or \
-              backend.setting('LOGIN_REDIRECT_URL')
+        allowed_hosts = backend.setting('ALLOWED_REDIRECT_HOSTS', []) + [
+            backend.strategy.request_host()]
+        url = sanitize_redirect(allowed_hosts, url) or \
+            backend.setting('LOGIN_REDIRECT_URL')
     return backend.strategy.redirect(url)
 
 
diff --git a/social/tests/test_utils.py b/social/tests/test_utils.py
index 7bd8db0..8ab2ead 100644
--- a/social/tests/test_utils.py
+++ b/social/tests/test_utils.py
@@ -13,31 +13,41 @@ PY3 = sys.version_info[0] == 3
 
 class SanitizeRedirectTest(unittest.TestCase):
     def test_none_redirect(self):
-        self.assertEqual(sanitize_redirect('myapp.com', None), None)
+        self.assertEqual(sanitize_redirect(['myapp.com'], None), None)
 
     def test_empty_redirect(self):
-        self.assertEqual(sanitize_redirect('myapp.com', ''), None)
+        self.assertEqual(sanitize_redirect(['myapp.com'], ''), None)
 
     def test_dict_redirect(self):
-        self.assertEqual(sanitize_redirect('myapp.com', {}), None)
+        self.assertEqual(sanitize_redirect(['myapp.com'], {}), None)
 
     def test_invalid_redirect(self):
-        self.assertEqual(sanitize_redirect('myapp.com', {'foo': 'bar'}), None)
+        self.assertEqual(sanitize_redirect(['myapp.com'], {'foo': 'bar'}), None)
 
     def test_wrong_path_redirect(self):
         self.assertEqual(
-            sanitize_redirect('myapp.com', 'http://notmyapp.com/path/'),
+            sanitize_redirect(['myapp.com'], 'http://notmyapp.com/path/'),
             None
         )
 
     def test_valid_absolute_redirect(self):
         self.assertEqual(
-            sanitize_redirect('myapp.com', 'http://myapp.com/path/'),
+            sanitize_redirect(['myapp.com'], 'http://myapp.com/path/'),
             'http://myapp.com/path/'
         )
 
     def test_valid_relative_redirect(self):
-        self.assertEqual(sanitize_redirect('myapp.com', '/path/'), '/path/')
+        self.assertEqual(sanitize_redirect(['myapp.com'], '/path/'), '/path/')
+
+    def test_multiple_hosts(self):
+        allowed_hosts = ['myapp1.com', 'myapp2.com']
+        for host in allowed_hosts:
+            url = 'http://{}/path/'.format(host)
+            self.assertEqual(sanitize_redirect(allowed_hosts, url), url)
+
+    def test_multiple_hosts_wrong_host(self):
+        self.assertEqual(sanitize_redirect(
+            ['myapp1.com', 'myapp2.com'], 'http://notmyapp.com/path/'), None)
 
 
 class UserIsAuthenticatedTest(unittest.TestCase):
diff --git a/social/utils.py b/social/utils.py
index 0b5a507..c70db52 100644
--- a/social/utils.py
+++ b/social/utils.py
@@ -81,21 +81,21 @@ def setting_name(*names):
     return to_setting_name(*((SETTING_PREFIX,) + names))
 
 
-def sanitize_redirect(host, redirect_to):
+def sanitize_redirect(hosts, redirect_to):
     """
-    Given the hostname and an untrusted URL to redirect to,
+    Given a list of hostnames and an untrusted URL to redirect to,
     this method tests it to make sure it isn't garbage/harmful
     and returns it, else returns None, similar as how's it done
     on django.contrib.auth.views.
     """
     if redirect_to:
         try:
-            # Don't redirect to a different host
-            netloc = urlparse(redirect_to)[1] or host
+            # Don't redirect to a host not in a list
+            netloc = urlparse(redirect_to)[1] or hosts[0]
         except (TypeError, AttributeError):
             pass
         else:
-            if netloc == host:
+            if netloc in hosts:
                 return redirect_to
 
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-social-auth.git



More information about the Python-modules-commits mailing list