From 8204c7ddca508d8732687f5f8e3d1d2754ab57c8 Mon Sep 17 00:00:00 2001 From: Matthew Riley MacPherson Date: Fri, 3 Jun 2011 18:20:23 -0300 Subject: [PATCH] Don't allow private IP addresses (bug 638559) Throw a validation error if a private IP is used in the URL field. --- apps/feedback/forms.py | 2 ++ apps/feedback/tests/test_validators.py | 21 ++++++++++++++++++++- apps/feedback/validators.py | 18 ++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/apps/feedback/forms.py b/apps/feedback/forms.py index 2dda4a2e..a4af0585 100644 --- a/apps/feedback/forms.py +++ b/apps/feedback/forms.py @@ -12,6 +12,7 @@ from feedback.models import Opinion from feedback.validators import (validate_swearwords, validate_no_html, validate_no_email, validate_no_urls, + validate_no_private_ips, ExtendedURLValidator) @@ -24,6 +25,7 @@ def __init__(self, *args, **kwargs): # Remove old URL validator, add ours instead. self.validators = filter(lambda x: not isinstance(x, URLValidator), self.validators) + self.validators.append(validate_no_private_ips) self.validators.append(ExtendedURLValidator()) def to_python(self, value): diff --git a/apps/feedback/tests/test_validators.py b/apps/feedback/tests/test_validators.py index 4961aa87..e2543dcb 100644 --- a/apps/feedback/tests/test_validators.py +++ b/apps/feedback/tests/test_validators.py @@ -2,7 +2,8 @@ import test_utils -from feedback.validators import validate_no_urls, ExtendedURLValidator +from feedback.validators import (validate_no_urls, validate_no_private_ips, + ExtendedURLValidator) class ValidatorTests(test_utils.TestCase): @@ -18,6 +19,24 @@ def test_chrome_url(self): self.assertRaises(ValidationError, v, 'about:') self.assertRaises(ValidationError, v, 'chrome:bogus') + def test_private_ips_not_allowed(self): + """Make sure private IPs can't be submitted as URLs.""" + patterns = ( + ('https://mozilla.com', False), + ('http://tofumatt.com', False), + ('youtube.com', False), + ('0.0.0.0', True), + ('http://127.0.0.1', True), + ('HTTP://10.0.0.13', True), + ('https://192.168.0.4', True), + ) + for pattern in patterns: + if pattern[1]: + self.assertRaises(ValidationError, validate_no_private_ips, + pattern[0]) + else: + validate_no_private_ips(pattern[0]) + def test_url_in_text(self): """Find URLs in text.""" patterns = ( diff --git a/apps/feedback/validators.py b/apps/feedback/validators.py index b5fd3cdd..f767df40 100644 --- a/apps/feedback/validators.py +++ b/apps/feedback/validators.py @@ -14,6 +14,17 @@ # Simple email regex to keep people from submitting personal data. EMAIL_RE = re.compile(r'[^\s]+@[^\s]+\.[^\s]{2,6}') +# IPv4 Address verifier +PRIVATE_IP_RE = re.compile( + r'^(https?://)?' # http:// or https:// + r'(?:0\.0\.0\.0)|' + r'(?:127\.0)|' + r'(?:10\.)|' + r'(?:172\.1[6-9]\.)|' + r'(?:172\.2[0-9]\.)|' + r'(?:172\.3[0-1]\.)|' + r'(?:192\.168\.)', re.IGNORECASE) + # Simple "possibly a URL" regex URL_RE = re.compile(r'(://|www\.[^\s]|\.\w{2,}/)') @@ -45,6 +56,13 @@ def validate_no_email(str): 'Thanks!')) +def validate_no_private_ips(str): + """Disallow private IPv4 IPs from being submitted.""" + if PRIVATE_IP_RE.search(str): + raise ValidationError( + _('URLs with IP addresses must contain public IP addresses.')) + + def validate_no_urls(str): """Disallow text possibly containing a URL.""" if URL_RE.search(str):