Files
synapse/tests/crypto
Kegan DougalandClaude Opus 5 c320ced0fc Only a member key may assert its own linkage information
An `m.room.member` event's `content.localpart` and `content.domain` claim who
the member key in `state_key` belongs to, and the server named by
`content.domain` signs the event to vouch for the claim. That signature is
not enough on its own: a moderator kicking or banning a member can name a
domain they control, vouch for the claim with that domain's signing key, and
produce a verifiable but false statement about somebody else — defacing an
innocent member with an abusive localpart, or pointing them at a server that
then receives their traffic.

So require the claim to come from the member too. The member key named by
`state_key` signs the event under the entity `state_key`, with the member
keys' constant key ID, and linkage information on an event the member did not
send is ignored unless it is there. A moderator cannot produce that signature
without the member's key, and the absence of one costs them nothing: the kick
or the ban still takes effect, since this is not a validity rule. It only
decides whether anyone believes what the event says about who was kicked.

The events this server builds follow suit. A membership event sent by one of
our users about another — an invite — now carries the target's own signature
alongside ours, which is what makes it worth anything to the servers that
receive it. A kick, a ban or an unban carries no linkage information at all:
we would be asserting something we are not entitled to assert, and the
target's localpart has no business being published on somebody else's event.
Members' own events are unchanged; their `sender` signature is already their
assertion, and a second copy of it would say nothing more.

This replaces the previous arrangement, where the server's signature vouching
for linkage information was made under the constant `state_key` rather than
under the server's own name. That distinguished a claim about the target from
one about the sender, but it did not establish who was entitled to make it.
The entity name goes back to the server's name, as everywhere else in Matrix,
and `state_key` now names what it says: the member key in the event's state
key, signing for itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-15 17:12:45 +02:00
..