Skip to content

Cap Zstandard request decompression window at 8 MB#67688

Open
BrennanConroy wants to merge 1 commit into
mainfrom
brennanconroy/zstd-decompression-options
Open

Cap Zstandard request decompression window at 8 MB#67688
BrennanConroy wants to merge 1 commit into
mainfrom
brennanconroy/zstd-decompression-options

Conversation

@BrennanConroy

Copy link
Copy Markdown
Member
  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Cap the Zstandard request decompression window at 8 MB (windowLog 23).

Description

The request decompression middleware decodes zstd request bodies from untrusted clients. The zstd decoder sizes its window buffer from the frame header, and the native default allows windows up to 128 MB. That lets a small compressed request force a large decoder allocation, which is a decompression-bomb style DoS vector.

This wires up the new System.IO.Compression.ZstandardDecompressionOptions.MaxWindowLog (from dotnet/runtime#129768) and sets it to 23 (8 MB) internally on the request decompression provider. 8 MB is the maximum window RFC 9659 permits for the HTTP zstd content coding, and it matches what browsers such as Chromium enforce. A request that advertises a larger window now fails to decompress.

This is intentionally an internal change with no new public API. The related API proposal (#67476) to expose these options was not approved, so the window is capped at the RFC-mandated value with no configuration knob for now.

Notes for reviewers:

  • No effect on well-behaved clients: default streaming zstd emits a window of at most ~2 MB (windowLog 21). Only payloads built with a larger window (for example zstd --long, ultra levels, or an explicit WindowLog > 23) are rejected.
  • The compression side is unchanged. A decoder cap costs nothing, whereas pinning the encoder would waste memory for no benefit, and ResponseCompression already emits compliant windows.
  • When the window is too large the runtime decoder throws IOException ("Data requires too much memory for decoding..."). The middleware lets it propagate, matching how it already surfaces other decode failures. The added test asserts this.

Related to #67476

Set MaxWindowLog to 23 (8 MB) on the request decompression provider's
ZstandardDecompressionOptions, as required by RFC 9659 for the "zstd" HTTP
content coding. This bounds the memory the decoder can be forced to allocate
for a single request. Default streaming compression uses a window of at most
2 MB and is unaffected; payloads produced with a larger window (for example,
"zstd --long") will fail to decompress.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 8, 2026 23:45

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

Caps Zstandard (zstd) request-body decompression window size to the RFC 9659 maximum (8 MiB / windowLog 23) to mitigate decompression-bomb style memory DoS from untrusted clients, by configuring the runtime decoder’s new ZstandardDecompressionOptions.MaxWindowLog.

Changes:

  • Configure ZstandardStream request decompression with ZstandardDecompressionOptions { MaxWindowLog = 23 }.
  • Add an integration-style middleware test that compresses with an oversized window (windowLog 24) and asserts decompression fails.
  • Document the rationale (RFC requirement and browser behavior) inline in the provider.
Show a summary per file
File Description
src/Middleware/RequestDecompression/src/ZstandardDecompressionProvider.cs Uses ZstandardDecompressionOptions.MaxWindowLog = 23 to cap decoder window to 8 MiB per RFC 9659.
src/Middleware/RequestDecompression/test/RequestDecompressionMiddlewareTests.cs Adds coverage to ensure oversized zstd windows are rejected (throws during request processing).

Copilot's findings

  • Files reviewed: 2/2 changed files
  • Comments generated: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants