Let us contemplate how we can make XMPP service more useful and more secure.

A lot of people would like for Riseup to enable the extensions that make mobile and multi-device XMPP work better, in the opinions of Daniel Gultsch, the Conversations guy. There is a lot of stupid XMPP stuff, but elijah thinks Gultsch is actually on the right track. Also, we would like to make using Omemo trouble free, without breaking OTR. Omemo is the standard for adopting Axolotl in XMPP.

Links of interest

XMPP clients that support Omemo

Clients that don’t support Omemo

In general the IRC world is not in the same boat, it seems, although there’s no reason why it couldn’t reuse the same protocols because they have similar issues (OTR fails with multiple devices).

Encryption considerations


OMEMO is a fairly new protocol (2014) which improves upon OTR by enabling multi-user chat and multi-device support. It is inspired and based on the Axolotl protocol developped by Open Whisper Systems for their Signal protocol.

Compatibility considerations:

  • not backwards-compatible with OTR, but is being standardized as the new end-to-end encryption mechanism on XMPP: https://conversations.im/omemo/ conversations.im/xeps/multi-end.html
  • works regardless of server support, but is enhanced by Message Carbons (XEP-0280) and Message Archive Management (XEP-0313) especially for multi-device support
  • note that other protocols are being developped as well, for example OTRv4 and n1sec

Security considerations:

  • enables similar “OTR-like” capabilities, so removes the need to trust the server with the content of messages, to a certain extent
  • does not protect the roster, so the server still knows exactly who your friends are, a critical security liability
  • multi-device support means that a compromise of one of the device allows an attacker to spy on the user’s other devices, which creates a new attack surface that wasn’t present in OTR and that users may not be fully aware of. the multi-device protocol itself offers for novel way of accessing user’s cleartext, if there is a flaw in the protocol

Require encrypted messages

