summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJake Howard <git@theorangeone.net>2026-01-14 15:25:45 +0000
committerJacob Walls <jacobtylerwalls@gmail.com>2026-02-03 08:24:42 -0500
commitf578acc8c54530fffabd52d2db654c8669b011af (patch)
treecefccf69ba78097e45739c0a4fd61d8d05207451 /tests
parent6dc23508f3395e1254c315084c7334ef81c4c09a (diff)
[4.2.x] Fixed CVE-2025-14550 -- Optimized repeated header parsing in ASGI requests.
Thanks Jiyong Yang for the report, and Natalia Bidart, Jacob Walls, and Shai Berger for reviews. Backport of eb22e1d6d643360e952609ef562c139a100ea4eb from main.
Diffstat (limited to 'tests')
-rw-r--r--tests/asgi/tests.py27
1 files changed, 27 insertions, 0 deletions
diff --git a/tests/asgi/tests.py b/tests/asgi/tests.py
index f2e293d8bc..9395c8626c 100644
--- a/tests/asgi/tests.py
+++ b/tests/asgi/tests.py
@@ -7,6 +7,7 @@ from asgiref.testing import ApplicationCommunicator
from django.contrib.staticfiles.handlers import ASGIStaticFilesHandler
from django.core.asgi import get_asgi_application
+from django.core.handlers.asgi import ASGIRequest
from django.core.signals import request_finished, request_started
from django.db import close_old_connections
from django.test import (
@@ -193,6 +194,32 @@ class ASGITest(SimpleTestCase):
self.assertEqual(response_body["type"], "http.response.body")
self.assertEqual(response_body["body"], b"Echo!")
+ async def test_meta_not_modified_with_repeat_headers(self):
+ scope = self.async_request_factory._base_scope(path="/", http_version="2.0")
+ scope["headers"] = [(b"foo", b"bar")] * 200_000
+
+ setitem_count = 0
+
+ class InstrumentedDict(dict):
+ def __setitem__(self, *args, **kwargs):
+ nonlocal setitem_count
+ setitem_count += 1
+ super().__setitem__(*args, **kwargs)
+
+ class InstrumentedASGIRequest(ASGIRequest):
+ @property
+ def META(self):
+ return self._meta
+
+ @META.setter
+ def META(self, value):
+ self._meta = InstrumentedDict(**value)
+
+ request = InstrumentedASGIRequest(scope, None)
+
+ self.assertEqual(len(request.headers["foo"].split(",")), 200_000)
+ self.assertLessEqual(setitem_count, 100)
+
async def test_untouched_request_body_gets_closed(self):
application = get_asgi_application()
scope = self.async_request_factory._base_scope(method="POST", path="/post/")