VYPR
Moderate severityNVD Advisory· Published Nov 29, 2023· Updated Nov 4, 2025

aiohttp's ClientSession is vulnerable to CRLF injection via method

CVE-2023-49082

Description

aiohttp is an asynchronous HTTP client/server framework for asyncio and Python. Improper validation makes it possible for an attacker to modify the HTTP request (e.g. insert a new header) or even create a new HTTP request if the attacker controls the HTTP method. The vulnerability occurs only if the attacker can control the HTTP method (GET, POST etc.) of the request. If the attacker can control the HTTP version of the request it will be able to modify the request (request smuggling). This issue has been patched in version 3.9.0.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
aiohttpPyPI
< 3.9.03.9.0

Affected products

1

Patches

1
e4ae01c2077d

Add HTTP method validation (#6533) (#7806)

https://github.com/aio-libs/aiohttpSam BullNov 8, 2023via ghsa
4 files changed · +21 3
  • aiohttp/client_reqrep.py+8 1 modified
    @@ -81,6 +81,7 @@
         from .tracing import Trace
     
     
    +_CONTAINS_CONTROL_CHAR_RE = re.compile(r"[^-!#$%&'*+.^_`|~0-9a-zA-Z]")
     json_re = re.compile(r"^application/(?:[\w.+-]+?\+)?json")
     
     
    @@ -275,10 +276,16 @@ def __init__(
             trust_env: bool = False,
             server_hostname: Optional[str] = None,
         ):
    -
             if loop is None:
                 loop = asyncio.get_event_loop()
     
    +        match = _CONTAINS_CONTROL_CHAR_RE.search(method)
    +        if match:
    +            raise ValueError(
    +                f"Method cannot contain non-token characters {method!r} "
    +                "(found at least {match.group()!r})"
    +            )
    +
             assert isinstance(url, URL), url
             assert isinstance(proxy, (URL, type(None))), proxy
             # FIXME: session is None in tests only, need to fix tests
    
  • CHANGES/6533.feature+1 0 added
    @@ -0,0 +1 @@
    +Add HTTP method validation.
    
  • tests/test_client_request.py+5 0 modified
    @@ -89,6 +89,11 @@ def test_method3(make_request) -> None:
         assert req.method == "HEAD"
     
     
    +def test_method_invalid(make_request) -> None:
    +    with pytest.raises(ValueError, match="Method cannot contain non-token characters"):
    +        make_request("METHOD WITH\nWHITESPACES", "http://python.org/")
    +
    +
     def test_version_1_0(make_request) -> None:
         req = make_request("get", "http://python.org/", version="1.0")
         assert req.version == (1, 0)
    
  • tests/test_web_request.py+7 2 modified
    @@ -42,7 +42,10 @@ def test_base_ctor() -> None:
     
         assert "GET" == req.method
         assert HttpVersion(1, 1) == req.version
    -    assert req.host == socket.getfqdn()
    +    # MacOS may return CamelCased host name, need .lower()
    +    # FQDN can be wider than host, e.g.
    +    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'
    +    assert req.host.lower() in socket.getfqdn().lower()
         assert "/path/to?a=1&b=2" == req.path_qs
         assert "/path/to" == req.path
         assert "a=1&b=2" == req.query_string
    @@ -65,7 +68,9 @@ def test_ctor() -> None:
         assert "GET" == req.method
         assert HttpVersion(1, 1) == req.version
         # MacOS may return CamelCased host name, need .lower()
    -    assert req.host.lower() == socket.getfqdn().lower()
    +    # FQDN can be wider than host, e.g.
    +    # 'fv-az397-495' in 'fv-az397-495.internal.cloudapp.net'
    +    assert req.host.lower() in socket.getfqdn().lower()
         assert "/path/to?a=1&b=2" == req.path_qs
         assert "/path/to" == req.path
         assert "a=1&b=2" == req.query_string
    

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

10

News mentions

0

No linked articles in our index yet.