CVE-2024-51501
Description
Refit is an automatic type-safe REST library for .NET Core, Xamarin and .NET The various header-related Refit attributes (Header, HeaderCollection and Authorize) are vulnerable to CRLF injection. The way HTTP headers are added to a request is via the HttpHeaders.TryAddWithoutValidation method. This method does not check for CRLF characters in the header value. This means that any headers added to a refit request are vulnerable to CRLF-injection. In general, CRLF-injection into a HTTP header (when using HTTP/1.1) means that one can inject additional HTTP headers or smuggle whole HTTP requests. If an application using the Refit library passes a user-controllable value through to a header, then that application becomes vulnerable to CRLF-injection. This is not necessarily a security issue for a command line application like the one above, but if such code were present in a web application then it becomes vulnerable to request splitting (as shown in the PoC) and thus Server Side Request Forgery. Strictly speaking this is a potential vulnerability in applications using Refit and not in Refit itself. This issue has been addressed in release versions 7.2.22 and 8.0.0 and all users are advised to upgrade. There are no known workarounds for this vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
RefitNuGet | < 7.2.22 | 7.2.22 |
Patches
28cb6f752001c483b1d8df180Fix for CRLF injection vulnerability (#1834)
3 files changed · +54 −1
Refit/RequestBuilderImplementation.cs+13 −1 modified@@ -977,7 +977,7 @@ static void AddHeadersToRequest(Dictionary<string, string?>? headersToAdd, HttpR // sure we have an HttpContent object to add them to, // provided the HttpClient will allow it for the method if (ret.Content == null && !IsBodyless(ret.Method)) - ret.Content = new ByteArrayContent(Array.Empty<byte>()); + ret.Content = new ByteArrayContent([]); foreach (var header in headersToAdd) { @@ -1335,6 +1335,10 @@ static void SetHeader(HttpRequestMessage request, string name, string? value) if (value == null) return; + // CRLF injection protection + name = EnsureSafe(name); + value = EnsureSafe(value); + var added = request.Headers.TryAddWithoutValidation(name, value); // Don't even bother trying to add the header as a content header @@ -1345,6 +1349,14 @@ static void SetHeader(HttpRequestMessage request, string name, string? value) } } + static string EnsureSafe(string value) + { + // Remove CR and LF characters +#pragma warning disable CA1307 // Specify StringComparison for clarity + return value.Replace("\r", string.Empty).Replace("\n", string.Empty); +#pragma warning restore CA1307 // Specify StringComparison for clarity + } + static bool IsBodyless(HttpMethod method) => method == HttpMethod.Get || method == HttpMethod.Head; } }
Refit/RestMethodInfo.cs+6 −0 modified@@ -259,6 +259,12 @@ static void VerifyUrlPathIsSane(string relativePath) throw new ArgumentException( $"URL path {relativePath} must start with '/' and be of the form '/foo/bar/baz'" ); + + // CRLF injection protection + if (relativePath.Contains("\r") || relativePath.Contains("\n")) + throw new ArgumentException( + $"URL path {relativePath} must not contain CR or LF characters" + ); } static Dictionary<int, RestMethodParameterInfo> BuildParameterMap(
Refit.Tests/AuthenticatedClientHandlerTests.cs+35 −0 modified@@ -4,8 +4,11 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; + using Refit; // for the code gen + using RichardSzalay.MockHttp; + using Xunit; namespace Refit.Tests; @@ -49,6 +52,12 @@ public interface IInheritedAuthenticatedServiceWithHeaders : IAuthenticatedServi Task<string> GetInheritedThing(); } + public interface IInheritedAuthenticatedServiceWithHeadersCRLF : IAuthenticatedServiceWithHeaders + { + [Get("/get-inherited-thing\r\n\r\nGET /smuggled")] + Task<string> GetInheritedThing(); + } + [Headers("Authorization: Bearer")] public interface IAuthenticatedServiceWithHeaders { @@ -347,4 +356,30 @@ public async void AuthentictedMethodFromInheritedClassWithHeadersAttributeUsesAu Assert.Equal("Ok", result); } + + [Fact] + public async void AuthentictedMethodFromInheritedClassWithHeadersAttributeUsesAuth_WithCRLFCheck() + { + var handler = new MockHttpMessageHandler(); + var settings = new RefitSettings() + { + AuthorizationHeaderValueGetter = (_, __) => Task.FromResult("tokenValue"), + HttpMessageHandlerFactory = () => handler, + }; + + handler + .Expect(HttpMethod.Get, "http://api/get-inherited-thing") + .WithHeaders("Authorization", "Bearer tokenValue") + .Respond("text/plain", "Ok"); + + await Assert.ThrowsAsync<ArgumentException>(async () => + { + var fixture = RestService.For<IInheritedAuthenticatedServiceWithHeadersCRLF>( + "http://api", + settings + ); + + var result = await fixture.GetInheritedThing(); + }); + } }
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- github.com/advisories/GHSA-3hxg-fxwm-8gf7ghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-51501ghsaADVISORY
- github.com/reactiveui/refit/blob/258a771f44417c6e48e103ac921fe4786f3c2a1e/Refit/RequestBuilderImplementation.csnvdWEB
- github.com/reactiveui/refit/commit/483b1d8df18098f137ca0eca056b7e9ec19f70ddghsaWEB
- github.com/reactiveui/refit/security/advisories/GHSA-3hxg-fxwm-8gf7nvdWEB
News mentions
0No linked articles in our index yet.