You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by di...@apache.org on 2022/02/28 18:52:44 UTC

[allura] branch master updated: 8414 Added a new validator to restrict private/internal ips from being submitted in the form

This is an automated email from the ASF dual-hosted git repository.

dill0wn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/allura.git


The following commit(s) were added to refs/heads/master by this push:
     new a8e4aee  8414 Added a new validator to restrict private/internal ips from being submitted in the form
a8e4aee is described below

commit a8e4aeed65e8be2d3904303ea70b74829a182195
Author: Guillermo Cruz <gu...@slashdotmedia.com>
AuthorDate: Thu Feb 24 10:29:26 2022 -0700

    8414 Added a new validator to restrict private/internal ips from being submitted in the form
---
 Allura/allura/lib/validators.py                    | 18 ++++++++++++++
 ForgeImporters/forgeimporters/trac/__init__.py     |  2 +-
 .../forgeimporters/trac/tests/test_tickets.py      | 28 +++++++++++++++++++++-
 .../forgesvn/tests/functional/test_controllers.py  |  9 ++++++-
 ForgeSVN/forgesvn/widgets.py                       |  2 +-
 5 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/Allura/allura/lib/validators.py b/Allura/allura/lib/validators.py
index e7b2ec7..f49d636 100644
--- a/Allura/allura/lib/validators.py
+++ b/Allura/allura/lib/validators.py
@@ -26,6 +26,9 @@ from tg import tmpl_context as c
 from . import helpers as h
 from datetime import datetime
 import six
+from urllib.parse import urlparse
+from ipaddress import ip_address
+import socket
 
 
 class URL(fev.URL):
@@ -47,6 +50,21 @@ class URL(fev.URL):
     ''', re.I | re.VERBOSE)
 
 
+class URLIsPrivate(URL):
+
+    def _to_python(self, value, state):
+        value = super(URLIsPrivate, self)._to_python(value, state)
+        url_components = urlparse(value)
+        try:
+            host_ip = socket.gethostbyname(url_components.netloc)
+        except socket.gaierror:
+            raise fev.Invalid("Invalid URL.", value, state)
+        parse_ip = ip_address(host_ip)
+        if parse_ip and parse_ip.is_private:
+            raise fev.Invalid("Invalid URL.", value, state)
+        return value
+
+
 class NonHttpUrl(URL):
     messages = {
         'noScheme': 'You must start your URL with a scheme',
diff --git a/ForgeImporters/forgeimporters/trac/__init__.py b/ForgeImporters/forgeimporters/trac/__init__.py
index 3a0949d..5fffd77 100644
--- a/ForgeImporters/forgeimporters/trac/__init__.py
+++ b/ForgeImporters/forgeimporters/trac/__init__.py
@@ -23,7 +23,7 @@ import requests
 from allura.lib import validators
 
 
-class TracURLValidator(validators.URL):
+class TracURLValidator(validators.URLIsPrivate):
     not_empty = True
     messages = {
         'unavailable': 'This project is unavailable for import'
diff --git a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
index 0b010e0..f421d11 100644
--- a/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
+++ b/ForgeImporters/forgeimporters/trac/tests/test_tickets.py
@@ -26,7 +26,7 @@ from ming.orm import ThreadLocalORMSession
 from tg import tmpl_context as c
 
 from allura.tests import TestController
-from allura.tests.decorators import with_tracker
+from allura.tests.decorators import with_tracker, with_wiki
 from alluratest.controller import TestRestApiBase, setup_unit_test
 from alluratest.tools import module_not_available
 
@@ -185,6 +185,32 @@ class TestTracTicketImportController(TestController, TestCase):
                           )])
         self.assertEqual(import_tool.post.call_count, 0)
 
+        @with_tracker
+        @patch('forgeimporters.trac.requests.head')
+        @patch('forgeimporters.base.import_tool')
+        def test_url_ticket_import_fail(self, import_tool, head):
+            head.return_value.status_code = 200
+            params = dict(trac_url='https://sf-1.xb.sf.net/trac/url',
+                          mount_label='mylabel',
+                          mount_point='mymount',
+                          )
+            r = self.app.post('/p/test/admin/ext/import/trac-tickets-sf/create', params,
+                              status=200)
+            self.assertIn('Invalid URL', r.text)
+
+        @with_wiki
+        @patch('forgeimporters.trac.requests.head')
+        @patch('forgeimporters.base.import_tool')
+        def test_url_wiki_import_fail(self, import_tool, head):
+            head.return_value.status_code = 200
+            params = dict(trac_url='https://sf-1.xb.sf.net/trac/url',
+                          mount_label='mylabel',
+                          mount_point='mymount',
+                          )
+            r = self.app.post('/p/test/admin/ext/import/trac-wiki/create', params,
+                              status=200)
+            self.assertIn('Invalid URL', r.text)
+
 
 class TestTracImportSupport(TestCase):
 
diff --git a/ForgeSVN/forgesvn/tests/functional/test_controllers.py b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
index 99100f3..197f912 100644
--- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py
+++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py
@@ -318,11 +318,18 @@ class TestImportController(SVNTestController):
         r = self.app.get('/p/test/admin/empty/importer').follow(status=200)
         assert 'Enter the URL of the source repository below' in r
 
+    @with_tool('test', 'SVN', 'empty', 'empty SVN')
+    def test_url_import_validation_fail(self):
+        params = dict(checkout_url='https://sf-1.xb.sf.net/trac/url')
+        r = self.app.post('/p/test/admin/empty/importer/do_import', params,
+                          status=200)
+        assert 'Invalid URL' in r.text
+
     @patch('forgesvn.svn_main.allura.tasks.repo_tasks')
     @with_tool('test', 'SVN', 'empty', 'empty SVN')
     def test_do_import_empty_repo(self, tasks):
         self.app.post('/p/test/admin/empty/importer/do_import',
-                      {'checkout_url': 'http://fake.svn/'})
+                      {'checkout_url': 'http://github.com/'})
         assert tasks.reclone.post.called
 
     @patch('forgesvn.svn_main.allura.tasks.repo_tasks')
diff --git a/ForgeSVN/forgesvn/widgets.py b/ForgeSVN/forgesvn/widgets.py
index 69ce307..849d183 100644
--- a/ForgeSVN/forgesvn/widgets.py
+++ b/ForgeSVN/forgesvn/widgets.py
@@ -26,7 +26,7 @@ from allura.lib import validators
 from allura.lib.widgets.forms import ForgeForm
 
 
-class ValidateSvnUrl(validators.URL):
+class ValidateSvnUrl(validators.URLIsPrivate):
     url_re = re.compile(r'''
         ^(http|https|svn)://
         (?:[%:\w]*@)?                              # authenticator