Skip to content

security: Add max_length to zlib.decompress in uworker_io.py to prevent decompression bomb DoS#5334

Open
prasanna8585 wants to merge 1 commit into
google:masterfrom
prasanna8585:security/uworker-zlib-decompress-max-length
Open

security: Add max_length to zlib.decompress in uworker_io.py to prevent decompression bomb DoS#5334
prasanna8585 wants to merge 1 commit into
google:masterfrom
prasanna8585:security/uworker-zlib-decompress-max-length

Conversation

@prasanna8585

Copy link
Copy Markdown

Summary

uworker_io.py calls zlib.decompress() three times without a max_length limit. A compromised or malicious uworker process could upload a small zlib-compressed bomb (~4 MB) to its signed GCS output URL, causing the trusted tworker to exhaust memory when decompressing, crashing the orchestrator.

The code already acknowledges the trust boundary:

# ...make sure we can infer the actual input since the output is not trusted.

But the decompression step had no corresponding size guard.

Changes

  • Add _MAX_UWORKER_MSG_SIZE = 256 * 1024 * 1024 constant (256 MB)
  • Apply max_length=_MAX_UWORKER_MSG_SIZE to all three zlib.decompress() calls:
    • download_and_deserialize_uworker_input() (line 129)
    • download_input_based_on_output_url() (line 170)
    • download_and_deserialize_uworker_output() (line 184)

The existing except zlib.error blocks already handle decompression failures gracefully — no additional error handling is required.

Attack Scenario

# Inside a compromised uworker:
import zlib, requests
bomb = zlib.compress(b'\x00' * (4 * 1024 * 1024 * 1024), level=1)  # ~4MB → 4GB
requests.put(signed_upload_url, data=bomb)
# tworker calls zlib.decompress(bomb) → OOM crash

Fix Verification

After this patch, zlib.decompress(data, max_length=_MAX_UWORKER_MSG_SIZE) raises zlib.error if the decompressed output exceeds 256 MB. The caller's existing except zlib.error block handles this as a backward-compatibility fallback, so no disruption to normal operation.

A compromised or malicious uworker process could upload a zlib-
compressed decompression bomb to its signed GCS output URL. The
trusted tworker, which explicitly treats uworker output as untrusted,
was calling zlib.decompress() on this data without any size limit.
This could cause an OOM crash on the tworker, disrupting ClusterFuzz
orchestration.

Add _MAX_UWORKER_MSG_SIZE (256 MB) as an upper bound on all three
zlib.decompress() calls in uworker_io.py (lines 129, 170, 184).

The existing except zlib.error blocks handle the new zlib.error
that decompress raises when the limit is exceeded, so no additional
error handling is required.

Fixes: decompression bomb DoS via untrusted uworker output
@prasanna8585 prasanna8585 requested a review from a team as a code owner June 21, 2026 14:25
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.

1 participant