diff --git a/synapse/handlers/federation.py b/synapse/handlers/federation.py
index f39233d8469aeac3a72c1fe48eb7945340180a8a..ba3ede8024f86fc515404c2140fe058b48c6a80d 100644
--- a/synapse/handlers/federation.py
+++ b/synapse/handlers/federation.py
@@ -81,6 +81,7 @@ class FederationHandler(BaseHandler):
         self.pusher_pool = hs.get_pusherpool()
         self.spam_checker = hs.get_spam_checker()
         self.event_creation_handler = hs.get_event_creation_handler()
+        self._server_notices_mxid = hs.config.server_notices_mxid
 
         # When joining a room we need to queue any events for that room up
         self.room_queues = {}
@@ -1180,6 +1181,13 @@ class FederationHandler(BaseHandler):
         if not self.is_mine_id(event.state_key):
             raise SynapseError(400, "The invite event must be for this server")
 
+        # block any attempts to invite the server notices mxid
+        if event.state_key == self._server_notices_mxid:
+            raise SynapseError(
+                http_client.FORBIDDEN,
+                "Cannot invite this user",
+            )
+
         event.internal_metadata.outlier = True
         event.internal_metadata.invite_from_remote = True
 
diff --git a/synapse/handlers/room_member.py b/synapse/handlers/room_member.py
index 9b99f0f9d7beaff1c5d188d9ddb141ab95dfb436..5263f09aaa9fca89589a745cb755b79fa84a2f16 100644
--- a/synapse/handlers/room_member.py
+++ b/synapse/handlers/room_member.py
@@ -309,6 +309,13 @@ class RoomMemberHandler(object):
                 )
 
         if effective_membership_state == Membership.INVITE:
+            # block any attempts to invite the server notices mxid
+            if target.to_string() == self._server_notices_mxid:
+                raise SynapseError(
+                    http_client.FORBIDDEN,
+                    "Cannot invite this user",
+                )
+
             block_invite = False
 
             if (self._server_notices_mxid is not None and
diff --git a/synapse/server_notices/server_notices_manager.py b/synapse/server_notices/server_notices_manager.py
index 0d48aeb95ecbf65654d9c6f2355c02de427a012b..15086600ede6e11d211ec8f0f54418a76bdc7576 100644
--- a/synapse/server_notices/server_notices_manager.py
+++ b/synapse/server_notices/server_notices_manager.py
@@ -78,6 +78,11 @@ class ServerNoticesManager(object):
         )
         system_mxid = self._config.server_notices_mxid
         for room in rooms:
+            # it's worth noting that there is an asymmetry here in that we
+            # expect the user to be invited or joined, but the system user must
+            # be joined. This is kinda deliberate, in that if somebody somehow
+            # manages to invite the system user to a room, that doesn't make it
+            # the server notices room.
             user_ids = yield self._store.get_users_in_room(room.room_id)
             if system_mxid in user_ids:
                 # we found a room which our user shares with the system notice