Compare commits

...

2 Commits

Author SHA1 Message Date
Andrew Morgan
cb75484734 newsfile 2025-06-17 12:48:41 +01:00
anoa's Codex Agent
40b647d1cd Add allowlist for MSC4133 custom profile fields 2025-06-17 12:43:45 +01:00
4 changed files with 50 additions and 1 deletions

View File

@@ -0,0 +1 @@
Add `msc4133_key_allowlist` experimental option to configure a list of custom profile keys that users may set.

View File

@@ -21,7 +21,7 @@
import enum
from functools import cache
from typing import TYPE_CHECKING, Any, Optional
from typing import TYPE_CHECKING, Any, List, Optional
import attr
import attr.validators
@@ -552,6 +552,18 @@ class ExperimentalConfig(Config):
# MSC4133: Custom profile fields
self.msc4133_enabled: bool = experimental.get("msc4133_enabled", False)
self.msc4133_key_allowlist: Optional[List[str]] = experimental.get(
"msc4133_key_allowlist"
)
if self.msc4133_key_allowlist is not None:
if not isinstance(self.msc4133_key_allowlist, list) or not all(
isinstance(k, str) for k in self.msc4133_key_allowlist
):
raise ConfigError(
"experimental_features.msc4133_key_allowlist must be a list of strings",
("experimental", "msc4133_key_allowlist"),
)
# MSC4210: Remove legacy mentions
self.msc4210_enabled: bool = experimental.get("msc4210_enabled", False)

View File

@@ -481,6 +481,14 @@ class ProfileHandler:
if not by_admin and target_user != requester.user:
raise AuthError(403, "Cannot set another user's profile")
allowlist = self.hs.config.experimental.msc4133_key_allowlist
if allowlist is not None and field_name not in allowlist:
raise SynapseError(
403,
"Changing this profile field is disabled on this server",
Codes.FORBIDDEN,
)
await self.store.set_profile_field(target_user, field_name, new_value)
# Custom fields do not propagate into the user directory *or* rooms.

View File

@@ -776,6 +776,34 @@ class ProfileTestCase(unittest.HomeserverTestCase):
self.assertEqual(channel.code, 403, channel.result)
self.assertEqual(channel.json_body["errcode"], Codes.FORBIDDEN)
@unittest.override_config(
{
"experimental_features": {
"msc4133_enabled": True,
"msc4133_key_allowlist": ["allowed_field"],
}
}
)
def test_set_custom_field_not_allowlisted(self) -> None:
"""Setting a field not in the allowlist should be rejected."""
channel = self.make_request(
"PUT",
f"/_matrix/client/unstable/uk.tcpip.msc4133/profile/{self.owner}/blocked",
content={"blocked": "test"},
access_token=self.owner_tok,
)
self.assertEqual(channel.code, 403, channel.result)
self.assertEqual(channel.json_body["errcode"], Codes.FORBIDDEN)
# Allowed field should succeed.
channel = self.make_request(
"PUT",
f"/_matrix/client/unstable/uk.tcpip.msc4133/profile/{self.owner}/allowed_field",
content={"allowed_field": "ok"},
access_token=self.owner_tok,
)
self.assertEqual(channel.code, 200, channel.result)
def _setup_local_files(self, names_and_props: Dict[str, Dict[str, Any]]) -> None:
"""Stores metadata about files in the database.