fix(security): treat a new identity key as a message request, never as a known contact

A stranger could pick the display name of an existing contact ("Mom")
and appear as that contact. Messages from a key that is not in the
contact list now open a message request labelled "(unknown)": no
replies, read receipts, typing indicators, calls or name in
notifications until the user accepts it and names the contact
themselves. Names that look like an existing contact (case, diacritics,
Cyrillic/Greek homoglyphs, invisible characters) also show a warning in
the real contact's chat.

When the relay account of a known contact shows up with a different
key, the chat shows "safety number changed", verification is cleared
and the session that now belongs to the other key is dropped before
sending, so a reply never goes to the new key.
This commit is contained in:
Julius Joska
2026-10-23 10:50:42 +02:00
parent 2f6b542f24
commit 717aeed4ff
23 changed files with 999 additions and 67 deletions
@@ -341,8 +341,10 @@ class ConversationsNotifier extends AsyncNotifier<List<Conversation>> {
// Příchozí zprávy, které jsem právě přečetl → pošlu za ně potvrzení
// přečtení (sendReadReceipts sám zkontroluje, jestli je funkce zapnutá).
// Upozornění appky (notice) nikdo neposlal — potvrzovat ho nelze.
final justRead = conv.messages
.where((m) => !m.isMine(identity.id) && !m.isRead)
.where((m) =>
!m.isMine(identity.id) && !m.isRead && m.notice == null)
.toList();
conv.markAllRead(identity.id);