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

Commit f96b85e

Browse files
authored
Ensure the type of URL attributes is always str when matching against preview blacklist (#12333)
1 parent c31c109 commit f96b85e

File tree

3 files changed

+49
-4
lines changed

3 files changed

+49
-4
lines changed

changelog.d/12333.bugfix

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a long-standing bug affecting URL previews that would generate a 500 response instead of a 403 if the previewed URL includes a port that isn't allowed by the relevant blacklist.

synapse/rest/media/v1/preview_url_resource.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -200,12 +200,17 @@ async def _async_render_GET(self, request: SynapseRequest) -> None:
200200
match = False
201201
continue
202202

203+
# Some attributes might not be parsed as strings by urlsplit (such as the
204+
# port, which is parsed as an int). Because we use match functions that
205+
# expect strings, we want to make sure that's what we give them.
206+
value_str = str(value)
207+
203208
if pattern.startswith("^"):
204-
if not re.match(pattern, getattr(url_tuple, attrib)):
209+
if not re.match(pattern, value_str):
205210
match = False
206211
continue
207212
else:
208-
if not fnmatch.fnmatch(getattr(url_tuple, attrib), pattern):
213+
if not fnmatch.fnmatch(value_str, pattern):
209214
match = False
210215
continue
211216
if match:

tests/rest/media/v1/test_url_preview.py

+41-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import os
1818
import re
1919
from typing import Any, Dict, Optional, Sequence, Tuple, Type
20-
from urllib.parse import urlencode
20+
from urllib.parse import quote, urlencode
2121

2222
from twisted.internet._resolver import HostResolution
2323
from twisted.internet.address import IPv4Address, IPv6Address
@@ -69,7 +69,6 @@ def make_homeserver(self, reactor: MemoryReactor, clock: Clock) -> HomeServer:
6969
"2001:800::/21",
7070
)
7171
config["url_preview_ip_range_whitelist"] = ("1.1.1.1",)
72-
config["url_preview_url_blacklist"] = []
7372
config["url_preview_accept_language"] = [
7473
"en-UK",
7574
"en-US;q=0.9",
@@ -1123,3 +1122,43 @@ def test_cache_expiry(self) -> None:
11231122
os.path.exists(path),
11241123
f"{os.path.relpath(path, self.media_store_path)} was not deleted",
11251124
)
1125+
1126+
@unittest.override_config({"url_preview_url_blacklist": [{"port": "*"}]})
1127+
def test_blacklist_port(self) -> None:
1128+
"""Tests that blacklisting URLs with a port makes previewing such URLs
1129+
fail with a 403 error and doesn't impact other previews.
1130+
"""
1131+
self.lookups["matrix.org"] = [(IPv4Address, "10.1.2.3")]
1132+
1133+
bad_url = quote("http://matrix.org:8888/foo")
1134+
good_url = quote("http://matrix.org/foo")
1135+
1136+
channel = self.make_request(
1137+
"GET",
1138+
"preview_url?url=" + bad_url,
1139+
shorthand=False,
1140+
await_result=False,
1141+
)
1142+
self.pump()
1143+
self.assertEqual(channel.code, 403, channel.result)
1144+
1145+
channel = self.make_request(
1146+
"GET",
1147+
"preview_url?url=" + good_url,
1148+
shorthand=False,
1149+
await_result=False,
1150+
)
1151+
self.pump()
1152+
1153+
client = self.reactor.tcpClients[0][2].buildProtocol(None)
1154+
server = AccumulatingProtocol()
1155+
server.makeConnection(FakeTransport(client, self.reactor))
1156+
client.makeConnection(FakeTransport(server, self.reactor))
1157+
client.dataReceived(
1158+
b"HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n"
1159+
% (len(self.end_content),)
1160+
+ self.end_content
1161+
)
1162+
1163+
self.pump()
1164+
self.assertEqual(channel.code, 200)

0 commit comments

Comments
 (0)