VYPR
Moderate severityNVD Advisory· Published Nov 18, 2024· Updated Nov 3, 2025

aiohttp vulnerable to request smuggling due to incorrect parsing of chunk extensions

CVE-2024-52304

Description

aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. Prior to version 3.10.11, the Python parser parses newlines in chunk extensions incorrectly which can lead to request smuggling vulnerabilities under certain conditions. If a pure Python version of aiohttp is installed (i.e. without the usual C extensions) or AIOHTTP_NO_EXTENSIONS is enabled, then an attacker may be able to execute a request smuggling attack to bypass certain firewalls or proxy protections. Version 3.10.11 fixes the issue.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
aiohttpPyPI
< 3.10.113.10.11

Affected products

1

Patches

1
259edc369075

[PR #9851/541d86d backport][3.10] Fix incorrect parsing of chunk extensions with the pure Python parser (#9853)

https://github.com/aio-libs/aiohttpJ. Nick KostonNov 13, 2024via ghsa
3 files changed · +58 1
  • aiohttp/http_parser.py+7 0 modified
    @@ -845,6 +845,13 @@ def feed_data(
                             i = chunk.find(CHUNK_EXT, 0, pos)
                             if i >= 0:
                                 size_b = chunk[:i]  # strip chunk-extensions
    +                            # Verify no LF in the chunk-extension
    +                            if b"\n" in (ext := chunk[i:pos]):
    +                                exc = BadHttpMessage(
    +                                    f"Unexpected LF in chunk-extension: {ext!r}"
    +                                )
    +                                set_exception(self.payload, exc)
    +                                raise exc
                             else:
                                 size_b = chunk[:pos]
     
    
  • CHANGES/9851.bugfix.rst+1 0 added
    @@ -0,0 +1 @@
    +Fixed incorrect parsing of chunk extensions with the pure Python parser -- by :user:`bdraco`.
    
  • tests/test_http_parser.py+50 1 modified
    @@ -13,6 +13,7 @@
     
     import aiohttp
     from aiohttp import http_exceptions, streams
    +from aiohttp.base_protocol import BaseProtocol
     from aiohttp.http_parser import (
         NO_EXTENSIONS,
         DeflateBuffer,
    @@ -1477,7 +1478,55 @@ async def test_parse_chunked_payload_split_chunks(response: Any) -> None:
         assert await reader.read() == b"firstsecond"
     
     
    -def test_partial_url(parser: Any) -> None:
    +@pytest.mark.skipif(NO_EXTENSIONS, reason="Only tests C parser.")
    +async def test_parse_chunked_payload_with_lf_in_extensions_c_parser(
    +    loop: asyncio.AbstractEventLoop, protocol: BaseProtocol
    +) -> None:
    +    """Test the C-parser with a chunked payload that has a LF in the chunk extensions."""
    +    # The C parser will raise a BadHttpMessage from feed_data
    +    parser = HttpRequestParserC(
    +        protocol,
    +        loop,
    +        2**16,
    +        max_line_size=8190,
    +        max_field_size=8190,
    +    )
    +    payload = (
    +        b"GET / HTTP/1.1\r\nHost: localhost:5001\r\n"
    +        b"Transfer-Encoding: chunked\r\n\r\n2;\nxx\r\n4c\r\n0\r\n\r\n"
    +        b"GET /admin HTTP/1.1\r\nHost: localhost:5001\r\n"
    +        b"Transfer-Encoding: chunked\r\n\r\n0\r\n\r\n"
    +    )
    +    with pytest.raises(http_exceptions.BadHttpMessage, match="\\\\nxx"):
    +        parser.feed_data(payload)
    +
    +
    +async def test_parse_chunked_payload_with_lf_in_extensions_py_parser(
    +    loop: asyncio.AbstractEventLoop, protocol: BaseProtocol
    +) -> None:
    +    """Test the py-parser with a chunked payload that has a LF in the chunk extensions."""
    +    # The py parser will not raise the BadHttpMessage directly, but instead
    +    # it will set the exception on the StreamReader.
    +    parser = HttpRequestParserPy(
    +        protocol,
    +        loop,
    +        2**16,
    +        max_line_size=8190,
    +        max_field_size=8190,
    +    )
    +    payload = (
    +        b"GET / HTTP/1.1\r\nHost: localhost:5001\r\n"
    +        b"Transfer-Encoding: chunked\r\n\r\n2;\nxx\r\n4c\r\n0\r\n\r\n"
    +        b"GET /admin HTTP/1.1\r\nHost: localhost:5001\r\n"
    +        b"Transfer-Encoding: chunked\r\n\r\n0\r\n\r\n"
    +    )
    +    messages, _, _ = parser.feed_data(payload)
    +    reader = messages[0][1]
    +    assert isinstance(reader.exception(), http_exceptions.BadHttpMessage)
    +    assert "\\nxx" in str(reader.exception())
    +
    +
    +def test_partial_url(parser: HttpRequestParser) -> None:
         messages, upgrade, tail = parser.feed_data(b"GET /te")
         assert len(messages) == 0
         messages, upgrade, tail = parser.feed_data(b"st HTTP/1.1\r\n\r\n")
    

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

5

News mentions

0

No linked articles in our index yet.