Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion docs/docs/advanced/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ RestSharp allows configuring `RestClient` using client options, as mentioned at
| `Credentials` | Instance of `ICredentials` used for NTLM or Kerberos authentication. Not supported in browsers. |
| `UseDefaultCredentials` | Whether to use default OS credentials for NTLM or Kerberos authentication. Not supported in browsers. |
| `DisableCharset` | When set to `true`, the `Content-Type` header won't have the `charset` portion. Some older web servers don't understand the `charset` portion in the header and fail to process the request. |
| `AutomaticDecompression` | Allows customizing supported decompression methods. Default is `All` except for .NET Framework that only support `GZip`. Not supported in browsers. |
| `AutomaticDecompression` | Allows customizing supported decompression methods. Default is `GZip \| Deflate` on .NET and `GZip` on .NET Framework. Brotli is not enabled by default, see the [note below](#brotli-decompression). Not supported in browsers. |
| `MaxRedirects` | The number of redirects to follow. Delegates to `RedirectOptions.MaxRedirects`. Default is 50. |
| `ClientCertificates` | A collection of X.509 client certificates to be used for authentication. Not supported in browsers. |
| `Proxy` | Can be used if the client needs to use an explicit, non-default proxy. Not supported in browsers, on iOS and tvOS. |
Expand Down Expand Up @@ -195,6 +195,20 @@ Some of the options are used by RestSharp code, but some are only used to config
If setting these options to non-default values produce no desirable effect, check if your framework and platform supports them. RestSharp doesn't change behaviour based on values of those options.
:::

### Brotli decompression

:::warning
Brotli (`DecompressionMethods.Brotli`) is excluded from the default `AutomaticDecompression` value because the Brotli decoder bundled with the .NET runtime is affected by [CVE-2026-111497](https://nvd.nist.gov/vuln/detail/CVE-2026-111497), an out-of-bounds write that a malicious server can trigger with a crafted `Content-Encoding: br` response. The decoder is part of the runtime, not of RestSharp, so RestSharp cannot fix it; it can only avoid reaching it.

In practice servers that support Brotli also support gzip and honour `Accept-Encoding`, so responses arrive gzip-encoded instead. A server that sends `Content-Encoding: br` regardless of what the client advertised is not decoded by default: `RawBytes` holds the compressed body, `Content` is not meaningful, and `RestResponse.ContentEncoding` reports `br`. If you need Brotli and your runtime includes the fix, opt in explicitly:

```csharp
var client = new RestClient(new RestClientOptions("https://api.example.com") {
AutomaticDecompression = DecompressionMethods.All
});
```
:::

The `IRestClient` interface exposes the `Options` property, so any option can be inspected at runtime. However, RestSharp converts the options object provided to the client constructor to an immutable object. Therefore, no client option can be changed after the client is instantiated. It's because changing client options at runtime can produce issues in concurrent environments, effectively rendering the client as not thread-safe. Apart from that, changing the options that are used to create the message handler would require re-creating the handler, and also `HttpClient`, which should not be done at runtime.

## Configuring requests
Expand Down
6 changes: 6 additions & 0 deletions docs/docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ For release notes of previous versions, please check the [Releases page](https:/

Changes between major versions are documented in the documentation for each version on this website.

## v114.2

### Behavior changes

* **Brotli removed from the default `AutomaticDecompression`** — `RestClientOptions.AutomaticDecompression` now defaults to `GZip | Deflate` on .NET (previously `All`). The Brotli decoder bundled with the .NET runtime is affected by [CVE-2026-111497](https://nvd.nist.gov/vuln/detail/CVE-2026-111497), reachable from a crafted `Content-Encoding: br` response, and no patched runtime is available yet. Clients built with default options no longer advertise `br` and no longer route responses through that decoder. Set `AutomaticDecompression = DecompressionMethods.All` to restore the previous behavior. The .NET Framework default (`GZip`) is unchanged. See [Brotli decompression](advanced/configuration.md#brotli-decompression).

## v114.1

### New features
Expand Down
12 changes: 10 additions & 2 deletions src/RestSharp/Options/RestClientOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,19 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
public bool DisableCharset { get; set; }

/// <summary>
/// Set the decompression method to use when making requests
/// Set the decompression methods the client advertises in <c>Accept-Encoding</c> and applies to responses.
/// </summary>
/// <remarks>
/// The default is <c>GZip | Deflate</c> on .NET and <c>GZip</c> on .NET Framework.
/// Brotli is not enabled by default: the Brotli decoder bundled with the .NET runtime is affected by
/// CVE-2026-111497, an out-of-bounds write reachable from a crafted <c>Content-Encoding: br</c> response,
/// and no fixed runtime has shipped at the time of this release. Set this property to
/// <see cref="DecompressionMethods.All"/> to opt in once your runtime is patched.
/// A <c>br</c> response from a server that ignores <c>Accept-Encoding</c> is returned undecoded.
/// </remarks>
#if NET
[UnsupportedOSPlatform("browser")]
public DecompressionMethods AutomaticDecompression { get; set; } = DecompressionMethods.All;
public DecompressionMethods AutomaticDecompression { get; set; } = DecompressionMethods.GZip | DecompressionMethods.Deflate;
#else
public DecompressionMethods AutomaticDecompression { get; set; } = DecompressionMethods.GZip;
#endif
Expand Down
39 changes: 39 additions & 0 deletions test/RestSharp.Tests.Integrated/CompressionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,43 @@ public async Task Can_Handle_Uncompressed_Content() {

response.Content.Should().Be(value);
}

#if NET8_0_OR_GREATER
// Brotli is excluded from the default AutomaticDecompression because the Brotli decoder
// bundled with the .NET runtime is affected by CVE-2026-111497. See docs/advanced/configuration.md.
[Fact]
public async Task Default_Client_Does_Not_Advertise_Or_Decode_Brotli() {
const string value = "This is some brotli content";
using var server = WireMockServer.Start();

var body = await GetBody(s => new BrotliStream(s, CompressionMode.Compress, true), value);
ConfigureServer(server, body, "br");

using var client = new RestClient(server.Url!);
var request = new RestRequest("");
var response = await client.ExecuteAsync(request);

var acceptEncoding = server.LogEntries.Single().RequestMessage.Headers!["Accept-Encoding"].ToString();
acceptEncoding.Should().NotContain("br");

// The body is returned as-is: the Brotli decoder is never invoked
response.RawBytes.Should().Equal(body);
response.Content.Should().NotBe(value);
}

[Fact]
public async Task Can_Handle_Brotli_Compressed_Content_When_Opted_In() {
const string value = "This is some brotli content";
using var server = WireMockServer.Start();

var body = await GetBody(s => new BrotliStream(s, CompressionMode.Compress, true), value);
ConfigureServer(server, body, "br");

using var client = new RestClient(server.Url!, options => options.AutomaticDecompression = DecompressionMethods.All);
var request = new RestRequest("");
var response = await client.ExecuteAsync(request);

response.Content.Should().Be(value);
}
#endif
}