diff --git a/changelog.d/536.misc b/changelog.d/536.misc new file mode 100644 index 00000000..ba4e04e4 --- /dev/null +++ b/changelog.d/536.misc @@ -0,0 +1 @@ +Add a config option to drop emails if user-supplied content contains a given keyword. \ No newline at end of file diff --git a/sydent/config/email.py b/sydent/config/email.py index 1398e804..8556233d 100644 --- a/sydent/config/email.py +++ b/sydent/config/email.py @@ -90,7 +90,7 @@ def parse_config(self, cfg: ConfigParser) -> bool: if room_id # filter out empty lines } self.third_party_invite_keyword_blocklist = { - keyword + keyword.casefold() for keyword in third_party_invite_keyword_blocklist.split("\n") if keyword } diff --git a/sydent/http/servlets/store_invite_servlet.py b/sydent/http/servlets/store_invite_servlet.py index d948fd05..27075eb9 100644 --- a/sydent/http/servlets/store_invite_servlet.py +++ b/sydent/http/servlets/store_invite_servlet.py @@ -94,10 +94,6 @@ def render_POST(self, request: Request) -> JsonDict: sender, "Limit exceeded for this sender" ) - for keyword in self.sydent.config.email.third_party_invite_keyword_blocklist: - if keyword in [medium, address, roomId, sender]: - raise MatrixRestError(403, "M_UNAUTHORIZED", "Invite not allowed") - globalAssocStore = GlobalAssociationStore(self.sydent) mxid = globalAssocStore.getMxid(medium, normalised_address) if mxid: @@ -140,6 +136,17 @@ def render_POST(self, request: Request) -> JsonDict: substitutions[k] = v substitutions["token"] = token + for keyword in self.sydent.config.email.third_party_invite_keyword_blocklist: + for (key, value) in args.items(): + if keyword in value.casefold(): + logger.info( + "Denying invites as %r appears in arg %r: %r", + keyword, + key, + value, + ) + raise MatrixRestError(403, "M_UNAUTHORIZED", "Invite not allowed") + # Substitutions that the template requires, but are optional to provide # to the API. extra_substitutions = [ diff --git a/tests/test_invites.py b/tests/test_invites.py index 546f759f..b8963cdd 100644 --- a/tests/test_invites.py +++ b/tests/test_invites.py @@ -106,9 +106,10 @@ def test_invited_email_address_obfuscation(self): def test_third_party_invite_keyword_block_works(self): invite_config = { "medium": "email", - "address": "evil", - "room_id": "bad", - "sender": "@bad_dude:badness.org", + "address": "foo@example.com", + "room_id": "!bar", + "sender": "@foo:example.com", + "room_name": "This is an EVIL room name.", } request, channel = make_request( self.sydent.reactor,