VAITP Dataset

← Back to the dataset

CVE-2026-33332

Unvalidated parameter in NiceGUI media streaming causes memory exhaustion DoS.

  • CVSS 6.9
  • CWE-20
  • Resource Management
  • Remote

NiceGUI is a Python-based UI framework. Prior to version 3.9.0, NiceGUI's app.add_media_file() and app.add_media_files() media routes accept a user-controlled query parameter that influences how files are read during streaming. The parameter is passed to the range-response implementation without validation, allowing an attacker to bypass chunked streaming and force the server to load entire files into memory at once. With large media files and concurrent requests, this can lead to excessive memory consumption, degraded performance, or denial of service. This issue has been patched in version 3.9.0.

CVSS base score
6.9
Published
2026-03-24
OWASP
A04 Insecure Design
Orthogonal defect classification
Checking
Code defect classification
Missing Check
Category
Resource Management
Subcategory
Resource Exhaustion
Accessibility scope
Remote
Impact
Denial of Service (DoS)
Affected component
NiceGUI
Fixed by upgrading
Yes

Solution

Upgrade to NiceGUI version 1.4.1 or later.

Vulnerable code sample

import os
from pathlib import Path
from fastapi import Request
from fastapi.responses import Response, FileResponse
from nicegui import app, ui

DUMMY_FILE_PATH = Path("large_vulnerable_file.bin")
DUMMY_FILE_SIZE = 100 * 1024 * 1024  # 100 MB

if not DUMMY_FILE_PATH.exists():
    print(f"Creating a {DUMMY_FILE_SIZE // 1024 // 1024}MB dummy file...")
    with open(DUMMY_FILE_PATH, "wb") as f:
        f.write(os.urandom(DUMMY_FILE_SIZE))
    print("Dummy file created.")

# The following custom route simulates the vulnerable logic that existed
# in NiceGUI's internal media file handling prior to version 3.9.0.
# The vulnerability was that a user-controlled query parameter could
# bypass the intended streaming response.
@app.get("/media")
async def vulnerable_media_endpoint(request: Request):
    # An attacker provides a query parameter, here simulated as 'bypass_chunking'.
    # The vulnerable code path is triggered without proper validation.
    if "bypass_chunking" in request.query_params:
        # VULNERABLE PATH: The entire file is read into server memory at once.
        # Concurrent requests will lead to high memory usage and DoS.
        with open(DUMMY_FILE_PATH, "rb") as f:
            content = f.read()
        return Response(content, media_type="application/octet-stream")
    
    # NORMAL PATH: The file is streamed using FileResponse, which properly
    # handles HTTP Range requests for efficient delivery of large files.
    else:
        return FileResponse(DUMMY_FILE_PATH)

# UI to provide links for demonstrating the vulnerability.
ui.label("Demonstration of CVE-2026-33332")
ui.link(
    "Access file normally (safe, streaming)",
    "/media",
    new_tab=True
)
ui.link(
    "Access file with exploit (VULNERABLE, loads 100MB into server RAM)",
    "/media?bypass_chunking=true",
    new_tab=True,
)

ui.run()

Patched code sample

import re
from pathlib import Path

from fastapi import Request, Response
from fastapi.responses import FileResponse
from range_response import range_response


def patched_media_file_request_handler(request: Request, filepath: Path) -> Response:
    """
    A function representing the fixed request handler for media files in NiceGUI,
    demonstrating the patch for CVE-2024-33332.
    """
    if not filepath.is_file():
        return Response(content='Not Found', status_code=404)

    range_header = request.headers.get('Range')

    # This check is also part of the routing logic to avoid issues with range-response
    if 'If-Range' in request.headers or 'If-Match' in request.headers:
        range_header = None

    if range_header:
        # THE FIX: The 'Range' header is sanitized to allow only characters
        # that are valid for a range request. This prevents a malformed header
        # from being passed to the range_response library, which could be
        # exploited to force the server to load the entire file into memory.
        range_header = re.sub(r'[^_=\-,/\d]', '', range_header)

        # The actual implementation in NiceGUI modifies the request's internal
        # header list to use the sanitized value. This is a conceptual
        # representation of that process.
        mutable_headers = request.headers.mutablecopy()
        mutable_headers['range'] = range_header
        request.scope['headers'] = mutable_headers.raw

        try:
            # The range_response function now safely processes the request
            # using the sanitized 'Range' header.
            return range_response(filepath, start=0, end=0, request=request)
        except (FileNotFoundError, ValueError):
            return Response(content='Not Found', status_code=404)

    return FileResponse(filepath)

Payload

/_nicegui/media/large_file.mp4?range=bytes=a-b

Cite this entry

@misc{vaitp:cve202633332,
  title        = {{Unvalidated parameter in NiceGUI media streaming causes memory exhaustion DoS.}},
  author       = {Bogaerts, Fr\'ed\'eric and Ivaki, Naghmeh and Fonseca, Jos\'e},
  year         = {2026},
  note         = {VAITP Python Vulnerability Dataset, entry CVE-2026-33332},
  howpublished = {\url{https://netpack.pt/vaitp/vulnerability/CVE-2026-33332/}}
}
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 ::