Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package matrix-synapse for openSUSE:Factory 
checked in at 2025-10-07 18:29:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/matrix-synapse (Old)
 and      /work/SRC/openSUSE:Factory/.matrix-synapse.new.11973 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "matrix-synapse"

Tue Oct  7 18:29:41 2025 rev:142 rq:1309635 version:1.139.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/matrix-synapse/matrix-synapse.changes    
2025-10-01 18:59:30.260805384 +0200
+++ /work/SRC/openSUSE:Factory/.matrix-synapse.new.11973/matrix-synapse.changes 
2025-10-07 18:32:04.962871439 +0200
@@ -1,0 +2,15 @@
+Tue Oct  7 13:01:53 UTC 2025 - Marcus Rueckert <[email protected]>
+
+- Update to 1.139.1 (boo#1251231)
+  - Security Fixes
+    - Fix CVE-2025-61672 / GHSA-fh66-fcv5-jjfr. Lack of validation
+      for device keys in Synapse before 1.139.1 allows an attacker
+      registered on the victim homeserver to degrade federation
+      functionality, unpredictably breaking outbound federation to
+      other homeservers. (#17097)
+  - Deprecations and Removals
+    - Drop support for unstable field names from the long-accepted
+      MSC2732 (Olm fallback keys) proposal. This change allows unit
+      tests to pass following the security patch above. (#18996)
+
+-------------------------------------------------------------------

Old:
----
  matrix-synapse-1.139.0.obscpio

New:
----
  matrix-synapse-1.139.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ matrix-synapse-test.spec ++++++
--- /var/tmp/diff_new_pack.GWsTua/_old  2025-10-07 18:32:06.274926722 +0200
+++ /var/tmp/diff_new_pack.GWsTua/_new  2025-10-07 18:32:06.274926722 +0200
@@ -27,7 +27,7 @@
 
 %define         pkgname matrix-synapse
 Name:           %{pkgname}-test
-Version:        1.139.0
+Version:        1.139.1
 Release:        0
 Summary:        Test package for %{pkgname}
 License:        AGPL-3.0-or-later

++++++ matrix-synapse.spec ++++++
--- /var/tmp/diff_new_pack.GWsTua/_old  2025-10-07 18:32:06.318928577 +0200
+++ /var/tmp/diff_new_pack.GWsTua/_new  2025-10-07 18:32:06.318928577 +0200
@@ -158,7 +158,7 @@
 %define         pkgname matrix-synapse
 %define         eggname matrix_synapse
 Name:           %{pkgname}
-Version:        1.139.0
+Version:        1.139.1
 Release:        0
 Summary:        Matrix protocol reference homeserver
 License:        AGPL-3.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.GWsTua/_old  2025-10-07 18:32:06.390931610 +0200
+++ /var/tmp/diff_new_pack.GWsTua/_new  2025-10-07 18:32:06.394931779 +0200
@@ -4,7 +4,7 @@
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="url">https://github.com/element-hq/synapse.git</param>
     <param name="scm">git</param>
-    <param name="revision">v1.139.0</param>
+    <param name="revision">v1.139.1</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="versionrewrite-replacement">\1</param>
     <!--

++++++ matrix-synapse-1.139.0.obscpio -> matrix-synapse-1.139.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/CHANGES.md 
new/matrix-synapse-1.139.1/CHANGES.md
--- old/matrix-synapse-1.139.0/CHANGES.md       2025-09-30 12:58:59.000000000 
+0200
+++ new/matrix-synapse-1.139.1/CHANGES.md       2025-10-07 12:58:08.000000000 
+0200
@@ -1,5 +1,27 @@
+# Synapse 1.139.1 (2025-10-07)
+
+## Security Fixes
+
+- Fix [CVE-2025-61672](https://www.cve.org/CVERecord?id=CVE-2025-61672) / 
[GHSA-fh66-fcv5-jjfr](https://github.com/element-hq/synapse/security/advisories/GHSA-fh66-fcv5-jjfr).
 Lack of validation for device keys in Synapse before 1.139.1 allows an 
attacker registered on the victim homeserver to degrade federation 
functionality, unpredictably breaking outbound federation to other homeservers. 
([\#17097](https://github.com/element-hq/synapse/issues/17097))
+
+## Deprecations and Removals
+
+- Drop support for unstable field names from the long-accepted 
[MSC2732](https://github.com/matrix-org/matrix-spec-proposals/pull/2732) (Olm 
fallback keys) proposal. This change allows unit tests to pass following the 
security patch above. 
([\#18996](https://github.com/element-hq/synapse/issues/18996))
+
+
+
 # Synapse 1.139.0 (2025-09-30)
 
+### `/register` requests from old application service implementations may 
break when using MAS
+
+If you are using Matrix Authentication Service (MAS), as of this release any
+Application Services that do not set `inhibit_login=true` when calling `POST
+/_matrix/client/v3/register` will receive the error
+`IO.ELEMENT.MSC4190.M_APPSERVICE_LOGIN_UNSUPPORTED` in response. Please see 
[the
+upgrade
+notes](https://element-hq.github.io/synapse/develop/upgrade.html#register-requests-from-old-application-service-implementations-may-break-when-using-mas)
+for more information.
+
 No significant changes since 1.139.0rc3.
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/debian/changelog 
new/matrix-synapse-1.139.1/debian/changelog
--- old/matrix-synapse-1.139.0/debian/changelog 2025-09-30 12:58:59.000000000 
+0200
+++ new/matrix-synapse-1.139.1/debian/changelog 2025-10-07 12:58:08.000000000 
+0200
@@ -1,3 +1,9 @@
+matrix-synapse-py3 (1.139.1) stable; urgency=medium
+
+  * New Synapse release 1.139.1.
+
+ -- Synapse Packaging team <[email protected]>  Tue, 07 Oct 2025 11:46:51 
+0100
+
 matrix-synapse-py3 (1.139.0) stable; urgency=medium
 
   * New Synapse release 1.139.0.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/pyproject.toml 
new/matrix-synapse-1.139.1/pyproject.toml
--- old/matrix-synapse-1.139.0/pyproject.toml   2025-09-30 12:58:59.000000000 
+0200
+++ new/matrix-synapse-1.139.1/pyproject.toml   2025-10-07 12:58:08.000000000 
+0200
@@ -101,7 +101,7 @@
 
 [tool.poetry]
 name = "matrix-synapse"
-version = "1.139.0"
+version = "1.139.1"
 description = "Homeserver for the Matrix decentralised comms protocol"
 authors = ["Matrix.org Team and Contributors <[email protected]>"]
 license = "AGPL-3.0-or-later"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/synapse/handlers/e2e_keys.py 
new/matrix-synapse-1.139.1/synapse/handlers/e2e_keys.py
--- old/matrix-synapse-1.139.0/synapse/handlers/e2e_keys.py     2025-09-30 
12:58:59.000000000 +0200
+++ new/matrix-synapse-1.139.1/synapse/handlers/e2e_keys.py     2025-10-07 
12:58:08.000000000 +0200
@@ -57,7 +57,6 @@
 
 logger = logging.getLogger(__name__)
 
-
 ONE_TIME_KEY_UPLOAD = "one_time_key_upload_lock"
 
 
@@ -848,14 +847,22 @@
         """
         time_now = self.clock.time_msec()
 
-        # TODO: Validate the JSON to make sure it has the right keys.
         device_keys = keys.get("device_keys", None)
         if device_keys:
+            log_kv(
+                {
+                    "message": "Updating device_keys for user.",
+                    "user_id": user_id,
+                    "device_id": device_id,
+                }
+            )
             await self.upload_device_keys_for_user(
                 user_id=user_id,
                 device_id=device_id,
                 keys={"device_keys": device_keys},
             )
+        else:
+            log_kv({"message": "Did not update device_keys", "reason": "not a 
dict"})
 
         one_time_keys = keys.get("one_time_keys", None)
         if one_time_keys:
@@ -873,10 +880,9 @@
             log_kv(
                 {"message": "Did not update one_time_keys", "reason": "no keys 
given"}
             )
-        fallback_keys = keys.get("fallback_keys") or keys.get(
-            "org.matrix.msc2732.fallback_keys"
-        )
-        if fallback_keys and isinstance(fallback_keys, dict):
+
+        fallback_keys = keys.get("fallback_keys")
+        if fallback_keys:
             log_kv(
                 {
                     "message": "Updating fallback_keys for device.",
@@ -885,8 +891,6 @@
                 }
             )
             await self.store.set_e2e_fallback_keys(user_id, device_id, 
fallback_keys)
-        elif fallback_keys:
-            log_kv({"message": "Did not update fallback_keys", "reason": "not 
a dict"})
         else:
             log_kv(
                 {"message": "Did not update fallback_keys", "reason": "no keys 
given"}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/synapse/rest/client/keys.py 
new/matrix-synapse-1.139.1/synapse/rest/client/keys.py
--- old/matrix-synapse-1.139.0/synapse/rest/client/keys.py      2025-09-30 
12:58:59.000000000 +0200
+++ new/matrix-synapse-1.139.1/synapse/rest/client/keys.py      2025-10-07 
12:58:08.000000000 +0200
@@ -23,10 +23,19 @@
 import logging
 import re
 from collections import Counter
-from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
+from http import HTTPStatus
+from typing import TYPE_CHECKING, Any, Dict, List, Mapping, Optional, Tuple, 
Union
 
+from typing_extensions import Self
+
+from synapse._pydantic_compat import (
+    StrictBool,
+    StrictStr,
+    validator,
+)
 from synapse.api.auth.mas import MasDelegatedAuth
 from synapse.api.errors import (
+    Codes,
     InteractiveAuthIncompleteError,
     InvalidAPICallError,
     SynapseError,
@@ -37,11 +46,13 @@
     parse_integer,
     parse_json_object_from_request,
     parse_string,
+    validate_json_object,
 )
 from synapse.http.site import SynapseRequest
 from synapse.logging.opentracing import log_kv, set_tag
 from synapse.rest.client._base import client_patterns, interactive_auth_handler
 from synapse.types import JsonDict, StreamToken
+from synapse.types.rest import RequestBodyModel
 from synapse.util.cancellation import cancellable
 
 if TYPE_CHECKING:
@@ -59,7 +70,6 @@
         "device_keys": {
             "user_id": "<user_id>",
             "device_id": "<device_id>",
-            "valid_until_ts": <millisecond_timestamp>,
             "algorithms": [
                 "m.olm.curve25519-aes-sha2",
             ]
@@ -111,12 +121,123 @@
         self._clock = hs.get_clock()
         self._store = hs.get_datastores().main
 
+    class KeyUploadRequestBody(RequestBodyModel):
+        """
+        The body of a `POST /_matrix/client/v3/keys/upload` request.
+
+        Based on 
https://spec.matrix.org/v1.16/client-server-api/#post_matrixclientv3keysupload.
+        """
+
+        class DeviceKeys(RequestBodyModel):
+            algorithms: List[StrictStr]
+            """The encryption algorithms supported by this device."""
+
+            device_id: StrictStr
+            """The ID of the device these keys belong to. Must match the 
device ID used when logging in."""
+
+            keys: Mapping[StrictStr, StrictStr]
+            """
+            Public identity keys. The names of the properties should be in the
+            format `<algorithm>:<device_id>`. The keys themselves should be 
encoded as
+            specified by the key algorithm.
+            """
+
+            signatures: Mapping[StrictStr, Mapping[StrictStr, StrictStr]]
+            """Signatures for the device key object. A map from user ID, to a 
map from "<algorithm>:<device_id>" to the signature."""
+
+            user_id: StrictStr
+            """The ID of the user the device belongs to. Must match the user 
ID used when logging in."""
+
+        class KeyObject(RequestBodyModel):
+            key: StrictStr
+            """The key, encoded using unpadded base64."""
+
+            fallback: Optional[StrictBool] = False
+            """Whether this is a fallback key. Only used when handling 
fallback keys."""
+
+            signatures: Mapping[StrictStr, Mapping[StrictStr, StrictStr]]
+            """Signature for the device. Mapped from user ID to another map of 
key signing identifier to the signature itself.
+
+            See the following for more detail: 
https://spec.matrix.org/v1.16/appendices/#signing-details
+            """
+
+        device_keys: Optional[DeviceKeys] = None
+        """Identity keys for the device. May be absent if no new identity keys 
are required."""
+
+        fallback_keys: Optional[Mapping[StrictStr, Union[StrictStr, 
KeyObject]]]
+        """
+        The public key which should be used if the device's one-time keys are
+        exhausted. The fallback key is not deleted once used, but should be
+        replaced when additional one-time keys are being uploaded. The server
+        will notify the client of the fallback key being used through `/sync`.
+
+        There can only be at most one key per algorithm uploaded, and the 
server
+        will only persist one key per algorithm.
+
+        When uploading a signed key, an additional fallback: true key should be
+        included to denote that the key is a fallback key.
+
+        May be absent if a new fallback key is not required.
+        """
+
+        @validator("fallback_keys", pre=True)
+        def validate_fallback_keys(cls: Self, v: Any) -> Any:
+            if v is None:
+                return v
+            if not isinstance(v, dict):
+                raise TypeError("fallback_keys must be a mapping")
+
+            for k in v.keys():
+                if not len(k.split(":")) == 2:
+                    raise SynapseError(
+                        code=HTTPStatus.BAD_REQUEST,
+                        errcode=Codes.BAD_JSON,
+                        msg=f"Invalid fallback_keys key {k!r}. "
+                        'Expected "<algorithm>:<device_id>".',
+                    )
+            return v
+
+        one_time_keys: Optional[Mapping[StrictStr, Union[StrictStr, 
KeyObject]]] = None
+        """
+        One-time public keys for "pre-key" messages. The names of the 
properties
+        should be in the format `<algorithm>:<key_id>`.
+
+        The format of the key is determined by the key algorithm, see:
+        https://spec.matrix.org/v1.16/client-server-api/#key-algorithms.
+        """
+
+        @validator("one_time_keys", pre=True)
+        def validate_one_time_keys(cls: Self, v: Any) -> Any:
+            if v is None:
+                return v
+            if not isinstance(v, dict):
+                raise TypeError("one_time_keys must be a mapping")
+
+            for k, _ in v.items():
+                if not len(k.split(":")) == 2:
+                    raise SynapseError(
+                        code=HTTPStatus.BAD_REQUEST,
+                        errcode=Codes.BAD_JSON,
+                        msg=f"Invalid one_time_keys key {k!r}. "
+                        'Expected "<algorithm>:<device_id>".',
+                    )
+            return v
+
     async def on_POST(
         self, request: SynapseRequest, device_id: Optional[str]
     ) -> Tuple[int, JsonDict]:
         requester = await self.auth.get_user_by_req(request, allow_guest=True)
         user_id = requester.user.to_string()
+
+        # Parse the request body. Validate separately, as the handler expects a
+        # plain dict, rather than any parsed object.
+        #
+        # Note: It would be nice to work with a parsed object, but the handler
+        # needs to encode portions of the request body as canonical JSON before
+        # storing the result in the DB. There's little point in converted to a
+        # parsed object and then back to a dict.
         body = parse_json_object_from_request(request)
+        validate_json_object(body, self.KeyUploadRequestBody)
 
         if device_id is not None:
             # Providing the device_id should only be done for setting keys
@@ -149,8 +270,31 @@
                 400, "To upload keys, you must pass device_id when 
authenticating"
             )
 
+        if "device_keys" in body:
+            # Validate the provided `user_id` and `device_id` fields in
+            # `device_keys` match that of the requesting user. We can't do
+            # this directly in the pydantic model as we don't have access
+            # to the requester yet.
+            #
+            # TODO: We could use ValidationInfo when we switch to Pydantic v2.
+            # 
https://docs.pydantic.dev/latest/concepts/validators/#validation-info
+            if body["device_keys"]["user_id"] != user_id:
+                raise SynapseError(
+                    code=HTTPStatus.BAD_REQUEST,
+                    errcode=Codes.BAD_JSON,
+                    msg="Provided `user_id` in `device_keys` does not match 
that of the authenticated user",
+                )
+            if body["device_keys"]["device_id"] != device_id:
+                raise SynapseError(
+                    code=HTTPStatus.BAD_REQUEST,
+                    errcode=Codes.BAD_JSON,
+                    msg="Provided `device_id` in `device_keys` does not match 
that of the authenticated user device",
+                )
+
         result = await self.e2e_keys_handler.upload_keys_for_user(
-            user_id=user_id, device_id=device_id, keys=body
+            user_id=user_id,
+            device_id=device_id,
+            keys=body,
         )
 
         return 200, result
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/matrix-synapse-1.139.0/synapse/rest/client/sync.py 
new/matrix-synapse-1.139.1/synapse/rest/client/sync.py
--- old/matrix-synapse-1.139.0/synapse/rest/client/sync.py      2025-09-30 
12:58:59.000000000 +0200
+++ new/matrix-synapse-1.139.1/synapse/rest/client/sync.py      2025-10-07 
12:58:08.000000000 +0200
@@ -363,9 +363,6 @@
 
         # 
https://github.com/matrix-org/matrix-doc/blob/54255851f642f84a4f1aaf7bc063eebe3d76752b/proposals/2732-olm-fallback-keys.md
         # states that this field should always be included, as long as the 
server supports the feature.
-        response["org.matrix.msc2732.device_unused_fallback_key_types"] = (
-            sync_result.device_unused_fallback_key_types
-        )
         response["device_unused_fallback_key_types"] = (
             sync_result.device_unused_fallback_key_types
         )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/matrix-synapse-1.139.0/tests/handlers/test_e2e_keys.py 
new/matrix-synapse-1.139.1/tests/handlers/test_e2e_keys.py
--- old/matrix-synapse-1.139.0/tests/handlers/test_e2e_keys.py  2025-09-30 
12:58:59.000000000 +0200
+++ new/matrix-synapse-1.139.1/tests/handlers/test_e2e_keys.py  2025-10-07 
12:58:08.000000000 +0200
@@ -410,7 +410,6 @@
         device_id = "xyz"
         fallback_key = {"alg1:k1": "fallback_key1"}
         fallback_key2 = {"alg1:k2": "fallback_key2"}
-        fallback_key3 = {"alg1:k2": "fallback_key3"}
         otk = {"alg1:k2": "key2"}
 
         # we shouldn't have any unused fallback keys yet
@@ -531,28 +530,6 @@
             {"failures": {}, "one_time_keys": {local_user: {device_id: 
fallback_key2}}},
         )
 
-        # using the unstable prefix should also set the fallback key
-        self.get_success(
-            self.handler.upload_keys_for_user(
-                local_user,
-                device_id,
-                {"org.matrix.msc2732.fallback_keys": fallback_key3},
-            )
-        )
-
-        claim_res = self.get_success(
-            self.handler.claim_one_time_keys(
-                {local_user: {device_id: {"alg1": 1}}},
-                self.requester,
-                timeout=None,
-                always_include_fallback_keys=False,
-            )
-        )
-        self.assertEqual(
-            claim_res,
-            {"failures": {}, "one_time_keys": {local_user: {device_id: 
fallback_key3}}},
-        )
-
     def test_fallback_key_bulk(self) -> None:
         """Like test_fallback_key, but claims multiple keys in one handler 
call."""
         alice = f"@alice:{self.hs.hostname}"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/matrix-synapse-1.139.0/tests/rest/client/test_keys.py 
new/matrix-synapse-1.139.1/tests/rest/client/test_keys.py
--- old/matrix-synapse-1.139.0/tests/rest/client/test_keys.py   2025-09-30 
12:58:59.000000000 +0200
+++ new/matrix-synapse-1.139.1/tests/rest/client/test_keys.py   2025-10-07 
12:58:08.000000000 +0200
@@ -40,6 +40,127 @@
 from tests.utils import HAS_AUTHLIB
 
 
+class KeyUploadTestCase(unittest.HomeserverTestCase):
+    servlets = [
+        keys.register_servlets,
+        admin.register_servlets_for_client_rest_resource,
+        login.register_servlets,
+    ]
+
+    def test_upload_keys_fails_on_invalid_structure(self) -> None:
+        """Check that we validate the structure of keys upon upload.
+
+        Regression test for https://github.com/element-hq/synapse/pull/17097
+        """
+        self.register_user("alice", "wonderland")
+        alice_token = self.login("alice", "wonderland")
+
+        channel = self.make_request(
+            "POST",
+            "/_matrix/client/v3/keys/upload",
+            {
+                # Error: device_keys must be a dict
+                "device_keys": ["some", "stuff", "weewoo"]
+            },
+            alice_token,
+        )
+        self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
+        self.assertEqual(
+            channel.json_body["errcode"],
+            Codes.BAD_JSON,
+            channel.result,
+        )
+
+        channel = self.make_request(
+            "POST",
+            "/_matrix/client/v3/keys/upload",
+            {
+                # Error: properties of fallback_keys must be in the form 
`<algorithm>:<device_id>`
+                "fallback_keys": {"invalid_key": "signature_base64"}
+            },
+            alice_token,
+        )
+        self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
+        self.assertEqual(
+            channel.json_body["errcode"],
+            Codes.BAD_JSON,
+            channel.result,
+        )
+
+        channel = self.make_request(
+            "POST",
+            "/_matrix/client/v3/keys/upload",
+            {
+                # Same as above, but for one_time_keys
+                "one_time_keys": {"invalid_key": "signature_base64"}
+            },
+            alice_token,
+        )
+        self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
+        self.assertEqual(
+            channel.json_body["errcode"],
+            Codes.BAD_JSON,
+            channel.result,
+        )
+
+    def test_upload_keys_fails_on_invalid_user_id_or_device_id(self) -> None:
+        """
+        Validate that the requesting user is uploading their own keys and 
nobody
+        else's.
+        """
+        device_id = "DEVICE_ID"
+        alice_user_id = self.register_user("alice", "wonderland")
+        alice_token = self.login("alice", "wonderland", device_id=device_id)
+
+        channel = self.make_request(
+            "POST",
+            "/_matrix/client/v3/keys/upload",
+            {
+                "device_keys": {
+                    # Included `user_id` does not match requesting user.
+                    "user_id": "@unknown_user:test",
+                    "device_id": device_id,
+                    "algorithms": ["m.olm.curve25519-aes-sha2"],
+                    "keys": {
+                        f"ed25519:{device_id}": "publickey",
+                    },
+                    "signatures": {},
+                }
+            },
+            alice_token,
+        )
+        self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
+        self.assertEqual(
+            channel.json_body["errcode"],
+            Codes.BAD_JSON,
+            channel.result,
+        )
+
+        channel = self.make_request(
+            "POST",
+            "/_matrix/client/v3/keys/upload",
+            {
+                "device_keys": {
+                    "user_id": alice_user_id,
+                    # Included `device_id` does not match requesting user's.
+                    "device_id": "UNKNOWN_DEVICE_ID",
+                    "algorithms": ["m.olm.curve25519-aes-sha2"],
+                    "keys": {
+                        f"ed25519:{device_id}": "publickey",
+                    },
+                    "signatures": {},
+                }
+            },
+            alice_token,
+        )
+        self.assertEqual(channel.code, HTTPStatus.BAD_REQUEST, channel.result)
+        self.assertEqual(
+            channel.json_body["errcode"],
+            Codes.BAD_JSON,
+            channel.result,
+        )
+
+
 class KeyQueryTestCase(unittest.HomeserverTestCase):
     servlets = [
         keys.register_servlets,

++++++ matrix-synapse.obsinfo ++++++
--- /var/tmp/diff_new_pack.GWsTua/_old  2025-10-07 18:32:08.931038639 +0200
+++ /var/tmp/diff_new_pack.GWsTua/_new  2025-10-07 18:32:08.935038807 +0200
@@ -1,5 +1,5 @@
 name: matrix-synapse
-version: 1.139.0
-mtime: 1759229939
-commit: 72020f3f2c1890e6b262001bcdd6f642b729b9a9
+version: 1.139.1
+mtime: 1759834688
+commit: 76b012c3f5a1d51294dabcabde31e5dce94dddf8
 

++++++ vendor.tar.zst ++++++
/work/SRC/openSUSE:Factory/matrix-synapse/vendor.tar.zst 
/work/SRC/openSUSE:Factory/.matrix-synapse.new.11973/vendor.tar.zst differ: 
char 7, line 1

Reply via email to