Skip to content

Add experimental support for MSC4277 #18263

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Jul 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/18263.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add experimental support for [MSC4277](https://github.com/matrix-org/matrix-spec-proposals/pull/4277).
6 changes: 6 additions & 0 deletions synapse/config/experimental.py
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,12 @@ def read_config(
# MSC4076: Add `disable_badge_count`` to pusher configuration
self.msc4076_enabled: bool = experimental.get("msc4076_enabled", False)

# MSC4277: Harmonizing the reporting endpoints
#
# If enabled, ignore the score parameter and respond with HTTP 200 on
# reporting requests regardless of the subject's existence.
self.msc4277_enabled: bool = experimental.get("msc4277_enabled", False)

# MSC4235: Add `via` param to hierarchy endpoint
self.msc4235_enabled: bool = experimental.get("msc4235_enabled", False)

Expand Down
25 changes: 19 additions & 6 deletions synapse/rest/client/reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,10 @@ async def on_POST(
"Param 'reason' must be a string",
Codes.BAD_JSON,
)
if type(body.get("score", 0)) is not int: # noqa: E721
if (
not self.hs.config.experimental.msc4277_enabled
and type(body.get("score", 0)) is not int
): # noqa: E721
raise SynapseError(
HTTPStatus.BAD_REQUEST,
"Param 'score' must be an integer",
Expand All @@ -85,10 +88,15 @@ async def on_POST(
event = None

if event is None:
raise NotFoundError(
"Unable to report event: "
"it does not exist or you aren't able to see it."
)
if self.hs.config.experimental.msc4277_enabled:
# Respond with 200 and no content regardless of whether the event
# exists to prevent enumeration attacks.
return 200, {}
else:
raise NotFoundError(
"Unable to report event: "
"it does not exist or you aren't able to see it."
)

await self.store.add_event_report(
room_id=room_id,
Expand Down Expand Up @@ -138,7 +146,12 @@ async def on_POST(

room = await self.store.get_room(room_id)
if room is None:
raise NotFoundError("Room does not exist")
if self.hs.config.experimental.msc4277_enabled:
# Respond with 200 and no content regardless of whether the room
# exists to prevent enumeration attacks.
return 200, {}
else:
raise NotFoundError("Room does not exist")

await self.store.add_room_report(
room_id=room_id,
Expand Down
33 changes: 33 additions & 0 deletions tests/rest/client/test_reporting.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from synapse.util import Clock

from tests import unittest
from tests.unittest import override_config


class ReportEventTestCase(unittest.HomeserverTestCase):
Expand Down Expand Up @@ -81,6 +82,11 @@ def test_reason_and_score_null(self) -> None:
data = {"reason": None, "score": None}
self._assert_status(400, data)

@override_config({"experimental_features": {"msc4277_enabled": True}})
def test_score_str(self) -> None:
data = {"score": "string"}
self._assert_status(200, data)

def test_cannot_report_nonexistent_event(self) -> None:
"""
Tests that we don't accept event reports for events which do not exist.
Expand All @@ -98,6 +104,19 @@ def test_cannot_report_nonexistent_event(self) -> None:
msg=channel.result["body"],
)

@override_config({"experimental_features": {"msc4277_enabled": True}})
def test_event_existence_hidden(self) -> None:
"""
Tests that the requester cannot infer the existence of an event.
"""
channel = self.make_request(
"POST",
f"rooms/{self.room_id}/report/$nonsenseeventid:test",
{"reason": "i am very sad"},
access_token=self.other_user_tok,
)
self.assertEqual(200, channel.code, msg=channel.result["body"])

def test_cannot_report_event_if_not_in_room(self) -> None:
"""
Tests that we don't accept event reports for events that exist, but for which
Expand Down Expand Up @@ -193,6 +212,20 @@ def test_cannot_report_nonexistent_room(self) -> None:
msg=channel.result["body"],
)

@override_config({"experimental_features": {"msc4277_enabled": True}})
def test_room_existence_hidden(self) -> None:
"""
Tests that the requester cannot infer the existence of a room.
"""
channel = self.make_request(
"POST",
"/_matrix/client/v3/rooms/!bloop:example.org/report",
{"reason": "i am very sad"},
access_token=self.other_user_tok,
shorthand=False,
)
self.assertEqual(200, channel.code, msg=channel.result["body"])

def _assert_status(self, response_status: int, data: JsonDict) -> None:
channel = self.make_request(
"POST",
Expand Down
Loading