mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[5.0.x] Fixed CVE-2024-41991 -- Prevented potential ReDoS in django.utils.html.urlize() and AdminURLFieldWidget.
Thanks Seokchan Yoon for the report. Co-authored-by: Sarah Boyce <42296566+sarahboyce@users.noreply.github.com>
This commit is contained in:
		
				
					committed by
					
						 Sarah Boyce
						Sarah Boyce
					
				
			
			
				
	
			
			
			
						parent
						
							7b7b909579
						
					
				
				
					commit
					523da8771b
				
			| @@ -390,7 +390,7 @@ class AdminURLFieldWidget(forms.URLInput): | ||||
|         context["current_label"] = _("Currently:") | ||||
|         context["change_label"] = _("Change:") | ||||
|         context["widget"]["href"] = ( | ||||
|             smart_urlquote(context["widget"]["value"]) if value else "" | ||||
|             smart_urlquote(context["widget"]["value"]) if url_valid else "" | ||||
|         ) | ||||
|         context["url_valid"] = url_valid | ||||
|         return context | ||||
|   | ||||
| @@ -36,6 +36,8 @@ VOID_ELEMENTS = { | ||||
|     "spacer", | ||||
| } | ||||
|  | ||||
| MAX_URL_LENGTH = 2048 | ||||
|  | ||||
|  | ||||
| @keep_lazy(SafeString) | ||||
| def escape(text): | ||||
| @@ -330,9 +332,9 @@ class Urlizer: | ||||
|             # Make URL we want to point to. | ||||
|             url = None | ||||
|             nofollow_attr = ' rel="nofollow"' if nofollow else "" | ||||
|             if self.simple_url_re.match(middle): | ||||
|             if len(middle) <= MAX_URL_LENGTH and self.simple_url_re.match(middle): | ||||
|                 url = smart_urlquote(html.unescape(middle)) | ||||
|             elif self.simple_url_2_re.match(middle): | ||||
|             elif len(middle) <= MAX_URL_LENGTH and self.simple_url_2_re.match(middle): | ||||
|                 url = smart_urlquote("http://%s" % html.unescape(middle)) | ||||
|             elif ":" not in middle and self.is_email_simple(middle): | ||||
|                 local, domain = middle.rsplit("@", 1) | ||||
| @@ -447,6 +449,10 @@ class Urlizer: | ||||
|         except ValueError: | ||||
|             # value contains more than one @. | ||||
|             return False | ||||
|         # Max length for domain name labels is 63 characters per RFC 1034. | ||||
|         # Helps to avoid ReDoS vectors in the domain part. | ||||
|         if len(p2) > 63: | ||||
|             return False | ||||
|         # Dot must be in p2 (e.g. example.com) | ||||
|         if "." not in p2 or p2.startswith("."): | ||||
|             return False | ||||
|   | ||||
| @@ -23,6 +23,13 @@ CVE-2024-41990: Potential denial-of-service vulnerability in ``django.utils.html | ||||
| denial-of-service attack via very large inputs with a specific sequence of | ||||
| characters. | ||||
|  | ||||
| CVE-2024-41991: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` and ``AdminURLFieldWidget`` | ||||
| ======================================================================================================================= | ||||
|  | ||||
| :tfilter:`urlize`, :tfilter:`urlizetrunc`, and ``AdminURLFieldWidget`` were | ||||
| subject to a potential denial-of-service attack via certain inputs with a very | ||||
| large number of Unicode characters. | ||||
|  | ||||
| Bugfixes | ||||
| ======== | ||||
|  | ||||
|   | ||||
| @@ -23,6 +23,13 @@ CVE-2024-41990: Potential denial-of-service vulnerability in ``django.utils.html | ||||
| denial-of-service attack via very large inputs with a specific sequence of | ||||
| characters. | ||||
|  | ||||
| CVE-2024-41991: Potential denial-of-service vulnerability in ``django.utils.html.urlize()`` and ``AdminURLFieldWidget`` | ||||
| ======================================================================================================================= | ||||
|  | ||||
| :tfilter:`urlize`, :tfilter:`urlizetrunc`, and ``AdminURLFieldWidget`` were | ||||
| subject to a potential denial-of-service attack via certain inputs with a very | ||||
| large number of Unicode characters. | ||||
|  | ||||
| Bugfixes | ||||
| ======== | ||||
|  | ||||
|   | ||||
| @@ -462,7 +462,12 @@ class AdminSplitDateTimeWidgetTest(SimpleTestCase): | ||||
| class AdminURLWidgetTest(SimpleTestCase): | ||||
|     def test_get_context_validates_url(self): | ||||
|         w = widgets.AdminURLFieldWidget() | ||||
|         for invalid in ["", "/not/a/full/url/", 'javascript:alert("Danger XSS!")']: | ||||
|         for invalid in [ | ||||
|             "", | ||||
|             "/not/a/full/url/", | ||||
|             'javascript:alert("Danger XSS!")', | ||||
|             "http://" + "한.글." * 1_000_000 + "com", | ||||
|         ]: | ||||
|             with self.subTest(url=invalid): | ||||
|                 self.assertFalse(w.get_context("name", invalid, {})["url_valid"]) | ||||
|         self.assertTrue(w.get_context("name", "http://example.com", {})["url_valid"]) | ||||
|   | ||||
| @@ -338,6 +338,15 @@ class TestUtilsHtml(SimpleTestCase): | ||||
|                 'Search for <a href="http://google.com/?q=">google.com/?q=</a>!', | ||||
|             ), | ||||
|             ("foo@example.com", '<a href="mailto:foo@example.com">foo@example.com</a>'), | ||||
|             ( | ||||
|                 "test@" + "한.글." * 15 + "aaa", | ||||
|                 '<a href="mailto:test@' | ||||
|                 + "xn--6q8b.xn--bj0b." * 15 | ||||
|                 + 'aaa">' | ||||
|                 + "test@" | ||||
|                 + "한.글." * 15 | ||||
|                 + "aaa</a>", | ||||
|             ), | ||||
|         ) | ||||
|         for value, output in tests: | ||||
|             with self.subTest(value=value): | ||||
| @@ -346,6 +355,10 @@ class TestUtilsHtml(SimpleTestCase): | ||||
|     def test_urlize_unchanged_inputs(self): | ||||
|         tests = ( | ||||
|             ("a" + "@a" * 50000) + "a",  # simple_email_re catastrophic test | ||||
|             # Unicode domain catastrophic tests. | ||||
|             "a@" + "한.글." * 1_000_000 + "a", | ||||
|             "http://" + "한.글." * 1_000_000 + "com", | ||||
|             "www." + "한.글." * 1_000_000 + "com", | ||||
|             ("a" + "." * 1000000) + "a",  # trailing_punctuation catastrophic test | ||||
|             "foo@", | ||||
|             "@foo.com", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user