mirror of
https://github.com/element-hq/synapse.git
synced 2024-11-25 19:15:51 +03:00
Ensure the type of URL attributes is always str when matching against preview blacklist (#12333)
This commit is contained in:
parent
c31c1091d4
commit
f96b85eca8
3 changed files with 49 additions and 4 deletions
1
changelog.d/12333.bugfix
Normal file
1
changelog.d/12333.bugfix
Normal file
|
@ -0,0 +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.
|
|
@ -200,12 +200,17 @@ class PreviewUrlResource(DirectServeJsonResource):
|
||||||
match = False
|
match = False
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# Some attributes might not be parsed as strings by urlsplit (such as the
|
||||||
|
# port, which is parsed as an int). Because we use match functions that
|
||||||
|
# expect strings, we want to make sure that's what we give them.
|
||||||
|
value_str = str(value)
|
||||||
|
|
||||||
if pattern.startswith("^"):
|
if pattern.startswith("^"):
|
||||||
if not re.match(pattern, getattr(url_tuple, attrib)):
|
if not re.match(pattern, value_str):
|
||||||
match = False
|
match = False
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
if not fnmatch.fnmatch(getattr(url_tuple, attrib), pattern):
|
if not fnmatch.fnmatch(value_str, pattern):
|
||||||
match = False
|
match = False
|
||||||
continue
|
continue
|
||||||
if match:
|
if match:
|
||||||
|
|
|
@ -17,7 +17,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Optional, Sequence, Tuple, Type
|
from typing import Any, Dict, Optional, Sequence, Tuple, Type
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import quote, urlencode
|
||||||
|
|
||||||
from twisted.internet._resolver import HostResolution
|
from twisted.internet._resolver import HostResolution
|
||||||
from twisted.internet.address import IPv4Address, IPv6Address
|
from twisted.internet.address import IPv4Address, IPv6Address
|
||||||
|
@ -69,7 +69,6 @@ class URLPreviewTests(unittest.HomeserverTestCase):
|
||||||
"2001:800::/21",
|
"2001:800::/21",
|
||||||
)
|
)
|
||||||
config["url_preview_ip_range_whitelist"] = ("1.1.1.1",)
|
config["url_preview_ip_range_whitelist"] = ("1.1.1.1",)
|
||||||
config["url_preview_url_blacklist"] = []
|
|
||||||
config["url_preview_accept_language"] = [
|
config["url_preview_accept_language"] = [
|
||||||
"en-UK",
|
"en-UK",
|
||||||
"en-US;q=0.9",
|
"en-US;q=0.9",
|
||||||
|
@ -1123,3 +1122,43 @@ class URLPreviewTests(unittest.HomeserverTestCase):
|
||||||
os.path.exists(path),
|
os.path.exists(path),
|
||||||
f"{os.path.relpath(path, self.media_store_path)} was not deleted",
|
f"{os.path.relpath(path, self.media_store_path)} was not deleted",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@unittest.override_config({"url_preview_url_blacklist": [{"port": "*"}]})
|
||||||
|
def test_blacklist_port(self) -> None:
|
||||||
|
"""Tests that blacklisting URLs with a port makes previewing such URLs
|
||||||
|
fail with a 403 error and doesn't impact other previews.
|
||||||
|
"""
|
||||||
|
self.lookups["matrix.org"] = [(IPv4Address, "10.1.2.3")]
|
||||||
|
|
||||||
|
bad_url = quote("http://matrix.org:8888/foo")
|
||||||
|
good_url = quote("http://matrix.org/foo")
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
"preview_url?url=" + bad_url,
|
||||||
|
shorthand=False,
|
||||||
|
await_result=False,
|
||||||
|
)
|
||||||
|
self.pump()
|
||||||
|
self.assertEqual(channel.code, 403, channel.result)
|
||||||
|
|
||||||
|
channel = self.make_request(
|
||||||
|
"GET",
|
||||||
|
"preview_url?url=" + good_url,
|
||||||
|
shorthand=False,
|
||||||
|
await_result=False,
|
||||||
|
)
|
||||||
|
self.pump()
|
||||||
|
|
||||||
|
client = self.reactor.tcpClients[0][2].buildProtocol(None)
|
||||||
|
server = AccumulatingProtocol()
|
||||||
|
server.makeConnection(FakeTransport(client, self.reactor))
|
||||||
|
client.makeConnection(FakeTransport(server, self.reactor))
|
||||||
|
client.dataReceived(
|
||||||
|
b"HTTP/1.0 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html\r\n\r\n"
|
||||||
|
% (len(self.end_content),)
|
||||||
|
+ self.end_content
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pump()
|
||||||
|
self.assertEqual(channel.code, 200)
|
||||||
|
|
Loading…
Reference in a new issue