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

Commit 52c88a3

Browse files
committed
Add validation for relations received over federation.
1 parent a15a893 commit 52c88a3

File tree

4 files changed

+67
-4
lines changed

4 files changed

+67
-4
lines changed

synapse/events/utils.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,6 +454,7 @@ async def _injected_bundled_aggregations(
454454
return
455455

456456
event_id = event.event_id
457+
room_id = event.room_id
457458

458459
# The bundled aggregations to include.
459460
aggregations = {}
@@ -463,7 +464,7 @@ async def _injected_bundled_aggregations(
463464
aggregations[RelationTypes.ANNOTATION] = annotations.to_dict()
464465

465466
references = await self.store.get_relations_for_event(
466-
event_id, RelationTypes.REFERENCE, direction="f"
467+
event_id, room_id, RelationTypes.REFERENCE, direction="f"
467468
)
468469
if references.chunk:
469470
aggregations[RelationTypes.REFERENCE] = references.to_dict()

synapse/rest/client/relations.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,7 @@ async def on_GET(
212212

213213
pagination_chunk = await self.store.get_relations_for_event(
214214
event_id=parent_id,
215+
room_id=room_id,
215216
relation_type=relation_type,
216217
event_type=event_type,
217218
limit=limit,
@@ -383,7 +384,9 @@ async def on_GET(
383384

384385
# This checks that a) the event exists and b) the user is allowed to
385386
# view it.
386-
await self.event_handler.get_event(requester.user, room_id, parent_id)
387+
event = await self.event_handler.get_event(requester.user, room_id, parent_id)
388+
if event is None:
389+
raise SynapseError(404, "Unknown parent event.")
387390

388391
if relation_type != RelationTypes.ANNOTATION:
389392
raise SynapseError(400, "Relation type must be 'annotation'")
@@ -402,6 +405,7 @@ async def on_GET(
402405

403406
result = await self.store.get_relations_for_event(
404407
event_id=parent_id,
408+
room_id=room_id,
405409
relation_type=relation_type,
406410
event_type=event_type,
407411
aggregation_key=key,

synapse/storage/databases/main/relations.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class RelationsWorkerStore(SQLBaseStore):
3737
async def get_relations_for_event(
3838
self,
3939
event_id: str,
40+
room_id: str,
4041
relation_type: Optional[str] = None,
4142
event_type: Optional[str] = None,
4243
aggregation_key: Optional[str] = None,
@@ -49,6 +50,7 @@ async def get_relations_for_event(
4950
5051
Args:
5152
event_id: Fetch events that relate to this event ID.
53+
room_id: The room the event belongs to.
5254
relation_type: Only fetch events with this relation type, if given.
5355
event_type: Only fetch events with this event type, if given.
5456
aggregation_key: Only fetch events with this aggregation key, if given.
@@ -63,8 +65,8 @@ async def get_relations_for_event(
6365
the form `{"event_id": "..."}`.
6466
"""
6567

66-
where_clause = ["relates_to_id = ?"]
67-
where_args: List[Union[str, int]] = [event_id]
68+
where_clause = ["relates_to_id = ?", "room_id = ?"]
69+
where_args: List[Union[str, int]] = [event_id, room_id]
6870

6971
if relation_type is not None:
7072
where_clause.append("relation_type = ?")

tests/rest/client/test_relations.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616
import itertools
1717
import urllib.parse
1818
from typing import Dict, List, Optional, Tuple
19+
from unittest.mock import patch
1920

2021
from synapse.api.constants import EventTypes, RelationTypes
2122
from synapse.rest import admin
2223
from synapse.rest.client import login, register, relations, room, sync
2324

2425
from tests import unittest
2526
from tests.server import FakeChannel
27+
from tests.test_utils.event_injection import inject_event
2628

2729

2830
class RelationsTestCase(unittest.HomeserverTestCase):
@@ -651,6 +653,60 @@ def test_aggregation_get_event_for_thread(self):
651653
},
652654
)
653655

656+
def test_ignore_invalid_room(self):
657+
"""Test that we ignore invalid relations over federation."""
658+
# Create another room and send a message in it.
659+
room2 = self.helper.create_room_as(self.user_id, tok=self.user_token)
660+
res = self.helper.send(room2, body="Hi!", tok=self.user_token)
661+
parent_id = res["event_id"]
662+
663+
# Disable the validation to pretend this came over federation.
664+
with patch(
665+
"synapse.handlers.message.EventCreationHandler._validate_event_relation"
666+
):
667+
self.get_success(
668+
inject_event(
669+
self.hs,
670+
room_id=self.room,
671+
type="m.reaction",
672+
sender=self.user_id,
673+
content={
674+
"m.relates_to": {
675+
"rel_type": RelationTypes.ANNOTATION,
676+
"event_id": parent_id,
677+
"key": "A",
678+
}
679+
},
680+
)
681+
)
682+
683+
# They should be ignored when fetching relations.
684+
channel = self.make_request(
685+
"GET",
686+
f"/_matrix/client/unstable/rooms/{room2}/relations/{parent_id}",
687+
access_token=self.user_token,
688+
)
689+
self.assertEquals(200, channel.code, channel.json_body)
690+
self.assertEqual(channel.json_body["chunk"], [])
691+
692+
# And when fetching aggregations.
693+
channel = self.make_request(
694+
"GET",
695+
f"/_matrix/client/unstable/rooms/{room2}/aggregations/{parent_id}",
696+
access_token=self.user_token,
697+
)
698+
self.assertEquals(200, channel.code, channel.json_body)
699+
self.assertEqual(channel.json_body["chunk"], [])
700+
701+
# And for bundled aggregations.
702+
channel = self.make_request(
703+
"GET",
704+
f"/rooms/{room2}/event/{parent_id}",
705+
access_token=self.user_token,
706+
)
707+
self.assertEquals(200, channel.code, channel.json_body)
708+
self.assertNotIn("m.relations", channel.json_body["unsigned"])
709+
654710
def test_edit(self):
655711
"""Test that a simple edit works."""
656712

0 commit comments

Comments
 (0)