You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Servicing] Port #128979 (escape quotes and backslashes in MailAddress display name) to release/10.0, 9.0 and 8.0 #136842
Please consider servicing #128979 to release/10.0, and to release/9.0
and release/8.0 while they are still in support. Opening this as a new issue because #128979, #128980 and #128635 are all locked.
Why
#128979 escapes " and \ in a MailAddress display name on the path SmtpClient
uses to write the From, To, Cc and Reply-To headers. It carries milestone
11.0-preview7 and is not on any serviced branch. Verified per branch by file content in src/libraries/System.Net.Mail/src/System/Net/Mail/MailAddress.cs, with a control term
so a zero means a real absence:
branch
escapes \ and " in Encode
control: Encode (lines containing)
lines
release/8.0
0
7
324
release/9.0
0
7
324
release/10.0
0
7
324
main
1
7
341
That matters more than the compliance framing in #128635 suggests, because the display
name is routinely filled from user-supplied text when an application sends as Name <address>. Measured on 10.0.14 against a loopback SMTP sink, with one validated
recipient and only the display name varying:
display name X" <attacker@evil.com>, "
To: "X" <attacker@evil.com>, "" <victim@good.com>
Three independent parsers read two addresses out of that header, the injected one
first, and the strict RFC 5322 parser of Python's email package reports zero
defects, so a consumer gets no signal: policy.default → 2, email.utils.getaddresses
→ 2, and System.Net.Mail's own MailAddressCollection.Add → 2. On 11.0.0-rc.3.26522.148 all three read one. The same craft injects into From, Reply-To and Cc.
The envelope is unchanged — RCPT TO stays at the recipients the application asked for
— so this is header spoofing, not delivery redirection. A reply goes to every address in Reply-To, which is where the practical loss is.
Scope notes
A caller can protect itself today with public APIs only, by round-tripping through ToString() and MailAddress.TryCreate; I measured that rejecting every one of these
inputs identically on 8.0.33, 10.0.14 and 11.0.0-rc.3. And MailAddress.ToString()
already escapes the quote on the serviced branches, so the library knows the escaping is
required and only the SmtpClient path misses it. 10.0 is in active support until
2028-11-14.
Happy to open the servicing PR against release/10.0 if that is useful.
What is the impact of the bug on your scenario? That information would help us evaulate the possibility of backport.
Note that it is too late to service 9.0 and 8.0, the branches for the final update have been already finalized and they go out of support mid November.
Understood on 9.0 and 8.0. I am dropping that part of the request and narrowing this to release/10.0 only, which is in support until 2028-11-14.
On impact I should be straight with you: I am a security researcher, not a customer with a production deployment, so there is no incident and no affected product of my own behind this. The impact I can establish is the one in the body. The display name is routinely populated from user-supplied text when an application sends as Name <address>, and a single display name injects a second address into To, From, Cc and Reply-To. Three independent parsers then read two addresses out of the resulting header, including the strict RFC 5322 parser of Python's email package, which reports zero defects so a consumer gets no signal, and System.Net.Mail's own MailAddressCollection.Add. The envelope is unchanged, RCPT TO stays at the recipients the application asked for, so this is header spoofing and not delivery redirection, and the practical loss is a reply going to the injected Reply-To.
Two limits are worth keeping in view when weighing that. A caller can protect itself today with public APIs only, by round-tripping through ToString() and MailAddress.TryCreate, and MailAddress.ToString() already escapes the quote on the serviced branches, so only the SmtpClient path omits it.
Happy to open the release/10.0 servicing PR if that helps.
Closing for now, if there is a customer scenario affected by this, feel free to reopen, comment, or open another issue.
Note that documentation states that the display name parameter is not validated. Mail address is a trusted control plane parameter and it is applications responsibility to verify that the address is valid for their scenario.
Activity
dotnet-policy-service commentedon Nov 2, 2026
Tagging subscribers to this area: @karelz, @dotnet/ncl
See info in area-owners.md if you want to be subscribed.
rzikm commentedon Nov 2, 2026
What is the impact of the bug on your scenario? That information would help us evaulate the possibility of backport.
Note that it is too late to service 9.0 and 8.0, the branches for the final update have been already finalized and they go out of support mid November.
dotnet-policy-service commentedon Nov 2, 2026
This issue has been marked
needs-author-actionand may be missing some important information.earbona23 commentedon Nov 2, 2026
Understood on 9.0 and 8.0. I am dropping that part of the request and narrowing this to
release/10.0only, which is in support until 2028-11-14.On impact I should be straight with you: I am a security researcher, not a customer with a production deployment, so there is no incident and no affected product of my own behind this. The impact I can establish is the one in the body. The display name is routinely populated from user-supplied text when an application sends as
Name <address>, and a single display name injects a second address intoTo,From,CcandReply-To. Three independent parsers then read two addresses out of the resulting header, including the strict RFC 5322 parser of Python'semailpackage, which reports zero defects so a consumer gets no signal, andSystem.Net.Mail's ownMailAddressCollection.Add. The envelope is unchanged,RCPT TOstays at the recipients the application asked for, so this is header spoofing and not delivery redirection, and the practical loss is a reply going to the injectedReply-To.Two limits are worth keeping in view when weighing that. A caller can protect itself today with public APIs only, by round-tripping through
ToString()andMailAddress.TryCreate, andMailAddress.ToString()already escapes the quote on the serviced branches, so only theSmtpClientpath omits it.Happy to open the
release/10.0servicing PR if that helps.rzikm commentedon Nov 3, 2026
Closing for now, if there is a customer scenario affected by this, feel free to reopen, comment, or open another issue.
Note that documentation states that the display name parameter is not validated. Mail address is a trusted control plane parameter and it is applications responsibility to verify that the address is valid for their scenario.