Nov 11, 2026·9 min read·1 visit
An unauthenticated remote attacker can trigger a Denial of Service in ASP.NET Core applications hosted on Windows HTTP.sys by sending a single crafted HTTP request containing Transfer-Encoding: chunked, Content-Length, and X-Content-Length headers simultaneously.
CVE-2026-114154 is a high-severity Denial of Service (DoS) and uncontrolled resource consumption vulnerability in the Microsoft.AspNetCore.Server.HttpSys component of ASP.NET Core. When processing an HTTP request that simultaneously contains a chunked Transfer-Encoding header, a Content-Length header, and an explicit X-Content-Length header, the server throws an unhandled ArgumentException during header normalization. In certain versions, subsequent exception handling attempts to dereference a disposed native request context, aborting error response dispatch and leaking unmanaged HTTP.sys request structures.
CVE-2026-114154 is an unauthenticated remote Denial of Service (DoS) vulnerability affecting ASP.NET Core web applications configured to use the Windows HTTP Server API (HTTP.sys) via the Microsoft.AspNetCore.Server.HttpSys server implementation. Unlike Kestrel, which is a cross-platform managed web server, HttpSys interfaces directly with the kernel-mode http.sys driver on Windows to receive and process incoming HTTP requests.
The vulnerability is classified under CWE-401 (Missing Release of Memory after Effective Lifetime). It occurs during the initial request parsing and header normalization phase within the managed HttpSys wrapper. When an incoming HTTP/1.1 request includes both Transfer-Encoding: chunked and a Content-Length header, ASP.NET Core attempts to strip the Content-Length header to maintain compliance with RFC 9112 §6.1 and mitigate HTTP request smuggling risks.
To preserve the original value for diagnostic and backwards-compatibility purposes, the server copies the Content-Length value into a backup header named X-Content-Length. However, the code performs this insertion using IHeaderDictionary.Add(), which does not permit duplicate keys. If a client explicitly includes an X-Content-Length header alongside Transfer-Encoding: chunked and Content-Length, the dictionary throws an unhandled ArgumentException.
During the recovery phase in the asynchronous I/O completion callback (AsyncAcceptContext.IOCompleted), the exception handler attempts to send an HTTP 400 Bad Request response using the native request identifier. Because the underlying _nativeRequestContext may already be disposed or invalidated when the initial parsing fails, accessing its RequestId property triggers a secondary exception (such as a NullReferenceException or ObjectDisposedException). This secondary failure aborts the error dispatch routine, leaving unmanaged HTTP_REQUEST structures and asynchronous accept slots unreleased.
The root cause of CVE-2026-114154 consists of two distinct code defects in Microsoft.AspNetCore.Server.HttpSys: an unsafe dictionary insertion in Request.cs and an unsafe pointer/context dereference inside the exception handler of AsyncAcceptContext.cs.
First, during the instantiation and initialization of the managed Request object, the server validates request framing headers. When Transfer-Encoding: chunked is detected alongside a Content-Length header, the method RemoveContentLengthIfTransferEncodingContainsChunked() is invoked. In vulnerable versions of ASP.NET Core, this method executes headerDictionary.Add("X-Content-Length", headerDictionary[HeaderNames.ContentLength]). Because the Headers collection is populated directly from the client-supplied HTTP headers prior to this normalization step, any pre-existing X-Content-Length header sent over the wire already occupies that key in the dictionary. Calling .Add() on an existing key immediately raises a System.ArgumentException.
Second, request acceptance from the Windows kernel driver is managed asynchronously by AsyncAcceptContext.IOCompleted. Within this callback, a try block wraps the creation and initialization of the RequestContext and its corresponding Request object. When RemoveContentLengthIfTransferEncodingContainsChunked() throws the ArgumentException, control transfers to the catch (Exception) block in IOCompleted.
The catch block attempts to terminate the malformed request gracefully by calling server.SendError(asyncResult._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest). However, during the construction and failure of the RequestContext inside the try block, ownership of _nativeRequestContext is manipulated and its underlying memory buffers or pins can be released or nulled out. Consequently, evaluating asyncResult._nativeRequestContext.RequestId inside the catch block results in a secondary unhandled exception, bypassing the SendError call entirely.
> [!IMPORTANT]
> Because the secondary exception escapes the catch block before server.SendError can notify the kernel-mode http.sys driver, the unmanaged request handle remains open and the managed asynchronous accept context is not recycled properly.
Microsoft addressed this vulnerability across multiple servicing branches, including .NET 8.0 (commit 8cb8dc4a1d3e5a6aedeb3dbbfd0b390aac59f172), .NET 9.0 (commit 20e629e9af9cabb0c1c02410be99521821b22f83), and the standalone Microsoft.AspNetCore.Server.HttpSys 2.3 branch (commit efc799e69e38cdc36c7b9c96580014d28e68201c).
In the .NET 8.0 and .NET 9.0 branches, the fix modifies RemoveContentLengthIfTransferEncodingContainsChunked() in src/Servers/HttpSys/src/RequestProcessing/Request.cs to use TryAdd instead of Add:
File: src/Servers/HttpSys/src/RequestProcessing/Request.cs
@@ -522,7 +522,9 @@ private void RemoveContentLengthIfTransferEncodingContainsChunked()
// We should remove the Content-Length request header in this case, for compatibility
// reasons, include x-Content-Length so that the original Content-Length is still available.
IHeaderDictionary headerDictionary = Headers;
- headerDictionary.Add("X-Content-Length", headerDictionary[HeaderNames.ContentLength]);
+
+ // if user already passed X-Content-Length, we won't overwrite it
+ headerDictionary.TryAdd("X-Content-Length", headerDictionary[HeaderNames.ContentLength]);
Headers.ContentLength = StringValues.Empty;
if (!AllowKeepAliveAfterCLTE)By switching to headerDictionary.TryAdd(), the method checks whether X-Content-Length already exists in the dictionary before attempting insertion. If the client already provided an X-Content-Length header, TryAdd returns false without throwing an exception, preserving the client-supplied value while still clearing Headers.ContentLength.
In the release/2.3 branch (commit efc799e69e38cdc36c7b9c96580014d28e68201c), where TryAdd extension methods on IHeaderDictionary are not available on the target framework, the patch uses an explicit ContainsKey check and also remediates the secondary exception hazard in AsyncAcceptContext.cs:
File: src/Servers/HttpSys/src/AsyncAcceptContext.cs
@@ -70,6 +70,8 @@ private static void IOCompleted(AsyncAcceptContext asyncResult, uint errorCode,
HttpSysListener server = asyncResult.Server;
if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
{
+ var requestId = asyncResult._nativeRequestContext.RequestId;
+
// at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
// points to it we need to hook up our authentication handling code here.
try
@@ -83,7 +85,7 @@ private static void IOCompleted(AsyncAcceptContext asyncResult, uint errorCode,
}
catch (Exception)
{
- server.SendError(asyncResult._nativeRequestContext.RequestId, StatusCodes.Status400BadRequest);
+ server.SendError(requestId, StatusCodes.Status400BadRequest);
throw;
}
finally
File: src/Servers/HttpSys/src/RequestProcessing/Request.cs
@@ -380,7 +380,12 @@ private void RemoveContentLengthIfTransferEncodingContainsChunked()
// We should remove the Content-Length request header in this case, for compatibility
// reasons, include x-Content-Length so that the original Content-Length is still available.
IHeaderDictionary headerDictionary = Headers;
- headerDictionary.Add("X-Content-Length", headerDictionary[HttpKnownHeaderNames.ContentLength]);
+
+ // if user already passed X-Content-Length, we won't overwrite it
+ if (!headerDictionary.ContainsKey("X-Content-Length"))
+ {
+ headerDictionary.Add("X-Content-Length", headerDictionary[HttpKnownHeaderNames.ContentLength]);
+ }
Headers.ContentLength = StringValues.Empty;Caching var requestId = asyncResult._nativeRequestContext.RequestId; as a local value type (ulong) prior to entering the try block ensures that even if another parsing exception occurs during RequestContext initialization and disposes _nativeRequestContext, the catch handler can still reliably pass the requestId to server.SendError(). This makes the fix complete against both the specific X-Content-Length collision and any future exceptions thrown during early request initialization.
Exploiting CVE-2026-114154 requires no authentication, special privileges, or complex timing windows. The only prerequisite is that the target ASP.NET Core application is hosted using Microsoft.AspNetCore.Server.HttpSys (webBuilder.UseHttpSys()) and is reachable over HTTP or HTTPS without an intermediate reverse proxy stripping conflicting framing headers.
An attacker can trigger the exception path by sending an HTTP/1.1 request that includes all three headers (Transfer-Encoding: chunked, Content-Length, and X-Content-Length):
POST / HTTP/1.1
Host: target-server.local
Transfer-Encoding: chunked
Content-Length: 1
X-Content-Length: 100
Connection: keep-alive
0
When the target server receives this payload, the following execution sequence occurs:
http.sys driver parses the raw HTTP stream and passes the unmanaged HTTP_REQUEST structure to the managed HttpSysListener via AsyncAcceptContext.IOCompleted.Headers dictionary with Transfer-Encoding, Content-Length, and X-Content-Length.Transfer-Encoding: chunked and Content-Length are present, RemoveContentLengthIfTransferEncodingContainsChunked() is executed.headerDictionary.Add("X-Content-Length", ...) collides with the attacker-supplied X-Content-Length: 100 header and throws an ArgumentException.IOCompleted, dereferencing _nativeRequestContext.RequestId fails or the unhandled exception propagates up the I/O completion thread.> [!NOTE]
> In Microsoft's regression test suite (RequestTests.cs), a patched server responds to a request containing Transfer-Encoding: gzip, chunked, Content-Length: 1, and X-Content-Length: 123 with an HTTP 200 OK, stripping Content-Length while preserving X-Content-Length: 123.
By repeatedly transmitting this compact HTTP payload over concurrent connections, an unauthenticated attacker can exhaust available accept contexts, leak native request memory, or crash the hosting worker process, resulting in a sustained denial of service.
The primary impact of CVE-2026-114154 is a complete loss of service availability for affected ASP.NET Core endpoints. The vulnerability is rated 7.5 (High) under CVSS v3.1 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H). Because the flaw is triggered during initial header normalization before route matching, authentication middleware, or authorization policies execute, any publicly exposed endpoint on an HttpSys-hosted application is vulnerable.
The vulnerability does not allow arbitrary code execution, memory disclosure, or data modification (C:N/I:N). However, the availability impact (A:H) is severe because each malformed request causes unhandled exceptions on I/O completion threads or orphans native HTTP_REQUEST allocations. Low-bandwidth request floods are sufficient to exhaust server resources or trigger process termination.
Applications hosted on the default ASP.NET Core Kestrel web server (UseKestrel()) or hosted within IIS (using UseIIS() or UseIISIntegration()) do not execute the Microsoft.AspNetCore.Server.HttpSys request processing code path and are unaffected by this vulnerability.
As of publication, CVE-2026-114154 is not listed in the CISA Known Exploited Vulnerabilities (KEV) catalog, and no public weaponized exploit modules have been indexed in ExploitDB or PacketStorm.
To remediate CVE-2026-114154, organizations must update their .NET runtimes, SDKs, or NuGet package references to the patched releases published by Microsoft.
If immediate patching of the .NET runtime or application packages is not feasible, security teams can apply the following mitigations:
HttpSys server to reject incoming HTTP requests that contain both a Transfer-Encoding header and a Content-Length header with an HTTP 400 Bad Request response.X-Content-Length at the Edge: Configure upstream reverse proxies to remove any client-supplied X-Content-Length header before forwarding requests to the backend ASP.NET Core server.UseHttpSys() to UseKestrel() or deploy behind IIS, provided Windows kernel-level features specific to HttpSys (such as kernel-mode Windows Authentication or direct port sharing without IIS) are not strictly required.CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H| Product | Affected Versions | Fixed Version |
|---|---|---|
Microsoft.AspNetCore.Server.HttpSys Microsoft | >= 2.3.10, < 2.3.14 | 2.3.14 |
.NET 8.0 Microsoft | >= 8.0.0, < 8.0.34 | 8.0.34 |
.NET 9.0 Microsoft | >= 9.0.0, < 9.0.23 | 9.0.23 |
.NET 10.0 Microsoft | >= 10.0.0, < 10.0.15 | 10.0.15 |
Microsoft Visual Studio 2022 version 17.14 Microsoft | >= 17.14.0, < 17.14.45 | 17.14.45 |
Microsoft Visual Studio 2026 version 18.11 Microsoft | >= 18.11.0, < 18.11.4 | 18.11.4 |
Microsoft Visual Studio 2026 version 18.12 Microsoft | 18.12.0 | 18.12.1 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-401 (Missing Release of Memory after Effective Lifetime) |
| CVSS v3.1 Score | 7.5 High (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H) |
| Attack Vector | Network (Unauthenticated HTTP/1.1 Request) |
| Affected Component | Microsoft.AspNetCore.Server.HttpSys |
| Primary Impact | Denial of Service via Unhandled Exception & Native Resource Leak |
| Exploit Status | Unproven (No Public Weaponized Exploits) |
| CISA KEV Status | Not Listed |
The application fails to release memory and native resources allocated for request contexts and unmanaged HTTP.sys handles after their effective lifetime when early parsing exceptions abort normal connection lifecycle management.
CVE-2026-124194 is a forced authentication and spoofing vulnerability in Microsoft Office Outlook caused by a missing user interface warning before dereferencing remote network paths (CWE-356). By embedding an attacker-controlled Universal Naming Convention (UNC) path within MAPI message properties such as PidLidReminderFileParameter, an unauthenticated remote attacker can force a victim's system to initiate an outbound SMB or WebDAV connection upon opening or previewing a crafted message. This automatic authentication handshake leaks the user's NetNTLMv2 hash, enabling offline password cracking or real-time NTLM relay attacks. The vulnerability was exploited in the wild as a zero-day prior to its remediation in Microsoft's November 2026 Patch Tuesday updates and is listed in the CISA Known Exploited Vulnerabilities (KEV) catalog.
A local elevation of privilege vulnerability exists in the Microsoft .NET Aspire CLI (`Aspire.Cli`) versions 13.5.4 prior to 13.6.5. When executing SDK management commands (`aspire sdk generate`, `aspire sdk dump`, and `aspire sdk export`), the CLI creates temporary project directories inside the shared operating system temporary folder (such as `/tmp` on Unix-like systems) without restricting directory permissions or disabling MSBuild automatic response file resolution. A local, low-privileged attacker on a multi-user system can place a crafted `Directory.Build.rsp` file in the shared temporary directory hierarchy. When a victim user executes an affected Aspire CLI command, MSBuild traverses upward, ingests the attacker-controlled response file, and executes arbitrary commands in the security context of the victim user.
CVE-2026-120792 is a high-severity local information disclosure vulnerability in the Microsoft .NET Aspire CLI (Aspire.Cli) affecting versions 13.5.4 prior to 13.6.5. The flaw stems from the insertion of sensitive information into a shared temporary log file (CWE-532) combined with insecure temporary file creation (CWE-377) within the DeprecatedMcpCommandScanner component. During agent configuration scanning, the CLI unconditionally appends internal workspace paths and the first 200 characters of Model Context Protocol (MCP) agent configuration files to a statically named file in the system temporary directory. On multi-user systems, unprivileged local users can read this file to harvest API keys, authentication tokens, and internal service endpoints.
CVE-2026-114159 is a heap-based buffer overflow vulnerability (CWE-122) in Microsoft.DiaSymReader.Native affecting Microsoft Visual Studio and the .NET Runtime on Windows. An integer truncation error during the parsing of oversized document names in Portable PDB symbol files causes an undersized heap allocation, leading to an out-of-bounds memory write and remote code execution.
CVE-2026-114158 is a high-severity remote code execution vulnerability affecting Microsoft Visual Studio 2026 and multiple supported servicing branches of Microsoft .NET (.NET 8.0, 9.0, 10.0, and 11.0) on Windows. The flaw resides in the native symbol reader library, Microsoft.DiaSymReader.Native, and is triggered when parsing Portable Program Database (PDB) metadata containing malformed EmbeddedSource custom debug information records. By supplying a parent Record Identifier (RID) of zero or an out-of-bounds value, an attacker causes an integer underflow during 1-based to 0-based index conversion, leading to a heap-based buffer overflow and arbitrary code execution within the context of the host developer tool or runtime.
CVE-2026-114151 is a high-severity remote code execution vulnerability affecting Microsoft Visual Studio 2026 and multiple supported versions of the Microsoft .NET runtime on Windows. The flaw resides in the native Debug Information Access (DIA) symbol reader component, Microsoft.DiaSymReader.Native. When parsing Program Database (.pdb) files, the component fails to validate the length of serialized numeric records (specifically LF_DECIMAL structures) before unpacking them into a fixed-size stack buffer. An attacker who convinces a user or automated diagnostic process to load a crafted .pdb file can trigger a stack-based buffer overflow, resulting in arbitrary code execution within the context of the host process.