Merge branch 'master' into develop
Deploy the documentation / Calculate variables for GitHub Pages deployment (push) Successful in 1s
Build docker images / Build and push image for linux/amd64 (push) Failing after 35s
Build release artifacts / Calculate list of debian distros (push) Successful in 9s
Deploy the documentation / GitHub Pages (push) Failing after 3m25s
Schema / Ensure Synapse config schema is valid (push) Successful in 16s
Schema / Ensure generated documentation is up-to-date (push) Successful in 12s
Tests / changes (push) Successful in 6s
Tests / check-lockfile (push) Successful in 10s
Tests / lint-crlf (push) Successful in 8s
Tests / lint-newsfile (push) Has been skipped
Build release artifacts / Build wheels on ubuntu-24.04 (push) Failing after 6m52s
Tests / check-schema-delta (push) Successful in 11s
Tests / lint (push) Successful in 42s
Build release artifacts / Build .deb packages (push) Failing after 2m5s
Tests / check-sampleconfig (push) Failing after 2m9s
Tests / lint-clippy (push) Successful in 1m57s
Tests / lint-rustfmt (push) Successful in 56s
Tests / lint-readme (push) Successful in 19s
Tests / lint-rust (push) Failing after 1m57s
Build release artifacts / Build sdist (push) Failing after 13m59s
Tests / Typechecking (push) Failing after 7m34s
Tests / linting-done (push) Failing after 2s
Tests / calculate-test-jobs (push) Has been skipped
Tests / trial-olddeps (push) Has been skipped
Tests / portdb (14, 3.10) (push) Has been skipped
Tests / trial-pypy (all, pypy-3.10) (push) Has been skipped
Tests / portdb (17, 3.14) (push) Has been skipped
Tests / complement (monolith, SQLite) (push) Has been skipped
Tests / complement (monolith, Postgres) (push) Has been skipped
Tests / complement (workers, Postgres) (push) Has been skipped
Tests / cargo-bench (push) Has been skipped
Tests / cargo-test (push) Has been skipped
Tests / export-data (push) Has been skipped
Tests / sytest (push) Failing after 1s
Tests / trial (push) Failing after 10s
Tests / tests-done (push) Failing after 2s
Store complement-synapse image in ghcr.io / Build and push complement image (push) Failing after 49s
Latest dependencies / sytest (bookworm) (push) Has been skipped
Latest dependencies / check_repo (push) Successful in 2s
Latest dependencies / trial (postgres, 14) (push) Has been skipped
Latest dependencies / mypy (push) Has been skipped
Latest dependencies / trial (sqlite) (push) Has been skipped
Latest dependencies / sytest (postgres, redis, bookworm, workers) (push) Has been skipped
Latest dependencies / complement (monolith, Postgres) (push) Has been skipped
Latest dependencies / complement (monolith, SQLite) (push) Has been skipped
Latest dependencies / complement (workers, Postgres) (push) Has been skipped
Latest dependencies / open-issue (push) Has been skipped
Twisted Trunk / check_repo (push) Has been skipped
Twisted Trunk / mypy (push) Has been skipped
Twisted Trunk / trial (push) Has been skipped
Twisted Trunk / complement (monolith, Postgres) (push) Has been skipped
Twisted Trunk / complement (monolith, SQLite) (push) Has been skipped
Twisted Trunk / complement (workers, Postgres) (push) Has been skipped
Twisted Trunk / open-issue (push) Has been skipped
Build release artifacts / Build wheels on ubuntu-24.04-arm (push) Has been cancelled
Build release artifacts / Attach assets to release (push) Has been cancelled
Build docker images / Build and push image for linux/arm64 (push) Has been cancelled
Build docker images / Push merged images to docker.io/matrixdotorg/synapse (push) Has been cancelled
Build docker images / Push merged images to ghcr.io/element-hq/synapse (push) Has been cancelled
Tests / lint-clippy-nightly (push) Successful in 2m18s
Twisted Trunk / sytest (push) Has been skipped

