Skip to content

Commit 6127aa0

Browse files
Don't allow tagnames longer than 255 bytes (#18660)
1 parent 5ea2cf2 commit 6127aa0

File tree

3 files changed

+81
-1
lines changed

3 files changed

+81
-1
lines changed

changelog.d/18660.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Don't allow creation of tags with names longer than 255 bytes, as per the spec.

synapse/rest/client/tags.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,10 @@
2020
#
2121

2222
import logging
23+
from http import HTTPStatus
2324
from typing import TYPE_CHECKING, Tuple
2425

25-
from synapse.api.errors import AuthError
26+
from synapse.api.errors import AuthError, Codes, SynapseError
2627
from synapse.http.server import HttpServer
2728
from synapse.http.servlet import RestServlet, parse_json_object_from_request
2829
from synapse.http.site import SynapseRequest
@@ -35,6 +36,8 @@
3536

3637
logger = logging.getLogger(__name__)
3738

39+
MAX_TAG_LENGTH = 255
40+
3841

3942
class TagListServlet(RestServlet):
4043
"""
@@ -86,6 +89,16 @@ async def on_PUT(
8689
requester = await self.auth.get_user_by_req(request)
8790
if user_id != requester.user.to_string():
8891
raise AuthError(403, "Cannot add tags for other users.")
92+
93+
# check if the tag exceeds the length allowed by the matrix-specification
94+
# as defined in: https://spec.matrix.org/v1.15/client-server-api/#events-14
95+
if len(tag.encode("utf-8")) > MAX_TAG_LENGTH:
96+
raise SynapseError(
97+
HTTPStatus.BAD_REQUEST,
98+
"tag parameter's length is over 255 bytes",
99+
errcode=Codes.INVALID_PARAM,
100+
)
101+
89102
# Check if the user has any membership in the room and raise error if not.
90103
# Although it's not harmful for users to tag random rooms, it's just superfluous
91104
# data we don't need to track or allow.

tests/rest/client/test_tags.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"""Tests REST events for /tags paths."""
1616

1717
from http import HTTPStatus
18+
from urllib import parse as urlparse
1819

1920
import synapse.rest.admin
2021
from synapse.rest.client import login, room, tags
@@ -93,3 +94,68 @@ def test_put_tag_fails_if_room_does_not_exist(self) -> None:
9394
)
9495
# Check that the request failed with the correct error
9596
self.assertEqual(channel.code, HTTPStatus.FORBIDDEN, channel.result)
97+
98+
def test_put_tag_fails_if_tag_is_too_long(self) -> None:
99+
"""
100+
Test that a user cannot add a tag to a room that is longer than the 255 bytes
101+
allowed by the matrix specification.
102+
"""
103+
user1_id = self.register_user("user1", "pass")
104+
user1_tok = self.login(user1_id, "pass")
105+
room_id = self.helper.create_room_as(user1_id, tok=user1_tok)
106+
# create a string which is larger than 255 bytes
107+
tag = "X" * 300
108+
109+
# Make the request
110+
channel = self.make_request(
111+
"PUT",
112+
f"/user/{user1_id}/rooms/{room_id}/tags/{tag}",
113+
content={"order": 0.5},
114+
access_token=user1_tok,
115+
)
116+
# Check that the request failed
117+
self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
118+
119+
def test_put_tag_fails_if_tag_is_too_long_with_graphemes(self) -> None:
120+
"""
121+
Test that a user cannot add a tag to a room that contains graphemes which are in total
122+
longer than the 255 bytes allowed by the matrix specification.
123+
"""
124+
user1_id = self.register_user("user1", "pass")
125+
user1_tok = self.login(user1_id, "pass")
126+
room_id = self.helper.create_room_as(user1_id, tok=user1_tok)
127+
# create a string which is larger than 255 bytes (275)
128+
tag = "👩‍🚒" * 25
129+
130+
# Make the request
131+
channel = self.make_request(
132+
"PUT",
133+
f"/user/{user1_id}/rooms/{room_id}/tags/"
134+
+ urlparse.quote(tag.encode("utf-8")),
135+
content={"order": 0.5},
136+
access_token=user1_tok,
137+
)
138+
# Check that the request failed
139+
self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
140+
141+
def test_put_tag_succeeds_with_graphemes(self) -> None:
142+
"""
143+
Test that a user can add a tag to a room that contains graphemes which are in total
144+
less than the 255 bytes allowed by the matrix specification.
145+
"""
146+
user1_id = self.register_user("user1", "pass")
147+
user1_tok = self.login(user1_id, "pass")
148+
room_id = self.helper.create_room_as(user1_id, tok=user1_tok)
149+
# create a string of acceptable length (220 bytes)
150+
tag = "👩‍🚒" * 20
151+
152+
# Make the request
153+
channel = self.make_request(
154+
"PUT",
155+
f"/user/{user1_id}/rooms/{room_id}/tags/"
156+
+ urlparse.quote(tag.encode("utf-8")),
157+
content={"order": 0.5},
158+
access_token=user1_tok,
159+
)
160+
# Check that the request succeeded
161+
self.assertEqual(channel.code, HTTPStatus.OK, channel.result)

0 commit comments

Comments
 (0)