Skip to content

fix: bound response reads in preset catalog and download - #3778

Open
Quratulain-bilal wants to merge 4 commits into
github:mainfrom
Quratulain-bilal:fix/unbounded-presets-catalog-read
Open

fix: bound response reads in preset catalog and download#3778
Quratulain-bilal wants to merge 4 commits into
github:mainfrom
Quratulain-bilal:fix/unbounded-presets-catalog-read

Conversation

@Quratulain-bilal

@Quratulain-bilal Quratulain-bilal commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Replace unbounded
esponse.read()\ calls with
ead_response_limited()\ in \presets/init.py\ to prevent DoS via oversized catalog or preset archive responses.

Changes

Three call sites fixed:

  • _fetch_single_catalog\ JSON read (catalog metadata) - uses \MAX_JSON_METADATA_BYTES\ (1 MiB)
  • _fetch_catalog\ JSON read (legacy path) - uses \MAX_JSON_METADATA_BYTES\ (1 MiB)
  • \download_preset\ ZIP read (binary download) - uses \MAX_DOWNLOAD_BYTES\ (50 MiB)

Added \ rom .._download_security import MAX_DOWNLOAD_BYTES, MAX_JSON_METADATA_BYTES, read_response_limited.

Replace unbounded response.read() calls with read_response_limited()
in presets/__init__.py to prevent DoS via oversized catalog or preset
archive responses.

Three call sites fixed:
- _fetch_single_catalog JSON read (catalog metadata)
- _fetch_catalog JSON read (legacy path)
- download_preset ZIP read (binary download)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Bounds preset catalog and archive response reads to mitigate oversized-response DoS risks.

Changes:

  • Caps catalog JSON responses at 1 MiB.
  • Caps preset ZIP downloads at 50 MiB.
  • Reuses the shared bounded-response helper.
Show a summary per file
File Description
src/specify_cli/presets/__init__.py Adds bounded reads for catalogs and preset archives.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comments suppressed due to low confidence (1)

src/specify_cli/presets/init.py:4641

  • The download tests also use non-consuming read.return_value responses (tests/test_presets.py:2363-2364 and 2473-2474). With the bounded reader, each call replays the ZIP until the 50 MiB limit is hit, so matching-hash, no-hash, and direct-asset tests no longer reach their assertions. Convert these fixtures to consuming streams and add an oversized archive regression test that expects PresetError.
                zip_data = read_response_limited(response, max_bytes=MAX_DOWNLOAD_BYTES)
  • Files reviewed: 1/1 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread src/specify_cli/presets/__init__.py Outdated
Comment thread src/specify_cli/presets/__init__.py

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Comments suppressed due to low confidence (1)

src/specify_cli/presets/init.py:27

  • This duplicates read_response_limited from the existing import block below and introduces MAX_DOWNLOAD_BYTES and MAX_JSON_METADATA_BYTES, neither of which is used in this module. The resulting redefinition/unused imports will fail static lint checks; remove this line and keep the existing _download_security import block.
from .._download_security import MAX_DOWNLOAD_BYTES, MAX_JSON_METADATA_BYTES, read_response_limited
  • Files reviewed: 1/1 changed files
  • Comments generated: 0 new
  • Review effort level: Medium

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants