Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Commit

Permalink
guard against accidental modification
Browse files Browse the repository at this point in the history
  • Loading branch information
richvdh committed Oct 13, 2020
1 parent 617e8a4 commit 898196f
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
6 changes: 6 additions & 0 deletions synapse/events/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,12 @@ def auth_event_ids(self):
"""
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):
format_version = EventFormatVersions.V1 # All events of this type are V1
Expand Down
7 changes: 4 additions & 3 deletions synapse/events/third_party_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ async def check_event_allowed(
events = await self.store.get_events(prev_state_ids.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
# exercised, and it's likely to go very wrong if applied to events received over
# federation.
# Ensure that the event is frozen, to make sure that the module is not tempted
# to try to modify it. Any attempt to modify it at this point will invalidate
# the hashes and signatures.
event.freeze()

return await self.third_party_rules.check_event_allowed(event, state_events)

Expand Down
20 changes: 20 additions & 0 deletions tests/rest/client/test_third_party_rules.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,26 @@ async def check(ev, state):
self.render(request)
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):
"""The module can return a modified version of the event"""
# first patch the event checker so that it will modify the event
Expand Down

0 comments on commit 898196f

Please sign in to comment.