VYPR
Low severityOSV Advisory· Published Feb 3, 2026· Updated Feb 3, 2026

Potential denial-of-service vulnerability via repeated headers when using ASGI

CVE-2025-14550

Description

An issue was discovered in 6.0 before 6.0.2, 5.2 before 5.2.11, and 4.2 before 4.2.28. ASGIRequest allows a remote attacker to cause a potential denial-of-service via a crafted request with multiple duplicate headers. Earlier, unsupported Django series (such as 5.0.x, 4.1.x, and 3.2.x) were not evaluated and may also be affected. Django would like to thank Jiyong Yang for reporting this issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
DjangoPyPI
>= 6.0a1, < 6.0.26.0.2
DjangoPyPI
>= 5.2a1, < 5.2.115.2.11
DjangoPyPI
>= 4.2a1, < 4.2.284.2.28

Affected products

1

Patches

1
eb22e1d6d643

Fixed CVE-2025-14550 -- Optimized repeated header parsing in ASGI requests.

https://github.com/django/djangoJake HowardJan 14, 2026via ghsa
5 files changed · +69 6
  • django/core/handlers/asgi.py+6 5 modified
    @@ -3,6 +3,7 @@
     import sys
     import tempfile
     import traceback
    +from collections import defaultdict
     from contextlib import aclosing, closing
     
     from asgiref.sync import ThreadSensitiveContext, sync_to_async
    @@ -83,6 +84,7 @@ def __init__(self, scope, body_file):
                 self.META["SERVER_NAME"] = "unknown"
                 self.META["SERVER_PORT"] = "0"
             # Headers go into META.
    +        _headers = defaultdict(list)
             for name, value in self.scope.get("headers", []):
                 name = name.decode("latin1")
                 if name == "content-length":
    @@ -96,11 +98,10 @@ def __init__(self, scope, body_file):
                 value = value.decode("latin1")
                 if corrected_name == "HTTP_COOKIE":
                     value = value.rstrip("; ")
    -                if "HTTP_COOKIE" in self.META:
    -                    value = self.META[corrected_name] + "; " + value
    -            elif corrected_name in self.META:
    -                value = self.META[corrected_name] + "," + value
    -            self.META[corrected_name] = value
    +            _headers[corrected_name].append(value)
    +        if cookie_header := _headers.pop("HTTP_COOKIE", None):
    +            self.META["HTTP_COOKIE"] = "; ".join(cookie_header)
    +        self.META.update({name: ",".join(value) for name, value in _headers.items()})
             # Pull out request encoding, if provided.
             self._set_content_type_params(self.META)
             # Directly assign the body file to be our stream.
    
  • docs/releases/4.2.28.txt+12 0 modified
    @@ -17,3 +17,15 @@ allowed remote attackers to enumerate users via a timing attack.
     
     This issue has severity "low" according to the :ref:`Django security policy
     <security-disclosure>`.
    +
    +CVE-2025-14550: Potential denial-of-service vulnerability via repeated headers when using ASGI
    +==============================================================================================
    +
    +When receiving duplicates of a single header, ``ASGIRequest`` allowed a remote
    +attacker to cause a potential denial-of-service via a specifically created
    +request with multiple duplicate headers. The vulnerability resulted from
    +repeated string concatenation while combining repeated headers, which
    +produced super-linear computation resulting in service degradation or outage.
    +
    +This issue has severity "moderate" according to the :ref:`Django security
    +policy <security-disclosure>`.
    
  • docs/releases/5.2.11.txt+12 0 modified
    @@ -17,3 +17,15 @@ allowed remote attackers to enumerate users via a timing attack.
     
     This issue has severity "low" according to the :ref:`Django security policy
     <security-disclosure>`.
    +
    +CVE-2025-14550: Potential denial-of-service vulnerability via repeated headers when using ASGI
    +==============================================================================================
    +
    +When receiving duplicates of a single header, ``ASGIRequest`` allowed a remote
    +attacker to cause a potential denial-of-service via a specifically created
    +request with multiple duplicate headers. The vulnerability resulted from
    +repeated string concatenation while combining repeated headers, which
    +produced super-linear computation resulting in service degradation or outage.
    +
    +This issue has severity "moderate" according to the :ref:`Django security
    +policy <security-disclosure>`.
    
  • docs/releases/6.0.2.txt+12 0 modified
    @@ -18,6 +18,18 @@ allowed remote attackers to enumerate users via a timing attack.
     This issue has severity "low" according to the :ref:`Django security policy
     <security-disclosure>`.
     
    +CVE-2025-14550: Potential denial-of-service vulnerability via repeated headers when using ASGI
    +==============================================================================================
    +
    +When receiving duplicates of a single header, ``ASGIRequest`` allowed a remote
    +attacker to cause a potential denial-of-service via a specifically created
    +request with multiple duplicate headers. The vulnerability resulted from
    +repeated string concatenation while combining repeated headers, which
    +produced super-linear computation resulting in service degradation or outage.
    +
    +This issue has severity "moderate" according to the :ref:`Django security
    +policy <security-disclosure>`.
    +
     Bugfixes
     ========
     
    
  • tests/asgi/tests.py+27 1 modified
    @@ -223,7 +223,7 @@ async def test_post_body(self):
             self.assertEqual(response_body["type"], "http.response.body")
             self.assertEqual(response_body["body"], b"Echo!")
     
    -    async def test_create_request_error(self):
    +    async def test_request_too_big_request_error(self):
             # Track request_finished signal.
             signal_handler = SignalHandler()
             request_finished.connect(signal_handler)
    @@ -254,6 +254,32 @@ class TestASGIHandler(ASGIHandler):
                 signal_handler.calls[0]["thread"], threading.current_thread()
             )
     
    +    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_cancel_post_request_with_sync_processing(self):
             """
             The request.body object should be available and readable in view
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

1