Blocking

In the Fediverse, when you block someone, your server sends a message to their server. This is counter-intuitive, potentially dangerous, and generally kinda odd. Here I just want to record what happens and why.

Warning

When you block someone on Mastodon, it pops up an “are you sure” including, among other warnings, “They can see that they’re blocked”.

Dialog box titled "Block user?"  There are four warnings shown: "they can see that they're blocked", "they can't see your posts and you won't see theirs", "you won't see posts that mention them", and "they can't mention or follow you".

This is not really accurate. Better would be “they may be able to see that they’re blocked”. But what determines whether they can see it, and how does it look when they can see it?

SQL

The short answer is, admins can see who is blocked, by performing a SQL query directly on the database. On Mastodon, it looks like this:

mastodon_production=# select blocked.username as blocked_user, blocker.url as blocking_user from accounts as blocker join blocks on blocks.account_id = blocker.id join accounts as blocked on blocks.target_account_id = blocked.id;
 blocked_user |               blocking_user
--------------+--------------------------------------------
 pizzazz      | https://friends.holograms.test/profile/jem
(1 row)

On Friendica, it looks like this:

MariaDB [friendica]> select username as blocked_user, url as blocking_user from contact join `user-contact` on contact.id = `user-contact`.cid join user on `user-contact`.uid = user.uid where `is-blocked` = 1;
+--------------+--------------------------------------------+
| blocked_user | blocking_user                              |
+--------------+--------------------------------------------+
| Pizzazz      | https://friends.holograms.test/profile/jem |
+--------------+--------------------------------------------+
1 row in set (0.001 sec)

Clearly, this requires some degree of technical sophistication. But then again, given the background of most Fediverse participants, not really a very high degree. Especially if irresponsible blogs go around publishing the necessary queries for everyone to find.

The Problem

When a user like Jem blocks an abusive account like Pizzazz, what she’s trying to do is escape harrassment from some anonymous troll that for some reason has conceived a sick grudge against her. Jem doesn’t have time to invest in this, whereas Pizzazz is quite likely willing to invest 100% of her free time trying to get to Jem. This is the pattern that makes social media so toxic.

When someone like Pizzazz discovers that she’s blocked, she will not just give up and fade away. At first she will create a new account somewhere and try again. Once she’s burned through several accounts, she’ll start to get more creative. Blocking Pizzazz is just going to escalate the attack.

Pizzazz, the one with the free time, may well be the admin of her server. She might run a single-user instance, or she might be a leader of a clique who uses trolling as a demonstration of prestige. Alternatively, Pizzazz might have her account on a server where she is close friends with the admin, able to ask them to run the query on her behalf.

Messages

So from Jem’s point of view, the block is a contract only between her and her own server (friends.holograms.test). She wants her server to silently drop all interaction with Pizzazz, but otherwise do as little as possible to trigger Pizzazz to escalate.

But that’s not what Jem is getting, and if she reads the popup carefully she will realise that Pizzazz, on her server friends.misfits.test, can directly learn about the block. But that leads to the question, how does friends.misfits.test even know about the block in the first place?

The answer is simply that friends.holograms.test sends a message to friends.misfits.test. Here’s how the message looks when sent by Mastodon. (Friendica sends a much more flambloyant, but functionally equivalent message. It’s 47 lines long so I won’t reproduce it here.)

{
  "@context": "https://www.w3.org/ns/activitystreams",
  "id": "https://friends.holograms.test/00de45d0-ef48-433f-826f-99b475b48f9f",
  "type": "Block",
  "actor": "https://friends.holograms.test/users/jem",
  "object": "https://friends.misfits.test/profile/pizzazz"
}

The block is then recorded in friends.misfits.test database, ready for Pizzazz or her tame admin to retrieve with SQL. More than that though: friends.misfits.test need not be Mastodon, it could be alternative Fediverse software that directly alerts Pizzazz the instant someone blocks her. I don’t know of any software that does this, but it’s a pretty simple mod. Such a notification is even more likely to trigger retaliation from Pizzazz.

Spec

So this is pretty messed up. Why was ActivityPub designed this way?

The answer is, it wasn’t. The spec lists all the activities that a compatible implementation should support. Here’s the section for the Block activity, neatly listed under “Client to Server Interactions”.

