Skip to content

Commit a9361c4

Browse files
Bail out if admin_unsafely_bypass_quarantine was used by a non-admin (#19639)
1 parent 67b4d8e commit a9361c4

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

changelog.d/19639.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a bug introduced in v1.145 where a non-admin could bypass admin checks for downloading remote quarantined media. This relied on the media already being previously present on the homeserver.

synapse/rest/client/media.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ async def on_GET(
253253
),
254254
send_cors=True,
255255
)
256+
return
256257

257258
set_cors_headers(request)
258259
set_corp_headers(request)

tests/rest/admin/test_admin.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818
# [This file includes modifications made by New Vector Limited]
1919
#
2020
#
21+
from __future__ import annotations
2122

2223
import urllib.parse
23-
from typing import cast
24+
from typing import Any, cast
25+
from unittest.mock import Mock
2426

2527
from parameterized import parameterized
2628

29+
from twisted.internet.defer import Deferred
2730
from twisted.internet.testing import MemoryReactor
2831
from twisted.web.resource import Resource
2932

@@ -70,6 +73,24 @@ def create_resource_dict(self) -> dict[str, Resource]:
7073
resources["/_matrix/media"] = self.hs.get_media_repository_resource()
7174
return resources
7275

76+
def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
77+
self.fetches: list[tuple[tuple[Any, ...], dict[str, Any]]] = []
78+
79+
# A remote fetch of media that was not intentional.
80+
# Used to check that remote media fetches do NOT happen.
81+
def unexpected_remote_fetch(*args: Any, **kwargs: Any) -> Deferred[Any]:
82+
self.fetches.append((args, kwargs))
83+
return Deferred()
84+
85+
client = Mock()
86+
client.federation_get_file = unexpected_remote_fetch
87+
client.get_file = unexpected_remote_fetch
88+
89+
return self.setup_test_homeserver(
90+
clock=clock,
91+
federation_http_client=client,
92+
)
93+
7394
def _ensure_quarantined(
7495
self,
7596
user_tok: str,
@@ -176,6 +197,28 @@ def test_admin_can_bypass_quarantine(self) -> None:
176197
),
177198
)
178199

200+
def test_non_admin_bypass_does_not_fetch_remote_media(self) -> None:
201+
self.register_user("nonadmin", "pass", admin=False)
202+
non_admin_user_tok = self.login("nonadmin", "pass")
203+
204+
channel = self.make_request(
205+
"GET",
206+
"/_matrix/client/v1/media/download/example.com/remote_media"
207+
"?admin_unsafely_bypass_quarantine=true",
208+
shorthand=False,
209+
access_token=non_admin_user_tok,
210+
await_result=False,
211+
)
212+
self.pump()
213+
214+
self.assertEqual(400, channel.code, msg=channel.json_body)
215+
self.assertEqual(
216+
channel.json_body["error"],
217+
"Must be a server admin to bypass quarantine",
218+
)
219+
# Check that a remote fetch attempt did not occur.
220+
self.assertEqual(self.fetches, [])
221+
179222
@parameterized.expand(
180223
[
181224
# Attempt quarantine media APIs as non-admin

0 commit comments

Comments
 (0)