Nov 11, 2026·11 min read·4 visits
A race condition (CWE-362) in the ASP.NET Core Kestrel Named Pipes transport layer on Windows disposes of broken pipe streams before creating replacement instances during IOException recovery. Local attackers can exploit this brief namespace vacancy to squat on the named pipe name, override security descriptors, intercept privileged IPC traffic, and escalate privileges.
CVE-2026-114157 is a high-severity local privilege escalation and security feature bypass vulnerability affecting ASP.NET Core on Microsoft Windows. The flaw resides in the Kestrel web server's Named Pipes transport layer (Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes) and stems from a race condition (CWE-362) during broken pipe error recovery. When an active connection throws an IOException during handshake acceptance, the connection listener previously disposed of the broken NamedPipeServerStream instance before acquiring a replacement stream from its internal pool. This sequence created a momentary window where zero server instances of the named pipe existed in the Windows Named Pipe File System (NPFS). A local, low-privileged attacker can exploit this timing window to create a named pipe with the identical name and a permissive Discretionary Access Control List (DACL), hijacking subsequent inter-process communications and escalating privileges across security boundaries.
ASP.NET Core includes the Kestrel web server, which supports multiple transport layers for handling incoming requests. On Microsoft Windows platforms, Kestrel provides a Named Pipes transport (Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes) designed for high-performance, local Inter-Process Communication (IPC) without exposing network sockets. System services, desktop companion applications, and containerized workloads frequently use Kestrel over Named Pipes to expose privileged management APIs or internal RPC endpoints to local client processes.
CVE-2026-114157 is a race condition vulnerability (CWE-362) within the NamedPipeConnectionListener implementation of the Kestrel Named Pipes transport. The defect occurs when the server encounters an IOException while waiting for an incoming client connection to complete its handshake. During the error recovery routine, the listener releases the underlying operating system handle for the broken pipe before allocating a new server stream instance.
On Windows, if all server handles to a named pipe are closed, the pipe object is immediately deallocated from the Named Pipe File System (NPFS). Because Kestrel destroys the active stream before creating its successor, a brief timing window opens where the pipe name is completely unowned if no other pooled instances are currently bound.
A local attacker with low privileges (PR:L) can monitor or induce this error state and race the Kestrel server to register a new named pipe under the exact same name. By winning the race, the attacker defines the security descriptor for the pipe namespace, bypassing configurations such as CurrentUserOnly or custom Access Control Lists (ACLs). Subsequent connections from privileged clients or server worker instances bind to the attacker-controlled pipe, resulting in high impacts to both confidentiality and integrity across security boundaries (S:C).
Understanding the root cause of CVE-2026-114157 requires examining how the Windows kernel manages named pipe lifecycles within the Named Pipe File System (NPFS). When a server process initializes a named pipe via the Win32 CreateNamedPipe API (wrapped by System.IO.Pipes.NamedPipeServerStream in .NET), the very first active instance of that pipe name establishes the security descriptor, including the Discretionary Access Control List (DACL) and maximum instance count, for the entire pipe namespace (\\.\pipe\<PipeName>).
Subsequent calls to CreateNamedPipe for the same pipe name do not create a new pipe object; instead, they allocate additional server instances bound to the existing kernel object, inheriting and enforcing the security policies established by the initial creator. However, Windows maintains named pipe objects strictly through reference counting of open handles. The moment the last active server handle to a named pipe is closed or disposed, NPFS tears down the pipe object and frees the name in the global namespace. The next process to call CreateNamedPipe with that name becomes the new creator and dictates a fresh DACL.
In ASP.NET Core, NamedPipeConnectionListener manages connection acceptance using asynchronous worker loops (StartAsync) and an object pool (_namedPipeServerStreamPool). Under normal connection acceptance, Kestrel maintains continuous ownership of the pipe name by keeping multiple listener tasks active or pulling replacement streams while existing connections remain open.
The vulnerability is triggered when WaitForConnectionAsync() throws an IOException—a common occurrence when a connecting client abruptly disconnects or resets the pipe before the asynchronous accept completes. In the unpatched catch (IOException ex) block, NamedPipeConnectionListener executed nextStream.Dispose() prior to calling _namedPipeServerStreamPool.Get(). If the pool was exhausted or all concurrent listener workers experienced simultaneous broken pipe exceptions, nextStream.Dispose() closed the final server handle. During the microseconds between handle closure and the execution of _namedPipeServerStreamPool.Get(), the pipe name vanished from NPFS, enabling namespace squatting.
The defect and its corresponding fix are located in src/Servers/Kestrel/Transport.NamedPipes/src/Internal/NamedPipeConnectionListener.cs within the dotnet/aspnetcore repository. The StartAsync method runs in background tasks to accept incoming named pipe connections and hand them off to the Kestrel request processing pipeline.
In the vulnerable implementation, the exception handling block for IOException performed stream cleanup and stream allocation in the wrong sequence:
// Vulnerable code in src/Servers/Kestrel/Transport.NamedPipes/src/Internal/NamedPipeConnectionListener.cs
catch (IOException ex) when (!_listeningToken.IsCancellationRequested)
{
// WaitForConnectionAsync can throw IOException when the pipe is broken.
NamedPipeLog.ConnectionListenerBrokenPipe(_log, ex);
// FLAW: Disposing the stream first releases the OS handle.
// If no other server instances exist, the pipe name is freed in NPFS.
nextStream.Dispose();
// A race window exists here before Get() creates a new NamedPipeServerStream.
nextStream = _namedPipeServerStreamPool.Get();
}In commits 671bb7f9c84e24153ac8440e4e6de307a6cbd920 (for .NET 8.0) and a4ade6a6848f06681af1a57b5a7b555647d3e19d (for .NET 9.0), Microsoft resolved the issue by inverting the lifecycle operations during exception recovery:
File: src/Servers/Kestrel/Transport.NamedPipes/src/Internal/NamedPipeConnectionListener.cs
@@ -129,9 +129,18 @@ private async Task StartAsync(NamedPipeServerStream nextStream)
// WaitForConnectionAsync can throw IOException when the pipe is broken.
NamedPipeLog.ConnectionListenerBrokenPipe(_log, ex);
- // Dispose existing pipe, create a new one and continue accepting.
- nextStream.Dispose();
- nextStream = _namedPipeServerStreamPool.Get();
+ // Create a new pipe and continue accepting. We create the new one before disposing
+ // the broken one to ensure there is always a created stream and another process
+ // can't create a stream with the same name with a different access policy.
+ var brokenStream = nextStream;
+ try
+ {
+ nextStream = _namedPipeServerStreamPool.Get();
+ }
+ finally
+ {
+ brokenStream.Dispose();
+ }
}
catch (OperationCanceledException) when (_listeningToken.IsCancellationRequested)
{> [!NOTE]
> Even when a NamedPipeServerStream is in a broken state following an IOException, its underlying kernel handle remains open and valid for the purpose of holding the pipe name reservation and DACL within NPFS until Dispose() is explicitly called.
The patch stores a reference to the faulted stream in brokenStream, acquires a fresh NamedPipeServerStream via _namedPipeServerStreamPool.Get(), and disposes of brokenStream inside a finally block. This guarantees an overlapping handle lifetime: the new server instance binds to the existing pipe object in NPFS while brokenStream still holds an active handle, ensuring the reference count never drops to zero. Furthermore, the try...finally construct ensures that if _namedPipeServerStreamPool.Get() throws an out-of-memory or OS handle exhaustion exception, the broken stream handle is still deterministically released without causing a resource leak. The fix completely eliminates the race window on this recovery path.
Exploiting CVE-2026-114157 requires local code execution privileges on the target Windows host (AV:L/PR:L) and the presence of a privileged ASP.NET Core service configured to listen on a Kestrel Named Pipe endpoint. No public Proof-of-Concept (PoC) or active in-the-wild exploitation has been reported as of publication, and the attack complexity is rated High (AC:H) due to the tight timing constraints of the race condition.
To execute the attack, a low-privileged user process follows a multi-stage methodology:
\\.\pipe\ directory) to identify an endpoint hosted by a privileged ASP.NET Core process running as NT AUTHORITY\SYSTEM, LOCAL SERVICE, or an administrative account.catch (IOException) code path, the attacker opens client connections to the target pipe (provided the pipe ACL permits client connections from low-privileged users, or by exhausting concurrent worker instances during legitimate client activity) and immediately terminates or resets the client handle before the transport handshake finishes. Kestrel configures multiple parallel listener workers by default (NamedPipeTransportOptions.ListenerQueueCount), so the attacker must force all active listener instances into the recovery loop simultaneously or deplete the _namedPipeServerStreamPool.CreateNamedPipeW API with the target pipe name (\\.\pipe\<TargetPipe>) and a permissive SECURITY_ATTRIBUTES structure that grants GENERIC_ALL access to Everyone or Authenticated Users.CreateNamedPipeW succeeds during the gap between nextStream.Dispose() and _namedPipeServerStreamPool.Get(), the attacker controls the primary instance and the DACL of the named pipe. When Kestrel subsequently calls _namedPipeServerStreamPool.Get(), Kestrel's new server stream joins the attacker's pipe namespace (if the attacker's DACL permits it), or fails to bind if restricted. More critically, when privileged client processes connect to \\.\pipe\<TargetPipe>, their connections can be routed to the attacker's server instance. The attacker can read sensitive request payloads, inject malicious HTTP/gRPC responses back to the privileged client, or invoke ImpersonateNamedPipeClient to assume the security token of the connecting client process.Microsoft assigned CVE-2026-114157 a CVSS v3.1 base score of 7.5 (High) with the vector CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N. A key characteristic of this scoring vector is the Scope: Changed (S:C) metric. While the vulnerable component is the Kestrel Named Pipes transport layer, successful exploitation allows an attacker operating within a low-privileged user session to compromise client processes or service components operating in an elevated security context.
C:H)Inter-process communication over local named pipes is frequently assumed by application developers to be protected by operating system kernel ACLs, and therefore often transmits unencrypted HTTP or gRPC traffic without TLS. By hijacking the named pipe endpoint, an attacker can intercept authentication bearer tokens, API keys, database connection strings, or sensitive user data transmitted by local clients to the Kestrel server.
I:H)By acting as a man-in-the-middle or rogue endpoint for the named pipe, the attacker can forge responses to privileged clients or inject unauthorized commands into the Kestrel server pipeline. Additionally, if a privileged client connects to the attacker's pipe instance without restricting token impersonation (i.e., without setting SECURITY_IDENTIFICATION or SECURITY_ANONYMOUS quality of service flags), the attacker can impersonate the client's security context and execute arbitrary code as the privileged account.
A:N)The CVSS vector rates Availability impact as None (A:N), reflecting that the primary security consequence of the vulnerability is privilege escalation and security feature bypass rather than denial of service.
To remediate CVE-2026-114157, organizations must apply the November 2026 .NET servicing updates on all Windows systems running ASP.NET Core applications or Visual Studio environments. Because the vulnerability resides in the core Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes assembly distributed with the ASP.NET Core Shared Framework, updating the host runtime resolves the issue for framework-dependent deployments.
| Product / Component | Vulnerable Version Range | Patched Version |
|---|---|---|
| .NET 8.0 | >= 8.0.0 and < 8.0.34 | 8.0.34 |
| .NET 9.0 | >= 9.0.0 and < 9.0.23 | 9.0.23 |
| .NET 10.0 | >= 10.0.0 and < 10.0.15 | 10.0.15 |
| .NET 11.0 | >= 11.0.0-preview.1 and < 11.0.0 | 11.0.0 |
| Visual Studio 2022 (v17.14) | >= 17.14.0 and < 17.14.45 | 17.14.45 |
| Visual Studio 2026 (v18.11) | >= 18.11.0 and < 18.11.4 | 18.11.4 |
| Visual Studio 2026 (v18.12) | = 18.12.0 | 18.12.1+ |
> [!IMPORTANT] > Applications published as self-contained deployments bundle the ASP.NET Core runtime assemblies directly within the application directory. These applications will remain vulnerable even if the host machine's global .NET runtime is patched. Self-contained applications must be rebuilt against the updated SDK/runtime packages and redeployed.
For environments where immediate patching is not feasible, security teams can reduce the likelihood and impact of exploitation through configuration hardening and monitoring:
TokenImpersonationLevel.Identification or TokenImpersonationLevel.Anonymous when initializing NamedPipeClientStream to prevent rogue pipe servers from impersonating the client's security token.Microsoft.AspNetCore.Server.Kestrel diagnostic logging and alert on spikes in ConnectionListenerBrokenPipe events (Event ID associated with broken pipe exceptions), which indicate repeated connection failures typical of an active race condition attempt.CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
.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 |
.NET 11.0 Microsoft | >= 11.0.0-preview.1, < 11.0.0 | 11.0.0 |
Visual Studio 2022 (v17.14) Microsoft | >= 17.14.0, < 17.14.45 | 17.14.45 |
Visual Studio 2026 (v18.11) Microsoft | >= 18.11.0, < 18.11.4 | 18.11.4 |
Visual Studio 2026 (v18.12) Microsoft | = 18.12.0 | 18.12.1 |
| Attribute | Detail |
|---|---|
| Vulnerability ID | CVE-2026-114157 |
| Weakness Class | CWE-362 (Race Condition) |
| Attack Vector | Local (Windows Named Pipes IPC) |
| CVSS v3.1 Score | 7.5 High (AV:L/AC:H/PR:L/UI:N/S:C/C:H/I:H/A:N) |
| Security Impact | Local Privilege Escalation / Security Feature Bypass |
| Affected Component | Microsoft.AspNetCore.Server.Kestrel.Transport.NamedPipes |
| Exploit Status | Unproven / No public PoC |
| CISA KEV Status | Not Listed |
The program contains a code sequence that can run concurrently with other code, and the code sequence requires temporary, exclusive access to a shared resource, but a timing window exists in which the shared resource can be modified by another code sequence that is operating concurrently.
CVE-2026-114156 is an improper resolution of path equivalence vulnerability (CWE-41) in Microsoft ASP.NET Core affecting .NET 11.0 preview releases and Microsoft Visual Studio 2026. The vulnerability stems from a discrepancy between how path prefix validation helpers (such as PathString.StartsWithSegments) and downstream routing mechanisms handle alternate path separators and percent-encoded characters. An unauthenticated remote attacker can exploit this mismatch over the network to bypass path-based authorization middleware and access restricted endpoints.
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.
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.
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.