This commit is contained in:
Quentin Gliech
2026-02-12 17:23:37 +01:00
6 changed files with 153 additions and 2 deletions
+9
View File
@@ -1,3 +1,12 @@
# Synapse 1.147.1 (2026-02-12)
## Internal Changes
- Block federation requests and events authenticated using a known insecure signing key. See [CVE-2026-24044](https://www.cve.org/CVERecord?id=CVE-2026-24044) / [ELEMENTSEC-2025-1670](https://github.com/element-hq/ess-helm/security/advisories/GHSA-qwcj-h6m8-vp6q). ([\#19459](https://github.com/element-hq/synapse/issues/19459))
# Synapse 1.147.0 (2026-02-10)
No significant changes since 1.147.0rc1.
+6
View File
@@ -1,3 +1,9 @@
matrix-synapse-py3 (1.147.1) stable; urgency=medium
* New synapse release 1.147.1.
-- Synapse Packaging team <packages@matrix.org> Thu, 12 Feb 2026 15:45:15 +0000
matrix-synapse-py3 (1.147.0) stable; urgency=medium
* New synapse release 1.147.0.
+1 -1
View File
@@ -1,6 +1,6 @@
[project]
name = "matrix-synapse"
version = "1.147.0"
version = "1.147.1"
description = "Homeserver for the Matrix decentralised comms protocol"
readme = "README.rst"
authors = [
+23
View File
@@ -22,6 +22,7 @@
import abc
import logging
from contextlib import ExitStack
from http import HTTPStatus
from typing import TYPE_CHECKING, Callable, Iterable
import attr
@@ -60,6 +61,15 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
# List of Unpadded Base64 server signing keys that are known to be vulnerable to attack.
# Incoming requests from homeservers using any of these keys should be refused.
# Events containing signatures using any of these keys should be refused.
BANNED_SERVER_SIGNING_KEYS = (
# ELEMENTSEC-2025-1670
"l/O9hxMVKB6Lg+3Hqf0FQQZhVESQcMzbPN1Cz2nM3og=",
)
@attr.s(slots=True, frozen=True, cmp=False, auto_attribs=True)
class VerifyJsonRequest:
"""
@@ -349,6 +359,19 @@ class Keyring:
if key_result.valid_until_ts < verify_request.minimum_valid_until_ts:
continue
key = encode_verify_key_base64(key_result.verify_key)
if key in BANNED_SERVER_SIGNING_KEYS:
raise SynapseError(
HTTPStatus.UNAUTHORIZED,
"Server signing key %s:%s for server %s has been banned by this server"
% (
key_result.verify_key.alg,
key_result.verify_key.version,
verify_request.server_name,
),
Codes.UNAUTHORIZED,
)
await self.process_json(key_result.verify_key, verify_request)
verified = True
+46 -1
View File
@@ -20,7 +20,7 @@
#
import time
from typing import Any, cast
from unittest.mock import Mock
from unittest.mock import Mock, patch
import attr
import canonicaljson
@@ -238,6 +238,51 @@ class KeyringTestCase(unittest.HomeserverTestCase):
# self.assertFalse(d.called)
self.get_success(d)
def test_verify_json_for_server_using_banned_key(self) -> None:
"""Ensure that JSON signed using a banned server_signing_key fails verification."""
kr = keyring.Keyring(self.hs)
banned_signing_key = signedjson.key.generate_signing_key("1")
r = self.hs.get_datastores().main.store_server_keys_response(
"server9",
from_server="test",
ts_added_ms=int(time.time() * 1000),
verify_keys={
get_key_id(banned_signing_key): FetchKeyResult(
verify_key=get_verify_key(banned_signing_key), valid_until_ts=1000
)
},
# The entire response gets signed & stored, just include the bits we
# care about.
response_json={
"verify_keys": {
get_key_id(banned_signing_key): {
"key": encode_verify_key_base64(
get_verify_key(banned_signing_key)
)
}
}
},
)
self.get_success(r)
json1: JsonDict = {}
signedjson.sign.sign_json(json1, "server9", banned_signing_key)
# Ensure the signatures check out normally
d = kr.verify_json_for_server("server9", json1, 500)
self.get_success(d)
# Patch the list of banned signing keys and ensure the signature check fails
with patch.object(
keyring,
"BANNED_SERVER_SIGNING_KEYS",
(encode_verify_key_base64(get_verify_key(banned_signing_key))),
):
# should fail on a signed object signed by the banned key
d = kr.verify_json_for_server("server9", json1, 500)
self.get_failure(d, SynapseError)
def test_verify_for_local_server(self) -> None:
"""Ensure that locally signed JSON can be verified without fetching keys
over federation
+68
View File
@@ -0,0 +1,68 @@
#
# This file is licensed under the Affero General Public License (AGPL) version 3.
#
# Copyright (C) 2026 New Vector, Ltd
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# See the GNU Affero General Public License for more details:
# <https://www.gnu.org/licenses/agpl_3.0.html>.
#
#
from unittest.mock import patch
from signedjson.key import encode_verify_key_base64, get_verify_key
from synapse.crypto import keyring
from synapse.crypto.event_signing import add_hashes_and_signatures
from synapse.events import make_event_from_dict
from synapse.federation.federation_base import InvalidEventSignatureError
from tests import unittest
class FederationBaseTestCase(unittest.HomeserverTestCase):
def test_events_signed_by_banned_key_are_refused(self) -> None:
"""Ensure that event JSON signed using a banned server_signing_key fails verification."""
event_dict = {
"content": {"body": "Here is the message content"},
"event_id": "$0:domain",
"origin_server_ts": 1000000,
"type": "m.room.message",
"room_id": "!r:domain",
"sender": f"@u:{self.hs.config.server.server_name}",
"signatures": {},
"unsigned": {"age_ts": 1000000},
}
add_hashes_and_signatures(
self.hs.config.server.default_room_version,
event_dict,
self.hs.config.server.server_name,
self.hs.signing_key,
)
event = make_event_from_dict(event_dict)
fs = self.hs.get_federation_server()
# Ensure the signatures check out normally
self.get_success(
fs._check_sigs_and_hash(self.hs.config.server.default_room_version, event)
)
# Patch the list of banned signing keys and ensure the signature check fails
with patch.object(
keyring,
"BANNED_SERVER_SIGNING_KEYS",
(encode_verify_key_base64(get_verify_key(self.hs.signing_key))),
):
self.get_failure(
fs._check_sigs_and_hash(
self.hs.config.server.default_room_version, event
),
InvalidEventSignatureError,
)