VYPR
Moderate severityNVD Advisory· Published Apr 15, 2021· Updated Aug 3, 2024

Malicious users could control the content of invitation emails

CVE-2021-29432

Description

Sydent is a reference matrix identity server. A malicious user could abuse Sydent to send out arbitrary emails from the Sydent email address. This could be used to construct plausible phishing emails, for example. This issue has been fixed in 4469d1d.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
matrix-sydentPyPI
< 2.3.02.3.0

Affected products

1

Patches

1
4469d1d42b2b

Randomise multipart boundary, and include mxids in invite email notifs

https://github.com/matrix-org/sydentErik JohnstonApr 9, 2021via ghsa
6 files changed · +57 53
  • res/matrix-org/invite_template.eml+15 16 modified
    @@ -4,19 +4,20 @@ To: %(to)s
     Message-ID: %(messageid)s
     Subject: %(subject_header_value)s
     MIME-Version: 1.0
    -Content-Type: multipart/alternative; 
    -	boundary="7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ"
    +Content-Type: multipart/alternative;
    +	boundary="%(multipart_boundary)s"
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    +--%(multipart_boundary)s
     Content-Type: text/plain; charset=UTF-8
     Content-Disposition: inline
     
     Hi,
     
    -%(sender_display_name)s has invited you into a room %(bracketed_room_name)s on
    -Matrix. To join the conversation, either pick a Matrix client from
    -https://matrix.org/docs/projects/try-matrix-now.html or use the single-click
    -link below to join via Element (requires Chrome, Firefox, Safari, iOS or Android)
    +%(sender_display_name)s %(bracketed_verified_sender)shas invited you into a room
    +%(bracketed_room_name)son Matrix. To join the conversation, either pick a
    +Matrix client from https://matrix.org/docs/projects/try-matrix-now.html or use
    +the single-click link below to join via Element (requires Chrome, Firefox,
    +Safari, iOS or Android)
     
     %(web_client_location)/#/room/%(room_id_forurl)s?email=%(to_forurl)s&signurl=https%%3A%%2F%%2Fmatrix.org%%2F_matrix%%2Fidentity%%2Fapi%%2Fv1%%2Fsign-ed25519%%3Ftoken%%3D%(token)s%%26private_key%%3D%(ephemeral_private_key)s&room_name=%(room_name_forurl)s&room_avatar_url=%(room_avatar_url_forurl)s&inviter_name=%(sender_display_name_forurl)s&guest_access_token=%(guest_access_token_forurl)s&guest_user_id=%(guest_user_id_forurl)s
     
    @@ -38,12 +39,7 @@ Thanks,
     
     Matrix
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    -Content-Type: multipart/related;
    -	boundary="M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR";
    -	type="text/html"
    -
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR
    +--%(multipart_boundary)s
     Content-Type: text/html; charset=UTF-8
     Content-Disposition: inline
     
    @@ -68,6 +64,10 @@ pre, code {
         padding: 20px;
     }
     
    +#low-contrast {
    +    color: #666666
    +}
    +
     #inner {
         width: 640px;
     }
    @@ -102,7 +102,7 @@ pre, code {
     
     <p>Hi,</p>
     
    -<p>%(sender_display_name_forhtml)s has invited you into a room %(bracketed_room_name_forhtml)s on
    +<p>%(sender_display_name_forhtml)s <span class="low-contrast">%(bracketed_verified_sender_for_html)s</span> has invited you into a room %(bracketed_room_name_forhtml)s on
     Matrix. To join the conversation, either <a href="https://matrix.org/docs/projects/try-matrix-now.html">pick a Matrix client</a> or use the single-click
     link below to join via Element (requires
     <a href="https://www.google.com/chrome">Chrome</a>,
    @@ -139,6 +139,5 @@ create new communication solutions or extend the capabilities and reach of exist
             </table>
         </body>
     </html>
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR--
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ--
    +--%(multipart_boundary)s--
    
  • res/matrix-org/verification_template.eml+5 5 modified
    @@ -4,10 +4,10 @@ To: %(to)s
     Message-ID: %(messageid)s
     Subject: Confirm your email address for Matrix
     MIME-Version: 1.0
    -Content-Type: multipart/alternative; 
    -	boundary="7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ"
    +Content-Type: multipart/alternative;
    +	boundary="%(multipart_boundary)s"
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    +--%(multipart_boundary)s
     Content-Type: text/plain; charset=UTF-8
     Content-Disposition: inline
     
    @@ -35,7 +35,7 @@ Matrix defines the standard, and provides open source reference implementations
     Matrix-compatible Servers, Clients, Client SDKs and Application Services to help you
     create new communication solutions or extend the capabilities and reach of existing ones.
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    +--%(multipart_boundary)s
     Content-Type: text/html; charset=UTF-8
     Content-Disposition: inline
     
    @@ -85,4 +85,4 @@ create new communication solutions or extend the capabilities and reach of exist
     </body>
     </html>
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ--
    +--%(multipart_boundary)s--
    
  • res/vector-im/invite_template.eml+14 15 modified
    @@ -4,17 +4,18 @@ To: %(to)s
     Message-ID: %(messageid)s
     Subject: %(subject_header_value)s
     MIME-Version: 1.0
    -Content-Type: multipart/alternative; 
    -	boundary="7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ"
    +Content-Type: multipart/alternative;
    +	boundary="%(multipart_boundary)s"
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    +--%(multipart_boundary)s
     Content-Type: text/plain; charset=UTF-8
     Content-Disposition: inline
     
     Hi,
     
    -%(sender_display_name)s has invited you into a room %(bracketed_room_name)s on
    -Element. To join the conversation please follow the link below.
    +%(sender_display_name)s %(bracketed_verified_sender)shas invited you into a room
    +%(bracketed_room_name)son Element. To join the conversation please follow the
    +link below.
     
     %(web_client_location)/#/room/%(room_id_forurl)s?email=%(to_forurl)s&signurl=https%%3A%%2F%%2Fvector.im%%2F_matrix%%2Fidentity%%2Fapi%%2Fv1%%2Fsign-ed25519%%3Ftoken%%3D%(token)s%%26private_key%%3D%(ephemeral_private_key)s&room_name=%(room_name_forurl)s&room_avatar_url=%(room_avatar_url_forurl)s&inviter_name=%(sender_display_name_forurl)s&guest_access_token=%(guest_access_token_forurl)s&guest_user_id=%(guest_user_id_forurl)s
     
    @@ -51,12 +52,7 @@ decentralized communication delivering a community of users, bridged networks,
     integrated bots and applications plus full end-to-end encryption. To learn more about
     Matrix visit https://matrix.org.
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    -Content-Type: multipart/related;
    -	boundary="M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR";
    -	type="text/html"
    -
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR
    +--%(multipart_boundary)s
     Content-Type: text/html; charset=UTF-8
     Content-Disposition: inline
     
    @@ -81,6 +77,10 @@ pre, code {
         padding: 20px;
     }
     
    +#low-contrast {
    +    color: #666666
    +}
    +
     #inner {
         width: 640px;
     }
    @@ -123,8 +123,8 @@ pre, code {
     
     <p>Hi,</p>
     
    -<p>%(sender_display_name_forhtml)s has invited you into a room %(bracketed_room_name_forhtml)s on
    -Element.</p>
    +<p>%(sender_display_name_forhtml)s <span class="low-contrast">%(bracketed_verified_sender_for_html)s</span> has invited you into a
    +room %(bracketed_room_name_forhtml)s on Element.</p>
     
     <p>
         <a
    @@ -173,6 +173,5 @@ Matrix visit https://matrix.org.</p>
             </table>
         </body>
     </html>
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR--
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ--
    +--%(multipart_boundary)s--
    
  • res/vector-im/verification_template.eml+5 11 modified
    @@ -4,10 +4,10 @@ To: %(to)s
     Message-ID: %(messageid)s
     Subject: Confirm your email address for Element
     MIME-Version: 1.0
    -Content-Type: multipart/alternative; 
    -	boundary="7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ"
    +Content-Type: multipart/alternative;
    +	boundary="%(multipart_boundary)s"
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    +--%(multipart_boundary)s
     Content-Type: text/plain; charset=UTF-8
     Content-Disposition: inline
     
    @@ -51,12 +51,7 @@ decentralized communication delivering a community of users, bridged networks,
     integrated bots and applications plus full end-to-end encryption. To learn more about
     Matrix visit https://matrix.org.
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ
    -Content-Type: multipart/related;
    -	boundary="M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR";
    -	type="text/html"
    -
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR
    +--%(multipart_boundary)s
     Content-Type: text/html; charset=UTF-8
     Content-Disposition: inline
     
    @@ -171,6 +166,5 @@ pre, code {
             </table>
         </body>
     </html>
    ---M3yzHl5YZehm9v4bAM8sKEdcOoVnRnKR--
     
    ---7REaIwWQCioQ6NaBlAQlg8ztbUQj6PKJ--
    +--%(multipart_boundary)s--
    
  • sydent/http/servlets/store_invite_servlet.py+13 6 modified
    @@ -27,11 +27,10 @@
     from sydent.db.invite_tokens import JoinTokenStore
     from sydent.db.threepid_associations import GlobalAssociationStore
     
    -from sydent.http.servlets import get_args, send_cors, jsonwrap
    +from sydent.http.servlets import get_args, send_cors, jsonwrap, MatrixRestError
     from sydent.http.auth import authV2
     from sydent.util.emailutils import sendEmail
     
    -
     class StoreInviteServlet(Resource):
         def __init__(self, syd, require_auth=False):
             self.sydent = syd
    @@ -42,15 +41,19 @@ def __init__(self, syd, require_auth=False):
         def render_POST(self, request):
             send_cors(request)
     
    -        if self.require_auth:
    -            authV2(self.sydent, request)
    -
             args = get_args(request, ("medium", "address", "room_id", "sender",))
             medium = args["medium"]
             address = args["address"]
             roomId = args["room_id"]
             sender = args["sender"]
     
    +        verified_sender = None
    +        if self.require_auth:
    +            account = authV2(self.sydent, request)
    +            verified_sender = sender
    +            if account.userId != sender:
    +                raise MatrixRestError(403, "M_UNAUTHORIZED", "'sender' doesn't match")
    +
             globalAssocStore = GlobalAssociationStore(self.sydent)
             mxid = globalAssocStore.getMxid(medium, address)
             if mxid:
    @@ -104,9 +107,13 @@ def render_POST(self, request):
             for k in extra_substitutions:
                 substitutions.setdefault(k, '')
     
    +        substitutions["bracketed_verified_sender"] = ""
    +        if verified_sender:
    +            substitutions["bracketed_verified_sender"] = "(%s) " % (verified_sender,)
    +
             substitutions["ephemeral_private_key"] = ephemeralPrivateKeyBase64
             if substitutions["room_name"] != '':
    -            substitutions["bracketed_room_name"] = "(%s)" % substitutions["room_name"]
    +            substitutions["bracketed_room_name"] = "(%s) " % substitutions["room_name"]
     
             substitutions["web_client_location"] = self.sydent.default_web_client_location
             if 'org.matrix.web_client_location' in substitutions:
    
  • sydent/util/emailutils.py+5 0 modified
    @@ -34,6 +34,7 @@
     import email.utils
     
     from sydent.util import time_msec
    +from sydent.util.tokenutils import generateAlphanumericTokenOfLength
     
     logger = logging.getLogger(__name__)
     
    @@ -74,6 +75,10 @@ def sendEmail(sydent, templateFile, mailTo, substitutions):
             allSubstitutions[k+"_forhtml"] = escape(v)
             allSubstitutions[k+"_forurl"] = urllib.parse.quote(v)
     
    +    # We add randomize the multipart boundary to stop user input from
    +    # conflicting with it.
    +    allSubstitutions["multipart_boundary"] = generateAlphanumericTokenOfLength(32)
    +
         mailString = open(templateFile).read() % allSubstitutions
         parsedFrom = email.utils.parseaddr(mailFrom)[1]
         parsedTo = email.utils.parseaddr(mailTo)[1]
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

8

News mentions

0

No linked articles in our index yet.