This is an automated email from the ASF dual-hosted git repository. gcruz pushed a commit to branch gc/8414 in repository https://gitbox.apache.org/repos/asf/allura.git
commit 8b4662065abd0f2c5b0932ef20a50908cca54b2b Author: Guillermo Cruz <[email protected]> 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 | 8 +++++++ ForgeSVN/forgesvn/widgets.py | 2 +- 5 files changed, 55 insertions(+), 3 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..6ea2059 100644 --- a/ForgeSVN/forgesvn/tests/functional/test_controllers.py +++ b/ForgeSVN/forgesvn/tests/functional/test_controllers.py @@ -318,6 +318,14 @@ 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): + #r = self.app.get('/p/test/admin/empty/importer').follow(status=200) + 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): 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