With mod_otr.lua (https://github.com/dgoulet/prosody-otr) we require suggest that all messages are encrypted (with a pending PR, this includes Omemo and OpenPGP).

There are three options:

  • mandatory: always enforce encrypted messages.
  • optional: warn users if a message is not encrypted.
  • mixed: mandatory encryption for user to user message, optional for muc.

Currently, the ‘mandatory’ option will disable all MUC support, even if the MUC messages are encrypted with Omemo or OpenPGP.

Current setting: optional (with omemo patch applied)

Recommendation: switch to ‘mixed’, once bug in omemo patch is fixed (patch does not work with mixed mode). In the future, switch to mandatory, once mandatory mode supports muc.


anarcat> as a user, I find this plugin uber-annoying, and comparable to “security warnings” we get that we systematically ignore. there’s a horrible “alert fatigue” here that makes the current plugin basically useless: these days I am more looking for a way to ignore server-side notifications than fixing OTR or OMEMO, which is really bad. on the other hand, i am not sure OTR/OMEMO support is mature or stable enough to be enforced as mandatory. — anarcat

elijah> I agree that a warning is often worse than saying nothing. Teaching people to ignore warnings is never a good idea. I support moving to enforced encrypted user to user encryption, but not enforced encrypted muc (guido’s ‘mixed’ mode)

Encrypted MUC

It will take some work to get encrypted MUCs working smoothly. According to this: https://github.com/siacs/Conversations/#how-does-the-encryption-for-conferences-work

  • The MUC must be private
  • Every participate must be friends with every other participant (booo)

What will it require for us to make it so that every MUC is omemo-ready?

elijah> with conversations, it just always creates MUCs that are private, although you can manually make them public.

TODO: It looks like issues should be filed here.

Compliance Extensions

Riseup’s current compliance is listed here: github.com/iNPUTmice/ComplianceTester/b...

The following standards need work on Riseup’s jabber server:

  • Message Carbons – XEP-0280: testing required to see if it breaks OTR
  • Blocking Command – XEP-0191 fixed, some tweaks remain
  • Message Archive Management – XEP-0313: to be installed with archiving disabled by default and lower retention policy, patch required to store only OMEMO messages
  • Client State Indication – XEP-0352: to be installed, with upstream patch to fix conflict with other module
  • Push Notifications – XEP-0357: to be installed
  • HTTP File Upload – XEP-0363: to be installed?

Message Carbons – XEP-0280


Traditionally, XMPP delivers a message to whatever connected client has the highest priority. With message carbons, every message is sent to all clients that request to receive carbons.

This is very useful for a modern chat experience, where it does not matter which device you are using and you might want to seemlessly switch devices.

Compatibility considerations:

  • OTR session only works for a single device at a time. If you CC messages, then one client will get a bunch of garbled ciphertext.
  • However, in many cases, simply using multiple clients at the same time is enough to mess up OTR, with or without carbons.
  • However, Message Carbons are not enabled by default. The client must request for them to be enabled. So maybe in practice there is no problem? I guess the problem would be if a client supports both OTR and Message Carbons.
  • Pidgin audium? segfaults with OTR and message carbons, according to guido

Security considerations:

  • carbon copies expose more messages to other devices and may allow an attacker to leverage a compromised device to spy on a user. note that some copies are already sent to multiple clients, depending on obscure priority rules which may not be obvious to users, so this vulnerability is already present, only to a lesser extent.


  • We could enable message carbons, but skip if message is OTR


  1. We should confirm or reject with tests if carbons will disturb OTR experience.
    1. Why would it mess up OTR: because a client might subscribe to carbons and support OTR
    2. Why it should not mess up OTR: a client needs to enable carbons, and if it does this it should be smart enough to not carbon OTR.
  2. We should enable carbons if confirm it does not mess up OTR clients
  3. install modules.prosody.im/mod_carbons.html – present in prosody-modules debian package in jessie-backports


anarcat> So far evidence of those problems is flimsy at best, and concerns only one client (Adium) that is available only on one platform (OSX). I do not think we should block this feature on that report anymore.

daniel> The Carbons/OTR problem is not something the server should be concerned about. As you said clients must enable to receive carbons. So you can be sure that all clients that enable it know how to handle it in regards to OTR. Additonally the sending client has the ability to mark a single message as ‘do not copy this message’. So well behaving clients mark OTR messages as do not copy. It also should be added that the entire unreadable ciphertext only arises when the user is logged in with multiple clients.
Just enable it. You are not the only server that has users using OTR. And people will blame the client developer anyway. (Ironically the receiving client developer even though it’s not their fault)

elijah> I would like to believe you, but other people have reported problems with pidgin when message carbons were enabled. I assume pidgin doesn’t enable them.

sol> Pidgin doesn’t support message carbons, not yet. So the problem isn’t carbons, but OTR.

anarcat> if clients support OTR and not carbon, they send “garbage” down the wire (ie. encrypted messages without the “do not copy” flag), which could confuse carbon-enabled clients. this does degrade the experience for users that have one OTR-enabled client and a carbon-enabled, not-currently-using-OTR client, as the second client will get garbage. i do not think this is a blocking issue, and would be resolved by not sending carbons to non-OMEMO clients. —anarcat

daniel> What kind of problems? Can you point to a specific report?

elijah> guido says adium segfaults with carbon copies and OTR. But… I have not been able to reproduce any crashing issue, but I don’t have mac. I think it might not be reproducible. Also, fuck adium.

Blocking Command – XEP-0191


This is a simplified version of various previous attempts at allowing the client to block other users. It is simple, and just allows you to block or unblock other user ids from being able to send you any messages.

Security considerations:

  • This leaks to the server a cleartext copy of the list of user ids you want blocked. (although, this is not much different than the existing leak of roster and messages metadata to the server)

Recommendation: let’s install it, upgrade to 0.10 and mod_blocklist

Action: mod_blocking installed on 0.9

micah> In order to support this XEP, we need this module: modules.prosody.im/mod_blocking.html, this module requires mod_privacy, which we have enabled.
Note: we are running prosody 0.9, but in the (not yet released) 0.10 its mod_blocklist instead of mod_privacy and mod_blocking (An XEP-0191 implementation without dependency on mod_privacy is available in Prosody 0.10 as mod_blocklist.)

sol> I have been running 0.10 on production servers without any hassles, even though it isn’t officially released yet.

Message Archive Management – XEP-0313


Allows XMPP to work more like IMAP, where the client can retrieve messages that were delivered while the client was offline.

Security considerations:

  • We do not want to be storing cleartext messages on the server, although note that messages are already stored in-memory in the server while they are being transmitted to the clients, sometimes for a surprisingly long time


  • We could skip archiving messages encrypted with OTR and cleartext
    • If the sending client properly marks OTR messages as ‘do not copy’ as mentioned in the Carbons section those messages don’t get archived as well.
    • elijah> Does this actually happen? Do OTR messages get marked as do not copy?


  1. install mod_mam (https://modules.prosody.im/mod_mam.html) , disable archiving by default (default_archive_policy = false) and lowering retention delay from 1 week to 2-3 days?
  2. patch mod_mam.lua to only archive omemo or openpgp messages

daniel> seems fair

micah> why do we want to skip archiving messages encrypted with OTR? It seems like if we are fine with archiving those for omemo and openpgp, then otr should be ok too?

sol> Archiving OTR doesn’t have any benefit, since it can’t be read by the client later on.

micah> we could try and filter those out, we are using mod_firewall and are already filtering out geoip storage from pep8 with this filter rule:
KIND: iq
TYPE: set
PAYLOAD: jabber.org/protocol/pubsub
INSPECT: {http://jabber.org/protocol/pubsub}pubsub/publish@node=http://jabber.org/protocol/geoloc
BOUNCE=forbidden (I’m sorry, your position is too sensitive for us to let you publish it)

daniel> mod_mam already has specific storage conditions (instead of storing every message). Those conditions can easily be adapted to store only OMEMO and pgp encrypted messages. You don’t need an extra module for that. For reference here is the line of code that we need to change: hg.prosody.im/prosody-modules/file/tip/... It might be worth making this configurable and getting it upstream.

elijah> OK, it looks easy to ignore MAM for non-omemo and non-openpgp messages, but someone will need to write and maintain the patch.

anarcat> Note that MAM messages expire after 1 week by default (configurable) and cleanup jobs are ran every 4 hours (configurable). I also believe that Prosody (and other XMPP servers) store some messages on the server for some time, regardless of this configuration, if only to have time to transfer messages to all clients. This merely writes those messages to disk instead of keeping them for memory, enabling the server to keep them longer.

anarcat> Also note that not all clients support MAM: www.zash.se/mam.html

anarcat> A good argument against MAM:

I would be ok giving up otr for the conversations that I wanted everywhere but I guess I would prefer getting what I want, and keeping otr if it meant the server stored more info, is that the option?

That is: people will disable security to get the convenience of history in their clients. That’s bad because we want to enable MAM to enable OMEMO, not just to make OTR annoying!

Client State Indication – XEP-0352


Allows the server to decide what information to push to the client based on the level of interaction the user currently has with the client. This helps considerably on mobile devices, for example, because status updates don’t need to be pushed to clients that are not open and only running in the background.

Security considerations:

  • leaks some metadata to the server, but not much.

Recommendation: install mod_csi with patch, mod_throttle_unsolicited, mod_throttle_presence

what prosody module is this, I couldn’t find it on prosody.im/doc/xeplist
it looks like it is: modules.prosody.im/mod_csi.html combined with mod_throttle_* (hg.prosody.im/prosody-modules/file/tip/..., https://hg.prosody.im/prosody-modules/file/tip/mod_throttle_unsolicited as well as mod_filter_chatstates (hg.prosody.im/prosody-modules/file/tip/...
however: 11:59:20 < Ge0rG> micah: there is a nasty bug between mod_csi, mod_smacks and mobile clients that causes people to drop out of MUCs (we are using mod_smacks) prosody.im/issues/issue/648

sol> the above issue has been fixed, and a patch is available in the above issue: hg.prosody.im/trunk/rev/eed846384178 https://hg.prosody.im/0.9/rev/caee8a32983a

Push Notifications – XEP-0357


This specification defines a way for an XMPP servers to deliver information for use in push notifications to mobile and other devices.

Gultsch’s commentary on XEP-0357 needing business rules section: mail.jabber.org/pipermail/standards/201...

Gultsch and ChatSecure talk XEP-0357 implimentation issues: github.com/ChatSecure/ChatSecure-Push-S...

A Node XMPP Push Service for XEP-0357: Push Notifications: github.com/ChatSecure/RubDub

Security considerations:

  • privacy implications as plaintext content and metadata is shared with an arbitrary “pubsub node” when `push_with_sender` or `push_with_body` are enabled, but those are disabled by default and unnecessary

Recommendation: install mod_cloud_notify hg.prosody.im/prosody-modules/file/tip/...
but the README for this says:

There are privacy implications for enabling these options because plaintext content and metadata will be shared with centralized servers (the pubsub node) run by arbitrary app developers.

This warning only effects the options push_with_sender and push_with_body which are a) disabled by default b) unnecessary

(And yes; mod_cloud_notify is the proper module for this extension)

HTTP File Upload – XEP-0363


Written by Gultsch, this XEP specification defines a protocol to request permissions from another entity to upload a file to a specific path on an HTTP server and at the same time receive a URL from which that file can later be downloaded again.

This replaces existing and complicated methods of file upload/download. It works by allowing the client a place to http upload to, and returning the url for then getting that file.

Security considerations:

  • This (temporarily) stores raw, potentially cleartext, files on some server, although it is flexible what server it is.
  • It is up to the client to determine what the use is of the GET and PUT urls it is given. Clients with Omemo support will encrypt the files before they upload them.
  • Although we can enforce encryption for messages, we cannot enforce how HTTP File Upload is used. However, only a horrible client will upload cleartext files in the middle of an encrypted chat.
  • the file expiration policies for this are unclear, if defined at all: how long are files kept on the server? how is disk space managed?

Recommendation: install mod_http_upload modules.prosody.im/mod_http_upload.html, once we have made encrypted messages required?

anarcat> I am not sure why mandatory encrypted messages are necessary here, I am not sure how it changes the security considerations above. Sure, allowing users to upload files in the clear and sharing that is a serious foot-shooting device, but they can already do that in all sorts of horrible ways anyways (dropbox, regular file transfers, etc). It seems to me XEP-0363 makes it easier for our users to share files on our infrastructure, which we control, and that makes the process a little more secure than making them revert to third-party tools because file transfers don’t work well enough in XMPP.

The key thing here would be to have uploaded files encrypted somehow, so that the storage server would be zero-knowledge. It seems to me the perfect candidate for this is share.riseup.net, although that is far from being a standard HTTP server, and probably doesn’t interoperate well with XEP-0363.

XEP-0363 does specify the protocol for uploads (HTTP PUT) and recommends that file be stored “as long as possible”, but allowing that the server “MAY” expire files after a certain per-user disk quota has been reached, without explaining how this works.

Note that file uploads are limited to 10MB which may be a little small, it is unclear if this is a Lua/Prosody limitation or just a safeguard. Also note that the Prosody module makes no provision for interoperability with third-party services: it implements its own HTTP service, so improvements on encryption mechanisms would need to be implemented there or on the client side. Also note that the Conversations people are working on a XEP for encrypted file transfers as well, in conversations.im/xeps/omemo-filetransfe... —anarcat

First principles

  • We do not want to add to the liability of riseup by having riseup store more information than it already does.
  • We do not want to give users a false sense of security.
    • We don’t want people to think their cleartext chats have security properties that they do not.
    • We don’t want people to think their encrypted chats have security properties that they do not.

Threat modeling for chat is basically endless. If we exclude for moment all the issues with different forms of message encryption, that leaves us with the following big threats:

Data at rest

  • Riseup is compromised in some way, and stored data is read.
  • The other non-riseup provider is compromised in some way.
  • A user’s device is taken into possession by the attacker, and archive of messages are read.

Data in transit

  • Riseup is compromised in some way, and data in transit is read.
  • The other non-riseup provider is compromised in some way
  • An attacker is able to intercept or MiTM messages while in transit, without compromising providers.
  • A user’s device is taken into possession by the attacker, and a bug is placed on the device.
  • Users have not mutually authenticated, and encrypted messages are MiTM’ed.

Potential areas of data retention

  • IP address — we choose to not retain.
  • Message metadata — we choose not to retain.
  • Roster — currently, we must retain.
  • HTTP upload — we would prefer not to have any cleartext file uploads stored, but cleartext links to uncontrolled third-party services are currently exchanged.
  • Message copies — we would prefer not to have any cleartext messages stored, but copies of the cleartext is currently retained in memory unless e2e encryption like OTR or OMEMO is used

Potential areas of user confusion

Users think “riseup is secure”

Users think “Riseup is secure” but use XMPP without any message encryption. For many threat models, this is actually fine. However, from the perspective of Riseup, this is horrible, because we don’t ever want the opportunity to be able to read user messages. Also, who knows who the other provider is. Message encryption is necessary when your threat model includes the providers or the CA system, but this is difficult to communicate to users.

Changes to address this:

(1) We can make the use of message encryption required. This has the advantage of removing user choice, which can be a good thing, because it reduces the possibilities for mistakes. With required message encryption, it is more simple, people can say “use riseup” and it will be more meaningful, because more either more threat models will be covered or it will just refuse to work.

Users think “encryption solves everything”

Users think “my messages are secure because they are encrypted” but their client logs all the encrypted messages. If a user’s threat model includes their device being taken, this is bad for them. All clients can log encrypted chats, only a few default to not logging encrypted chats (e.g. pidgin + otr). Signal allows for a separate passphrase to encrypt the chat archive, but smart money says even people who use this feature don’t set long enough passphrases to be meaningful against offline attacks.

elijah> I don’t think there is anything we can do in these cases other than write our own client.
anarcat> how about filing issues with problematic clients?

Users forget about multiple devices

Users think “my messages are secure because they are encrypted” but they forget they are running multiple devices and some messages are copied to a device that is not secure or is no longer in their possession. This is a new threat introduced with carbon copies, which I think is the crux of much of the debate here.

elijah> this is a new problem, but one that must be addresses by the clients. This cannot be the responsibility of the service provider. If a user chooses to have multiple devices, we should not be making their life artifically more difficult.

Users do not authenticate fingerprints

All the of methods of message encryption that are used rely on manual verification of fingerprints for any authenticity. In general, people just don’t do this, and they ignore when new keys are generated. This is a horrible horrible security flaw in all these systems, because without strong authenticity there is no real confidentiality.

amonk> Not all. OTR now offers the Socialist Millionaire Protocol (SMP) as an option. But in my experience, almost no one uses OTR properly and thus securely, even people who are supposed to be security geeks. And the issue is not just poor operational security. They often don’t understand how it all works well enough to even be able to implement decent operational security. Almost always even when using OTR with a new “security geek” person, I have to explain how to do things properly, and even then be relatively adamant that we do so in order to achieve it. It’s a rough prospect, virtually impossible with “regular people,” and especially if SMP is not working for some reason.

elijah> SMP falls into the category of elegant math that is utterly useless in the real world.

Compared with Signal

It may be worth comparing a fully-featured OMEMO server/client setup to what we are actually trying to replace, which is usually Signal.

Feature Signal OMEMO
Contact discovery Okay, phone number-based, but relies on the phone monopolies which are hackable Okay, needs explicit contact, can reuse email identifiers and contact lists
Contact storage Excellent, protected and ephemeral server-side Poor, roster usually in clear-text on the server
Transport privacy Excellent, the reknown Axolotol algorithm Good, based on Axolotol, but not well deployed everywhere
User experience Excellent, minimal friction, no password Poor, needs registration, storing passwords and UIs of clients are generally poorly designed
Federation Poor, no federation Good, traditionnal client/server model, like email addresses
Software freedom Limited: voice calling server closed source Excellent: everything is free software in the stack
Feature set Good, supports messaging, file transfers and phone calls, no video calls Okay, messaging and file transfers generally work, but phone calls are usually incompatible add-ons

I may be missing some criterions here…


anarcat> In general, the premise of this document is a tension between “making XMPP more useful and more secure”. certain XEPs like MAM or HTTP file uploads do make the service much more useful, at a cost of extending the attack surface (MAM because it stores more messages on the server and HTTP because it encourages people to send cleartext files on the server). I still believe that enabling those modules will enhance the user experience well enough that they warrant such tradeoffs. I see those issues as orthogonal: the server must do what it can to help clients implement better protocols, but in the end, the clients are responsible for what they send to the server. For example, since some clients do not support OMEMO, that creates huge security liabilities on the server. That shouldn’t keep us from making a service that imposes less of a battery drain on mobile clients.

micah> I disagree with this perspective. As discussed before, there are innumerable client mishaps, either bugs or accidents, that cause users to do things that they actually didn’t intend to do. This is why we want to turn mandatory encryption on by default, because people keep screwing it up and accidentally connecting in the clear. Just because someone can use dropbox instead of something more secure, doesn’t mean that we should be trying to make things more secure by default, instead of more usable by default and trading out security. If people want something more usable, they can go use dropbox, but they expect that our service will keep things as secure as possible, and will chose to use riseup for that purpose. We need to balance the usability concerns, so it isn’t just some crazy howto that only can be followed on debian on the cli, with ‘use riseup, its secure’

anarcat> I guess this discussion belongs more in the ticket, i didn’t realize i could post there. ;) But I suspect you may have misunderstood my perspective: i do not want to keep riseup from enforcing encryption by default as a general rule, i just feel that OTR and OMEMO are not stable, mature or well-distributed enough to do this right now. And yes, Riseup’s XMPP server is probably one of the most secure available out there right now. I do not believe enabling the above XEPs (apart from MAM, and even there: storage can be disabled by default) will break the promise that Riseup is making things as secure as possible.

elijah> there are different competing issues that need to separated out.

(1) What server do we want now
(2) What server do we want ideally
(3) How do we transition from #1 to #2

amonk> It seems to me that too much is being made of client issues. A service provider’s responsibility ends with the service. Provide maximum possible enforced security in the service (and reasonable educational resources regarding use). The clients used, and how used, are beyond scope. If a given client does not work with the service because of the provider’s decisions (security based in this case), so be it. The users can use a client that works or use another service. Furthermore, regarding the age old conflict between security and usability, where to fall on that continuum is relative. Sometimes, one should settle more toward the usability end, but in the case of something like risup, one should definitely settle more toward the security end. If a user wants more fluff, they can use a fluffy service instead. This one provides a certain level, and reasonable expectation, of security (or, is at least supposed to do so). If/where it does not do that, it has failed. Finally, regarding OMEMO, notwithstanding its us of the signal protocol, it is primarily a fluff feature in practice at present, granting that OTR already fulfills its security proposition fairly well. Simultaneous multi-device capabilities are not a security need. The protocol is still very young and has some significant security problems as yet. Keep an eye on it, test it, sure, but it’s not ready for prime time yet with regard to security. Users can get uber convenience and fluff everywhere. What they can’t get everywhere is any reasonable assurance of security (especially if they are not specialists in that area, and as we know, nearly none are). What risuep should be primarily concerned with is helping such users defend themselves. If it fails in that (and especially in deference to fluff), it may as well be google.

elijah> i am not sure what you are advocating for, but I don’t consider support for time shifted messages to be fluff. I find that i don’t ever use protocols that don’t let me receive messages when I am not actively logged in. People who find IRC useful are people who have figured out a way to receive messages offline, either using screen + irssi or an IRC proxy. I end up using Signal more than XMPP because it supports time shifted messaging, even though I would much rather use XMPP.

amonk> I am advocating for security over features. If the idea is to communicate securely, everything beyond that is “fluff.” If you can have the latter without reducing the former, great. If not, don’t. Perhaps I should have used a less derogatory term. Also, the idea of IM at least used to be to leave the client running at least most of the time, thus providing a reasonable level of asynchronicity. And I agree about convenience/features/“fluff” in general use, but when one really needs security, nothing else even comes close in importance. I thought riseup was trying to provide a high level of security for the communication of radical/revolutionary thought. If so, security is more important than any other feature. If not, it’s all good.

elijah> this is all fuzzy thinking to me until someone can explain the exact threats that enabling carbons and MAM introduce. My problem with the discussion so far is that I think it is absolutely essential to draw a distinction between attack vectors that are invisible to user, and thus potentially disasterious to them because they cannot take them into account, and attack vectors which are obvious to the user. For example, an attack like SSL striping is a real problem for users, because it is totally impossible for them to imagine, so it is good that everyone moved quickly to prevent this attack. However, security practices like forcing users to change their passwords are incredibly counterproductive. Message carbons open an additional attack surface, but only for users who enable it explicity and only in a way that is immediately obvious to the user.

elijah> there are basically two objections to carbons and MAM:

  1. it will fuck up existing clients
  2. clients that take advantage of carbons and MAM are less secure because there are more copies of every message

The first proposition is empirically testable! We should stop having this conversation about #1 and just run actual experiments. The second proposition is patronizing to users and assumes that everyone has the same usage needs and threat models. We all want to push riseup more in the direction of a security context, where bad choices are eliminated, which is why we all want to require message encryption, although we differ on how fast that should be pushed (I would like immediately). But, I feel it is much too far to say that carbons and MAM always represent a bad choice, particularly if we enforce message encryption.


I found this article about omemo MUCs useful: https://current.workingdirectory.net/posts/2017/encrypted-mucs/
Trying it worked well for me (and two other persons). Please include the link in the doc.