Skip to content

feat(client): max_decompressed_size guard against decompression bombs#1262

Open
quinnj wants to merge 2 commits into
masterfrom
jq-decompress-limit
Open

feat(client): max_decompressed_size guard against decompression bombs#1262
quinnj wants to merge 2 commits into
masterfrom
jq-decompress-limit

Conversation

@quinnj
Copy link
Copy Markdown
Member

@quinnj quinnj commented May 30, 2026

Closes #1178.

Auto-decompression (gzip/deflate) currently has no size limit, so a small compressed payload can inflate to exhaust memory (a decompression/zip bomb). This adds an opt-in max_decompressed_size request keyword:

# reject any response whose decompressed body exceeds 10 MiB
HTTP.get(url; max_decompressed_size = 10 * 1024 * 1024)
# -> throws HTTP.DecompressionLimitError before the body inflates
  • 0 (default) keeps the current unbounded behavior — fully backward compatible.
  • The cap wraps the decompressor stream and is checked on each chunked read, so it fires after at most one extra chunk; memory stays bounded near the limit rather than materializing the whole bomb first.
  • Applies to both the default materialized resp.body and caller-owned response_stream sinks.
  • New HTTP.DecompressionLimitError (with the offending limit) for callers to catch.

Tested with a ~4 MB-of-zeros gzip bomb (a few KB on the wire): rejected under a small limit, succeeds with no/large limit, and the limit is enforced on an IOBuffer sink too.

Note: scoped to HTTP response-body decompression (the documented OOM vector). WebSocket frame limits are separate (maxframesize, see #1181).

🤖 Generated with Claude Code

…n bombs

Closes #1178. A new `max_decompressed_size` request keyword caps how many bytes
an auto-decompressed (gzip/deflate) response body may produce; reading past it
throws `DecompressionLimitError` before the bomb inflates. `0` (default) keeps
the current unbounded behavior. The limiter wraps the decompressor stream, so it
fires after at most one extra read chunk (memory stays bounded near the limit)
and applies to both the materialized `resp.body` and caller-owned
`response_stream` sinks.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 30, 2026

Codecov Report

❌ Patch coverage is 80.00000% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.30%. Comparing base (f9d62af) to head (6cf6415).

Files with missing lines Patch % Lines
src/http_client.jl 80.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1262      +/-   ##
==========================================
- Coverage   84.36%   84.30%   -0.07%     
==========================================
  Files          28       28              
  Lines       10689    10698       +9     
==========================================
+ Hits         9018     9019       +1     
- Misses       1671     1679       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…r type

The _DecompressLimitReader wrapper widened _response_body_reader's return into an
abstractly-parameterized union (Union{_BodyIO, _DecompressLimitReader,
TranscodingStream...}), which broke --trim static compilation
(trim_compile_tests verifier errors on macOS/Linux). Apply max_decompressed_size
inside the chunked read loops (_read_all_response_bytes / _copy_response_bytes!)
instead, leaving the reader's type set unchanged. Same DecompressionLimitError
and behavior; trim compile passes (63/63 locally).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

gzip / zip bomb mitigation

1 participant