这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Jul 22, 2025

This PR contains the following updates:

Package Change Age Confidence
starlette (changelog) ==0.41.3 -> ==0.49.1 age confidence

GitHub Vulnerability Alerts

CVE-2025-54121

Summary

When parsing a multi-part form with large files (greater than the default max spool size) starlette will block the main thread to roll the file over to disk. This blocks the event thread which means we can't accept new connections.

Details

Please see this discussion for details: https://github.com/encode/starlette/discussions/2927#discussioncomment-13721403. In summary the following UploadFile code (copied from here) has a minor bug. Instead of just checking for self._in_memory we should also check if the additional bytes will cause a rollover.

    @​property
    def _in_memory(self) -> bool:
        # check for SpooledTemporaryFile._rolled
        rolled_to_disk = getattr(self.file, "_rolled", True)
        return not rolled_to_disk

    async def write(self, data: bytes) -> None:
        if self.size is not None:
            self.size += len(data)

        if self._in_memory:
            self.file.write(data)
        else:
            await run_in_threadpool(self.file.write, data)

I have already created a PR which fixes the problem: https://github.com/encode/starlette/pull/2962

PoC

See the discussion here for steps on how to reproduce.

Impact

To be honest, very low and not many users will be impacted. Parsing large forms is already CPU intensive so the additional IO block doesn't slow down starlette that much on systems with modern HDDs/SSDs. If someone is running on tape they might see a greater impact.

CVE-2025-62727

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.


Release Notes

Kludex/starlette (starlette)

v0.49.1: Version 0.49.1

Compare Source

This release fixes a security vulnerability in the parsing logic of the Range header in FileResponse.

You can view the full security advisory: GHSA-7f5h-v6xp-fcq8

Fixed


Full Changelog: Kludex/starlette@0.49.0...0.49.1

v0.49.0: Version 0.49.0

Compare Source

Added

  • Add encoding parameter to Config class #​2996.
  • Support multiple cookie headers in Request.cookies #​3029.
  • Use Literal type for WebSocketEndpoint encoding values #​3027.

Changed

  • Do not pollute exception context in Middleware when using BaseHTTPMiddleware #​2976.

New Contributors

Full Changelog: Kludex/starlette@0.48.0...0.49.0

v0.48.0: Version 0.48.0

Compare Source

Added

  • Add official Python 3.14 support #​3013.

Changed


New Contributors

Full Changelog: Kludex/starlette@0.47.3...0.48.0

v0.47.3: Version 0.47.3

Compare Source

Fixed


New Contributors

Full Changelog: Kludex/starlette@0.47.2...0.47.3

v0.47.2

Compare Source

Fixed

  • Make UploadFile check for future rollover #​2962.

New Contributors

Full Changelog: Kludex/starlette@0.47.1...0.47.2

v0.47.1: Version 0.47.1

Compare Source

Fixed

  • Use Self in TestClient.__enter__ #​2951
  • Allow async exception handlers to type-check #​2949

Full Changelog: Kludex/starlette@0.47.0...0.47.1

v0.47.0: Version 0.47.0

Compare Source

Added

  • Add support for ASGI pathsend extension #​2671.
  • Add partitioned attribute to Response.set_cookie #​2501.

Changed

  • Change methods parameter type from list[str] to Collection[str] #​2903.
  • Replace import typing by from typing import ... in the whole codebase #​2867.

Fixed

  • Mark ExceptionMiddleware.http_exception as async to prevent thread creation #​2922.

New Contributors

Full Changelog: Kludex/starlette@0.46.2...0.47.0

v0.46.2: Version 0.46.2

Compare Source

What's Changed

New Contributors

Full Changelog: Kludex/starlette@0.46.1...0.46.2

v0.46.1: Version 0.46.1

Compare Source

Fixed

  • Allow relative directory path when follow_symlinks=True #​2896.

Full Changelog: Kludex/starlette@0.46.0...0.46.1

v0.46.0: Version 0.46.0

Compare Source

Added

  • GZipMiddleware: Make sure Vary header is always added if a response can be compressed #​2865.

Fixed

  • Raise exception from background task on BaseHTTPMiddleware #​2812.
  • GZipMiddleware: Don't compress on server sent events #​2871.

Changed

  • MultiPartParser: Rename max_file_size to spool_max_size #​2780.

Deprecated

  • Add deprecated warning to TestClient(timeout=...) #​2840.

New Contributors

Full Changelog: Kludex/starlette@0.45.3...0.46.0

v0.45.3: Version 0.45.3

Compare Source

Fixed


Full Changelog: Kludex/starlette@0.45.2...0.45.3

v0.45.2: Version 0.45.2

Compare Source

Fixed
  • Make create_memory_object_stream compatible with old anyio versions once again, and bump anyio minimum version to 3.6.2 by @​graingert in #​2833.

Full Changelog: Kludex/starlette@0.45.1...0.45.2

v0.45.1: Version 0.45.1

Compare Source

Fixed
Refactor

Full Changelog: Kludex/starlette@0.45.0...0.45.1

v0.45.0: Version 0.45.0

Compare Source

Removed


Full Changelog: Kludex/starlette@0.44.0...0.45.0

v0.44.0: Version 0.44.0

Compare Source

Added

New Contributors

Full Changelog: Kludex/starlette@0.43.0...0.44.0

v0.43.0: Version 0.43.0

Compare Source

Removed

  • Remove deprecated allow_redirects argument from TestClient #​2808.

Added

  • Make UUID path parameter conversion more flexible #​2806.

New Contributors

Full Changelog: Kludex/starlette@0.42.0...0.43.0

v0.42.0: Version 0.42.0

Compare Source

Added

  • Raise ClientDisconnect on StreamingResponse #​2732.

Fixed

  • Use ETag from headers when parsing If-Range in FileResponse #​2761.
  • Follow directory symlinks in StaticFiles when follow_symlinks=True #​2711.
  • Bump minimum python-multipart version to 0.0.18 0ba8395.
  • Bump minimum httpx version to 0.27.0 #​2773.

New Contributors

Full Changelog: Kludex/starlette@0.41.3...0.42.0


Configuration

📅 Schedule: Branch creation - "" (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@bolt-new-by-stackblitz
Copy link

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@renovate renovate bot force-pushed the renovate/pypi-starlette-vulnerability branch from 861a948 to 5def497 Compare October 29, 2025 00:46
@renovate renovate bot changed the title chore(deps): update dependency starlette to v0.47.2 [security] chore(deps): update dependency starlette to v0.49.1 [security] Oct 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants