Repository navigation
Fix unbounded request decompression on IIS out-of-process (MaxRequestBodySize) - #69187
Conversation
… IIS out-of-process (MaxRequestBodySize) ## Description On IIS out-of-process hosting, IISMiddleware cleared the request body size limit (MaxRequestBodySize = null). RequestDecompressionMiddleware consumed that as an unbounded decompressed-body budget, allowing an anonymous decompression-bomb DoS (temporary, with amplification). ## Fix Gate the null-assignment behind the Microsoft.AspNetCore.Server.IISIntegration.ClearMaxRequestBodySize AppContext switch (default off). By default the server request body size limit is preserved; apps needing the legacy defer-to-IIS behavior can opt in. ## Customer Impact Prevents unbounded request-body decompression on IIS out-of-process. Opt-out switch provided for compatibility. ## Regression No. Long-standing behavior since 2.0; exposed via RequestDecompression (7.0+). ## Risk Low. Minimal, gated change with opt-out. Product change validated identically on main; unit tests added. Local full build blocked by internal feed provisioning; relying on PR CI. ## Testing Unit tests: default preserves limit, switch clears it, read-only untouched, absent feature. Verified end-to-end on main via real IIS Express out-of-process deploy. ---- #### AI description (iteration 1) #### PR Classification Bug fix to address unbounded request decompression vulnerability in IIS out-of-process by changing the default behavior of MaxRequestBodySize handling. #### PR Summary This PR fixes a security issue where MaxRequestBodySize was being cleared by default in IIS out-of-process mode, allowing unbounded request decompression. The fix changes the default behavior to preserve the server's configured MaxRequestBodySize limit while providing an opt-in switch to restore the legacy behavior. - `IISMiddleware.cs`: Changed default behavior to no longer clear MaxRequestBodySize; added `ClearMaxRequestBodySizeSwitch` AppContext switch to enable legacy behavior of clearing the limit - `IISMiddlewareTests.cs`: Added comprehensive test coverage for MaxRequestBodySize handling including default behavior, opt-in switch behavior, read-only feature handling, and missing feature scenarios <!-- GitOpsUserAgent=GitOps.Apps.Server.pullrequestcopilot -->
There was a problem hiding this comment.
🟡 Changes recommended
The new switch-controlled behavior isn’t fully covered by tests (the opt-in path and the “feature absent” case under the opt-in switch need explicit coverage and isolation).
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR addresses a security/compatibility issue in IIS out-of-process hosting where IISMiddleware previously cleared IHttpMaxRequestBodySizeFeature.MaxRequestBodySize, which could be interpreted by request decompression as an unbounded decompressed-body budget. The change preserves the server-side limit by default and introduces an AppContext switch to opt into the legacy “clear the limit” behavior.
Changes:
- Gate clearing
MaxRequestBodySizebehind theMicrosoft.AspNetCore.Server.IISIntegration.ClearMaxRequestBodySizeAppContext switch (default: off). - Add unit tests to validate the default behavior (do not clear) and basic behavior when the feature is absent.
File summaries
| File | Description |
|---|---|
| src/Servers/IIS/IISIntegration/src/IISMiddleware.cs | Adds an AppContext switch-controlled opt-in path for clearing MaxRequestBodySize, preserving the configured limit by default. |
| src/Servers/IIS/IISIntegration/test/Tests/IISMiddlewareTests.cs | Adds tests around MaxRequestBodySize behavior and introduces test helpers for constructing an IISMiddleware instance and HttpContext. |
Review details
Suppressed comments (1)
src/Servers/IIS/IISIntegration/test/Tests/IISMiddlewareTests.cs:560
DoesNotThrowWhenMaxRequestBodySizeFeatureAbsentcurrently runs with the AppContext switch default (off), so it doesn't exercise the new guarded code path. Setting the switch to true for this test (and resetting it in a finally) ensures we cover the opt-in path where the feature lookup happens, while still validating it doesn't throw when the feature is missing.
[Fact]
public async Task DoesNotThrowWhenMaxRequestBodySizeFeatureAbsent()
{
var nextInvoked = false;
var context = new DefaultHttpContext();
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
- in-process must clear the limit on upgrade because its read loop enforces it - out-of-process runs on Kestrel, which never enforces it once upgraded - unblocks the three WebSocketsOutOfProcessTests failures 🧪 - Generated by Copilot
|
The three What failed
The fixScope the assertion to in-process hosting, where it is meaningful: if (context.Features.Get<IServerVariablesFeature>() is not null)
{
Assert.Null(context.Features.Get<IHttpMaxRequestBodySizeFeature>().MaxRequestBodySize);
}
|
|
/backport to release/10.0 |
|
/backport to release/9.0 |
|
Started backporting to |
|
/backport to release/8.0 |
|
Started backporting to |
|
Started backporting to |
On IIS out-of-process hosting, IISMiddleware cleared the request body size limit (MaxRequestBodySize = null). RequestDecompressionMiddleware consumed that as an unbounded decompressed-body budget, allowing an anonymous decompression-bomb DoS (temporary, with amplification).
Gate the null-assignment behind the Microsoft.AspNetCore.Server.IISIntegration.ClearMaxRequestBodySize AppContext switch (default off). By default the server request body size limit is preserved; apps needing the legacy defer-to-IIS behavior can opt in.
Prevents unbounded request-body decompression on IIS out-of-process. Opt-out switch provided for compatibility.