guard against accidental modification

This commit is contained in:
Richard van der Hoff 2020-10-13 22:02:41 +01:00
parent 617e8a4653
commit 898196f1cc
3 changed files with 30 additions and 3 deletions

View File

@ -312,6 +312,12 @@ class EventBase(metaclass=abc.ABCMeta):
""" """
return [e for e, _ in self.auth_events] return [e for e, _ in self.auth_events]
def freeze(self):
"""'Freeze' the event dict, so it cannot be modified by accident"""
# this will be a no-op if the event dict is already frozen.
self._dict = freeze(self._dict)
class FrozenEvent(EventBase): class FrozenEvent(EventBase):
format_version = EventFormatVersions.V1 # All events of this type are V1 format_version = EventFormatVersions.V1 # All events of this type are V1

View File

@ -69,9 +69,10 @@ class ThirdPartyEventRules:
events = await self.store.get_events(prev_state_ids.values()) events = await self.store.get_events(prev_state_ids.values())
state_events = {(ev.type, ev.state_key): ev for ev in events.values()} state_events = {(ev.type, ev.state_key): ev for ev in events.values()}
# The module can modify the event slightly if it wants, but caution should be # Ensure that the event is frozen, to make sure that the module is not tempted
# exercised, and it's likely to go very wrong if applied to events received over # to try to modify it. Any attempt to modify it at this point will invalidate
# federation. # the hashes and signatures.
event.freeze()
return await self.third_party_rules.check_event_allowed(event, state_events) return await self.third_party_rules.check_event_allowed(event, state_events)

View File

@ -114,6 +114,26 @@ class ThirdPartyRulesTestCase(unittest.HomeserverTestCase):
self.render(request) self.render(request)
self.assertEquals(channel.result["code"], b"403", channel.result) self.assertEquals(channel.result["code"], b"403", channel.result)
def test_cannot_modify_event(self):
"""cannot accidentally modify an event before it is persisted"""
# first patch the event checker so that it will try to modify the event
async def check(ev: EventBase, state):
ev.content = {"x": "y"}
return True
current_rules_module().check_event_allowed = check
# now send the event
request, channel = self.make_request(
"PUT",
"/_matrix/client/r0/rooms/%s/send/modifyme/1" % self.room_id,
{"x": "x"},
access_token=self.tok,
)
self.render(request)
self.assertEqual(channel.result["code"], b"500", channel.result)
def test_modify_event(self): def test_modify_event(self):
"""The module can return a modified version of the event""" """The module can return a modified version of the event"""
# first patch the event checker so that it will modify the event # first patch the event checker so that it will modify the event