Jul 20, 2026·6 min read·8 visits
A critical state desynchronization vulnerability in .NET's SslStream allows remote attackers to bypass mutual TLS (mTLS) policies. An attacker authenticates with a valid client certificate, requests renegotiation with an invalid or empty certificate, and relies on the server failing to clear its cached validation credentials to transmit unauthorized payloads over the unauthenticated connection.
A security feature bypass vulnerability exists in the .NET runtime's SslStream component. The flaw is caused by a state synchronization mismatch during Transport Layer Security (TLS) renegotiation or Post-Handshake Authentication (PHA). When renegotiation with a client fails due to an invalid or missing client certificate, the managed SslStream wrapper fails to invalidate its previously cached authentication properties. Consequently, downstream application logic continues to authorize requests under the context of the original valid identity, leading to incorrect authorization and authentication bypass.
CVE-2026-50528 describes a security feature bypass vulnerability located within the .NET runtime's implementation of SslStream (System.Net.Security namespace). This component serves as the core managed abstraction layer for establishing secure, transport-layer encrypted channels. The vulnerability manifests during dynamic transport state changes, specifically TLS renegotiation and Post-Handshake Authentication (PHA) routines, exposing systems utilizing mutual TLS (mTLS) to authentication bypass risks.
The vulnerability is classified under CWE-863 (Incorrect Authorization). In mutual TLS configurations, the server application queries the SslStream object to verify client certificates before granting access to protected endpoints. Because the underlying managed state machine fails to cleanly separate individual authentication epochs across renegotiations, the application exposes a critical security boundary bypass where transport state transitions fail to propagate down to authorization filters.
The root cause of CVE-2026-50528 lies in a synchronization lag between native platform security APIs and the managed .NET wrapper layers. The .NET SslStream relies on a Platform Abstraction Layer (PAL) to interface with native libraries: Schannel on Windows platforms, and OpenSSL on Linux and macOS environments. When a connection is initialized, the native layer negotiates the cryptographic parameters, and the managed SslState object caches variables such as RemoteCertificate and IsMutuallyAuthenticated.
Under normal circumstances, these variables are evaluated once. However, under TLS 1.2 renegotiation or TLS 1.3 Post-Handshake Authentication, a peer is allowed to update its credentials dynamically mid-session. When a renegotiation is triggered, the native library performs a secondary handshake. If the client fails to complete this handshake with a valid certificate, the native library flags the transport session as unauthenticated or failed.
Despite the failure at the native protocol level, the managed SslState machine fails to invalidate its internal cache. The RemoteCertificate property remains populated with the certificate provided during the initial handshake, and IsMutuallyAuthenticated remains set to true. The system fails open (CWE-636) because downstream application code evaluates the stale, cached metadata instead of querying the current, invalidated native state.
The bug resides in how SslState.cs handles transitions when the cryptographic context is renegotiated. Prior to the patch, the CompleteHandshake method inside the internal SslState class presumed that any reached state block represented a successful handshake transition, overwriting values only when new ones were successfully negotiated, rather than explicitly clearing out stale states on handshake failure.
// Vulnerable Code Path
internal void CompleteHandshake()
{
// Missing validation of state transition during renegotiation
_localCertificate = _context.LocalCertificate;
// Stale remote certificate and auth statuses are kept
_remoteCertificate = _context.RemoteCertificate;
_isMutuallyAuthenticated = _context.IsMutuallyAuthenticated;
}The official fix, introduced across commits 9db47f0b4f02e0804f4b16958f1c70068b95e7c3 and 013aa09028a670051e21cb7bd6d96cb1d761ac5d, resolves the issue by tracking the validation state explicitly. If the handshake context indicates an unresolved or failed state, the validation fields are explicitly cleared, and an exception is raised before the application can read incoming payloads.
// Patched Code Path
internal void CompleteHandshake()
{
if (!_context.IsValidHandshakeState)
{
// Explicitly clear cached properties to prevent identity inheritance
_remoteCertificate = null;
_isMutuallyAuthenticated = false;
throw new AuthenticationException("Handshake state is invalid.");
}
_localCertificate = _context.LocalCertificate;
_remoteCertificate = _context.RemoteCertificate;
_isMutuallyAuthenticated = _context.IsMutuallyAuthenticated;
}Additionally, the patch enforces the re-evaluation of custom RemoteCertificateValidationCallback results on session resumption, ensuring that validation logic is not bypassed when resuming previously established security sessions.
To execute this attack, a remote adversary must target an application utilizing .NET's SslStream configured with mutual authentication (mTLS) where the ClientCertificateRequired option is active. The attack operates entirely over the network and does not require pre-existing system privileges.
First, the attacker establishes a valid connection using a legitimate client certificate. This allows the connection to pass initial filters, prompting the .NET application to load and cache the authenticated identity context. Second, the attacker issues a TLS renegotiation message (e.g., via a ClientHello or HelloRequest frame) on the existing connection.
During renegotiation, the attacker purposely provides a spoofed, invalid, or empty certificate. While the native socket records a validation failure, the managed .NET layer continues to keep the connection socket open. Finally, the attacker sends the malicious endpoint payload. When the target server application inspects SslStream.RemoteCertificate to authorize the incoming payload, the stale, valid certificate from the initial handshake is returned, allowing the request to proceed.
The impact of CVE-2026-50528 is rated high, with a CVSS v3.1 base score of 8.2. The primary consequence is incorrect authorization, which leads directly to an authentication bypass. Because the vulnerability allows an unauthenticated attacker to assume the security context of a previously validated identity, it can lead to complete compromise of API endpoints, gRPC services, and microservice frameworks running on affected .NET runtimes.
The CVSS vector is breakdown as follows: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N. The integrity impact is high because unauthorized actions can be executed within the security context of a valid user. Confidentiality impact is low, allowing partial read access. There is no direct availability impact, as the exploit does not trigger system crashes or resource exhaustion.
The primary remediation for this vulnerability is upgrading the .NET runtime to patched versions. Microsoft has released security updates addressing the bug across all maintained release channels. Operators must update runtime environments to .NET 8.0.29, .NET 9.0.18, or .NET 10.0.6 as appropriate.
For systems where runtime patches cannot be deployed immediately, administrators should implement defensive configuration changes. The most effective workaround is disabling client-initiated renegotiation at the protocol level. For example, enforcing TLS 1.3 exclusively mitigates legacy TLS 1.2 renegotiation attack paths, as TLS 1.3 replaces renegotiation with a distinct Post-Handshake Authentication mechanism that is managed more securely.
// Secure configuration mitigating renegotiation vectors
var sslOptions = new SslServerAuthenticationOptions
{
EnabledSslProtocols = SslProtocols.Tls13,
ClientCertificateRequired = true,
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
// Implement custom validation logic
return sslPolicyErrors == SslPolicyErrors.None;
}
};Security operation centers can detect potential exploit attempts by monitoring network traffic for anomalous TLS handshake patterns. High rates of client-initiated renegotiation messages over a single TCP connection should be flagged as potential indicators of compromise.
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
.NET 8.0 Microsoft | 8.0.0 to < 8.0.29 | 8.0.29 |
.NET 9.0 Microsoft | 9.0.0 to < 9.0.18 | 9.0.18 |
.NET 10.0 Microsoft | 10.0.0 to < 10.0.6 | 10.0.6 |
Visual Studio 2022 version 17.12 Microsoft | 17.12.0 to < 17.12.22 | 17.12.22 |
Visual Studio 2022 version 17.14 Microsoft | 17.14.0 to < 17.14.36 | 17.14.36 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-863 (Primary), CWE-302, CWE-636 |
| Attack Vector | Network |
| CVSS v3.1 Score | 8.2 |
| EPSS Score | 0.00436 |
| EPSS Percentile | 35.41% |
| Impact | Security Feature Bypass |
| Exploit Status | none |
| KEV Status | Not Listed |
The software performs authorization checks but fails to correctly restrict actions, allowing a peer that fails authentication to inherit the authorized context of a different state.
A heap out-of-bounds write vulnerability exists in Pillow prior to version 12.3.0 due to an integer overflow during image expansion calculations. The subsequent patch introduced a division-by-zero regression causing denial of service.
CVE-2026-59198 is a high-severity heap out-of-bounds read vulnerability in Pillow, the Python imaging library, affecting versions from 5.2.0 up to 12.3.0. The vulnerability occurs in the TGA RLE compression path due to a calculation mismatch between the allocated packed 1-bit row buffer and the byte-level pixel stride assumption in the C-level encoder. This mismatch allows an attacker to leak up to approximately 57 KB of adjacent process heap memory directly into generated TGA image files.
A critical signed 32-bit integer overflow vulnerability was identified in Pillow (Python Imaging Library) versions prior to 12.3.0. The vulnerability resides within the native C extension library (libImaging) during coordinate and bounding box calculations in functions like ImagingPaste and ImagingFill2. Exploitation can bypass bounds and clipping safety checks, leading to a controlled heap backward underwrite and application crash.
CVE-2026-59200 is a high-severity uncontrolled resource consumption vulnerability in the Pillow Python Imaging Library. The flaw resides in the PDF stream decoder, allowing remote, unauthenticated attackers to trigger host out-of-memory crashes by submitting malicious PDF decompression bombs.
A denial-of-service (DoS) vulnerability in Pillow (Python Imaging Library) versions 12.0.0 through 12.2.0 allows unauthenticated remote attackers to trigger 100% CPU utilization and hang the processing thread. The issue occurs within the Encapsulated PostScript (EPS) image parser (PIL/EpsImagePlugin.py) due to missing validation on the byte count parsed from %%BeginBinary: comments, allowing negative values to cause an infinite backward stream seek loop. This formatting-level state-looping issue occurs during the initial format sniffing phase inside Image.open() and does not require the system Ghostscript interpreter to be executed or present. It is resolved in version 12.3.0.
A Denial of Service vulnerability exists in the JPEG2000 decoder of Pillow (versions 8.2.0 to 12.2.0) due to memory allocation state accumulation across tiles, leading to rapid process termination.