Skip to content

fix: use bounded read for workflow catalog HTTP responses - #3766

Open
Quratulain-bilal wants to merge 1 commit into
github:mainfrom
Quratulain-bilal:fix/unbounded-workflow-catalog-response
Open

fix: use bounded read for workflow catalog HTTP responses#3766
Quratulain-bilal wants to merge 1 commit into
github:mainfrom
Quratulain-bilal:fix/unbounded-workflow-catalog-response

Conversation

@Quratulain-bilal

Copy link
Copy Markdown
Contributor

Summary

The workflow catalog fetch (WorkflowCatalog._fetch_single_catalog and StepCatalog._fetch_single_catalog) used unbounded resp.read() to read HTTP responses into memory. A malicious or misconfigured catalog server could return an arbitrarily large response causing OOM.

Changes

  • src/specify_cli/workflows/catalog.py (lines 541, 1214): Replaced resp.read() with read_response_limited(resp, max_bytes=MAX_JSON_METADATA_BYTES) capped at 1 MiB at both call sites, consistent with how other JSON fetch paths in the codebase enforce bounded reads.

Testing

All 176 tests in tests/workflows/ pass after the fix.

Security Impact

This is a Medium severity fix - it closes a potential memory exhaustion vector against the workflow catalog fetch endpoint.

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 workflow and step catalog HTTP responses to 1 MiB, mitigating memory-exhaustion risks.

Changes:

  • Uses read_response_limited for both catalog fetch paths.
  • Applies MAX_JSON_METADATA_BYTES as the response limit.
Show a summary per file
File Description
src/specify_cli/workflows/catalog.py Adds bounded reads for workflow and step catalogs.

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/workflows/catalog.py:1219

  • Please cover the step-catalog fetch path with an oversized streamed response and assert StepCatalogError. StepCatalog has separate fetch/cache handling, and its current fetch tests also exit before reading the body, so they do not verify that this call site actually enforces the new limit.
                data = json.loads(
                    read_response_limited(resp, max_bytes=MAX_JSON_METADATA_BYTES).decode("utf-8")
  • Files reviewed: 1/1 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment on lines +543 to +544
data = json.loads(
read_response_limited(resp, max_bytes=MAX_JSON_METADATA_BYTES).decode("utf-8")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added 4 regression tests:

  • test_oversized_workflow_catalog_response_rejected: monkeypatches MAX_JSON_METADATA_BYTES to 512, serves 1024 bytes, asserts WorkflowCatalogError with "exceeds maximum size"
  • test_oversized_workflow_catalog_does_not_block_healthy_one: proves a valid catalog still works after an oversized one was rejected
  • test_oversized_step_catalog_response_rejected: same pattern for StepCatalog ? StepCatalogError
  • test_oversized_step_catalog_does_not_block_healthy_one: proves a valid step catalog still works after rejection

@mnriem mnriem left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Please address Copilot feedback

The workflow catalog fetch used unbounded resp.read() to read HTTP
responses into memory. A malicious or misconfigured catalog server
could return an arbitrarily large response causing OOM.

Replace with read_response_limited() capped at MAX_JSON_METADATA_BYTES
(1 MiB) at both call sites, consistent with how other JSON fetch
paths in the codebase enforce bounded reads.
@Quratulain-bilal
Quratulain-bilal force-pushed the fix/unbounded-workflow-catalog-response branch from 291d343 to 5c2087c Compare July 27, 2026 22:15
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