Back up a bit. ActivityPub actually consists of two protocols, usually abbreviated S2S for “server to server” and C2S for “client to server”. When messages are passed between servers, e.g. between friends.holograms.test and friends.misfits.test, that’s S2S. C2S is supposed to be used by the app on Jem’s phone to talk to friends.holograms.test. I say “supposed to”, because there are almost no implementations of C2S in the wild. Real apps use the Mastodon protocol instead.

Although many activities are listed under both sections of the spec (Create, Follow, Like), Block is firmly only for use by apps, and those apps don’t even exist. If such an app did exist, it would work exactly as Jem would wish: Jem uses her phone to tell her own server to block Pizzazz, and that’s the end of the story. Jem’s server has no business at all passing that message to Pizzazz’s server, that’s not in the spec.

Note that the spec states:

Servers SHOULD NOT deliver Block Activities to their object.

The “object” here, as shown in the JSON snippet above, is Pizzazz. The spec authors were well aware of the potential for retaliation. Here they are considering the case where the actor and the object are both on the same server. For example, Roxy is also on friends.misfits.test and blocks Pizzazz. The server could, but should not, deliver that message over C2S to Pizzazz. A naïve developer might notice that this is possible and wonder if that message should actually be sent, so the spec carefully tells that developer not to do that.

The spec does not address how the server should behave for Block activities relayed from other servers over S2S, because that’s not ever supposed to happen.

Shared Inbox

So we’ve identified the problem! Mastodon is being evil. And Friendica too. And probably a bunch of other implementations I didn’t bother testing.

Unfortunately, there is a good reason why those developers implemented it this way. It has to do with the “shared inbox” feature.

Mastodon in particular is optimised for sites hosting thousands of users. Assume Jem is a famous woman and has hundreds of thousands of followers. That probably includes hundreds of followers just on friends.misfits.test. Whenever she tweets, that message has to be relayed to all those hundreds of thousands of followers. If they were all addressed individually, that would mean hundreds of thousands of messages. If she’s having a rapid conversation, that could easily overwhelm her server.

But it’s particularly absurd that she has to send the same message hundreds of times over just to friends.misfits.test. Much more efficient is to send the message once, and let friends.misfits.test choose which users to show it to. So ActivityPub defines a “shared inbox” feature, which allows exactly this optimisation.

But then suppose that both Pizzazz and Roxy on friends.misfits.test are among those followers. Pizzazz has been blocked, but Roxy has not. How can friends.misfits.test know that it has to show the message to one but not the other?

That’s exactly what the Block message is for. It’s there to ensure that blocking works mostly as Jem would expect. Jem expects that when she blocks Pizzazz, Pizzazz no longer sees Jem’s messages, but since Roxy has not been blocked, Roxy does see those messages.

For this to work, Jem’s server has to trust that Pizzazz’s server will accept the message and “do the right thing”. And mostly, that’s exactly what servers do. Mostly.

Compromise

So we have two entirely understandable expectations from Jem, that really ought to be respected, but which contradict each other at the implementation.

Christine Lemmer-Webber, the principal author of the ActivityPub spec, has stated several times that she regrets the way shared inboxes were added to the spec at the last minute. Instead, she is working at the Spritely Institute on systems that are built on the capability model. This is probably the approach that would definitively solve this problem. But that would require using very much a different protocol to ActivityPub. Perhaps ActivityPub 2.0.

Today, despite limited adoption by ordinary users, we are still seeing an explosion of ActivityPub implementations. Most of these are hobby projects. Is it feasible that once a better protocol with stronger safety features becomes available, they will all rush to implement that? Hmm. Maybe some of them.

What’s happening is that developers are trying to take the ingredients they’ve been given and concoct a user experience that is compelling for actual users. These implementations have no choice but to balance the attractiveness of features (for example, Mastodon’s relatively good scaling) to the safety of their users. Compromise.

There’s not really much of a conclusion here. Things Are Not As They Ideally Would Be. Be careful out there.

Screenshot from the episode of Jem, Season 1 Episode 8, "Starbright Rising Star", music video "Welcome To The Jungle", showing a wild-eyed Pizzazz pouncing towards the camera.

Leave a Reply

Your email address will not be published. Required fields are marked *