Skip to content

[Servicing] Port #128979 (escape quotes and backslashes in MailAddress display name) to release/10.0, 9.0 and 8.0 #136842

Closed as not planned

Description

@earbona23

Request

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.

Activity

  1. dotnet-policy-service commented on Nov 2, 2026

    @dotnet-policy-service
    Contributor

    Tagging subscribers to this area: @karelz, @dotnet/ncl
    See info in area-owners.md if you want to be subscribed.

  2. rzikm commented on Nov 2, 2026

    @rzikm
    Member

    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.

  3. added
    needs-author-actionAn issue or pull request that requires more info or actions from the author.
    on Nov 2, 2026
  4. dotnet-policy-service commented on Nov 2, 2026

    @dotnet-policy-service
    Contributor

    This issue has been marked needs-author-action and may be missing some important information.

  5. earbona23 commented on Nov 2, 2026

    @earbona23
    Author

    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.

  6. rzikm commented on Nov 3, 2026

    @rzikm
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions