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.
| Package | Affected versions | Patched versions |
|---|---|---|
matrix-sydentPyPI | < 2.3.0 | 2.3.0 |
Affected products
1- Range: < 2.3.0
Patches
14469d1d42b2bRandomise multipart boundary, and include mxids in invite email notifs
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- github.com/advisories/GHSA-mh74-4m5g-fcjxghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2021-29432ghsaADVISORY
- github.com/matrix-org/sydent/commit/4469d1d42b2b1612b70638224c07e19623039c42ghsax_refsource_MISCWEB
- github.com/matrix-org/sydent/releases/tag/v2.3.0ghsax_refsource_MISCWEB
- github.com/matrix-org/sydent/security/advisories/GHSA-mh74-4m5g-fcjxghsax_refsource_CONFIRMWEB
- github.com/pypa/advisory-database/tree/main/vulns/matrix-sydent/PYSEC-2021-23.yamlghsaWEB
- pypi.org/project/matrix-sydentghsaWEB
- pypi.org/project/matrix-sydent/mitrex_refsource_MISC
News mentions
0No linked articles in our index yet.