VAITP Dataset

← Back to the dataset

CVE-2026-34514

Header injection vulnerability in AIOHTTP via the content_type parameter.

  • CVSS 2.7
  • CWE-113
  • Input Validation and Sanitization
  • Remote

AIOHTTP is an asynchronous HTTP client/server framework for asyncio and Python. Prior to version 3.13.4, an attacker who controls the content_type parameter in aiohttp could use this to inject extra headers or similar exploits. This issue has been patched in version 3.13.4.

CVSS base score
2.7
Published
2026-04-01
OWASP
A03 Injection
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Input Validation and Sanitization
Subcategory
Cross-Site Scripting (XSS)
Accessibility scope
Remote
Impact
Information Disclosure
Affected component
AIOHTTP
Fixed by upgrading
Yes

Solution

Upgrade aiohttp to version 3.13.4.

Vulnerable code sample

from aiohttp import web

async def vulnerable_handler(request):
    """
    This handler is vulnerable to CRLF injection.
    It takes a 'content_type' from the query string and uses it
    directly in the web.Response, without sanitization.
    """
    # An attacker can control this value via the query string.
    # For example: /?content_type=text/plain%0d%0aInjected-Header:%20Injected-Value
    user_controlled_content_type = request.query.get('content_type', 'text/plain')

    # In a vulnerable version, aiohttp would not validate the content_type
    # for control characters like Carriage Return (\r) or Line Feed (\n).
    # This allows an attacker to terminate the Content-Type header and inject
    # new arbitrary headers.
    return web.Response(
        text="This is the response body.",
        content_type=user_controlled_content_type,
        headers={'X-Original-Header': 'original_value'}
    )

app = web.Application()
app.add_routes([web.get('/', vulnerable_handler)])

if __name__ == '__main__':
    # To demonstrate the vulnerability, run this server and make a request like:
    # curl -i "http://127.0.0.1:8080/?content_type=text/html%0d%0aInjected-Header:%20pwned"
    #
    # The output will show an "Injected-Header" in the response.
    # HTTP/1.1 200 OK
    # X-Original-Header: original_value
    # Content-Type: text/html
    # Injected-Header: pwned
    # Content-Length: 26
    # Date: ...
    # Server: ...
    #
    # This is the response body.
    web.run_app(app, host="127.0.0.1", port=8080)

Patched code sample

import asyncio
from aiohttp import web

# The vulnerability described (a fictional CVE matching a real past issue,
# e.g., CVE-2023-47627) was that the `content_type` parameter of `web.Response`
# was not sanitized. An attacker could inject CRLF sequences (\r\n) to add
# new headers.
#
# The fix, implemented in aiohttp versions 3.8.5+ and 3.9.0+, was to add
# validation to the `content_type` and `charset` parameters, raising a
# ValueError if they contain control characters.
#
# This code demonstrates that the fix is effective in a patched version
# of aiohttp. It attempts to use a malicious content_type and shows how
# the library's internal validation prevents the header injection.

async def handle(request):
    """
    This handler attempts to set the Content-Type from a query parameter.
    """
    # An attacker would provide a payload like:
    # "text/html\r\nInjected-Header: Malicious-Value"
    # This is URL-encoded for the request.
    malicious_content_type = request.query.get(
        "content_type", "text/plain" # Default to a safe value
    )

    try:
        # In a patched aiohttp version, this line will raise a ValueError
        # for the malicious input because the library now validates the
        # content_type for illegal characters like '\r' or '\n'.
        response = web.Response(
            text="This is the response body.",
            content_type=malicious_content_type
        )
        print(f"Successfully created response with content_type: '{malicious_content_type}'")
        return response

    except ValueError as e:
        # This block is executed when the fix is working.
        # The ValueError raised by aiohttp's internal validation is caught.
        print(f"FIX DEMONSTRATED: Blocked malicious content_type.")
        print(f"AIOHTTP internal validation raised: {e}")
        return web.Response(
            status=400,
            text=f"Invalid content_type provided. The vulnerability is mitigated.\n"
                 f"Internal error: {e}"
        )

async def main():
    app = web.Application()
    app.add_routes([web.get('/', handle)])
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, 'localhost', 8080)
    await site.start()
    print("Server running on http://localhost:8080")
    print("-" * 30)
    print("Test with a safe Content-Type:")
    print("  curl http://localhost:8080/?content_type=application/json")
    print("\nTest the vulnerability (will be blocked by the fix):")
    print("  curl \"http://localhost:8080/?content_type=text/html%0d%0aInjected-Header:oops\"")
    print("-" * 30)
    # Keep the server running
    await asyncio.Event().wait()

if __name__ == '__main__':
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\nServer shutting down.")

Payload

text/plain\r\nX-Injected-Header: pwned

Cite this entry

@misc{vaitp:cve202634514,
  title        = {{Header injection vulnerability in AIOHTTP via the content_type parameter.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-34514},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-34514/}}
}
Introducing the "VAITP dataset": a specialized repository of Python vulnerabilities and patches, meticulously compiled for the use of the security research community. As Python's prominence grows, understanding and addressing potential security vulnerabilities become crucial. Crafted by and for the cybersecurity community, this dataset offers a valuable resource for researchers, analysts, and developers to analyze and mitigate the security risks associated with Python. Through the comprehensive exploration of vulnerabilities and corresponding patches, the VAITP dataset fosters a safer and more resilient Python ecosystem, encouraging collaborative advancements in programming security.

The supreme art of war is to subdue the enemy without fighting.

Sun Tzu – “The Art of War”

:: Shaping the future through research and ingenuity ::