-
Notifications
You must be signed in to change notification settings - Fork 397
[WIP] MSC4284: Policy Servers #4284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@@ -0,0 +1,188 @@ | |||
# MSC4284: Policy Servers |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Personally this MSC in its current state is proposing something that sounds like the reverse of a recent idea in Draupnir of extending the API as to allow the easy creation of external protections. But this MSC instead proposes an API for calling into a Evaluator over fed.
I personally think this sounds like a great idea as this approach allows the maintainence of the philosophy of letting homeservers focus on being homeservers and farms out moderation to dedicated tooling that is fit for purpose. This is great for not only extensibility but also maintainability of these capabilities.
Draupnir has recently started to venture into this direction a tiny bit via its HS Admin Capabilities and Synapse module. This shows theres definetively an appatite for this type of capabilitity in the ecosystem. I have also seen wishes for this exact type of MSC expressed recently.
The request body is *optional* but *strongly recommended* for efficient processing, as the policy | ||
server may not make efforts to locate the event over federation, especially during `/check`. | ||
|
||
Authentication is achieved using normal [Federation API request authentication](https://spec.matrix.org/v1.14/server-server-api/#request-authentication). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is routing to the server subject to the normal federation server name resolution stuff (https://spec.matrix.org/v1.14/server-server-api/#resolving-server-names) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would assume it makes sense to extend delegation in this MSC if we are using the normal server name stuff.
Since if the CS API can be separated it would make sense if this can also be separate but ofc using a separate subdomain always works as the MSC shows as an example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is routing to the server subject to the normal federation server name resolution stuff (https://spec.matrix.org/v1.14/server-server-api/#resolving-server-names) ?
Yes - it's intended that the server participates in the room, but may not implement the full suite of federation endpoints.
For Synapse homeservers, the above paragraph's consequences are natural behaviour of the spam checker | ||
module feature. A server could, with some performance penalty, deploy a module which calls the `/check` | ||
API to enact the consequences described above. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/element-hq/policyserv_spam_checker is an example of this, supported by https://matrix.org/blog/2025/04/introducing-policy-servers/
|
||
Provided `policy.example.org` is in the room, that server receives events as any other homeserver | ||
in the room would, *plus* becomes a Policy Server. If `policy.example.org` is not in the room, the | ||
assignment acts as though it was undefined: the room does not use a policy server. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe I'm missing something obvious, but why is the policy server required to be a Matrix server that is participating in the room?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This also appears to contradict the earlier statement: "This may be an existing logical server, such as matrix.org, or a dedicated host which serves no other purpose."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Johennes My understanding of that sentence is simply that the /check
endpoint may be implemented by an existing homeserver domain, or by a dedicated homeserver domain that doesn't provide any other Matrix functionality.
policy server ahead of sending their event(s). For example, `matrix.example.org` may have a user in | ||
the room with permission to send redactions and `/check`s all events. | ||
|
||
## Potential issues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd be worried about situations in which this MSC is in use in a room but not implemented in all HSs participating in that room, as the following could happen:
- all room moderators are on HSs that implement this MSC
- abuse content is sent to the room by abusive users
- moderators do not see these users or their content
- thus moderators don't redact the content and ban the users
- thus users on HSs that don't implement this MSC will still see the abuse content
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly this could be mitigated by having draupnir (or another moderation bot) also make requests to the policy server, and then redact events. You might see abuse content temporarily that way if your HS doesn't implement this MSC, but it may be better than nothing.
Important note about this is that the moderation bot would need to run on a server that does not soft-fail events based on the policy server, otherwise it wouldn't be able to see the events it needs to redact.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Important note about this is that the moderation bot would need to run on a server that does not soft-fail events based on the policy server, otherwise it wouldn't be able to see the events it needs to redact.
Perhaps there should be a way to opt-in to receiving soft-failed events as a client, so that moderation tools can still view and send redactions for abuse content and such. Such functionality would feel less hacky than making sure to run moderation tools on an HS that doesn't support this MSC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we're currently experimenting with having this done at the server level, via https://github.com/element-hq/policyserv_spam_checker for now
element-hq/synapse#18238 is another early example of experimentation in this area
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It kind of feels conceptually that each server should be able to redact events for their users only. This is in keeping with Matrix's server autonomy. Mod/admin servers can still redact which will still be broadcast to all other servers, but really whether this is applied is a per-server decision.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kegsay Such a design could also help prevent existing quirks, like DM conversation partners being able to unilaterally delete all conversation participants' messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Servers which use the policy server should be rejecting the events before they're sent to the room, instead of redacting them. A server could feasibly redact instead of send, but then it's just wasted events which may be further against room policy (flooding, "apparent malicious redaction", etc).
An alternative was considered where, in a future room version, all events must be signed by the policy | ||
server before they're able to be added to the DAG. However, this results in compulsory centralization | ||
and usage, removing the room's agency to choose which moderation tools they utilize and that room's | ||
ability to survive network partitions. This alternative does have an advantage of reducing bandwidth | ||
spend across the federation (as there's no point in sending a spammy event if the policy server won't | ||
sign it), but would require that communities upgrade their rooms to a compatible room version, which | ||
typically take significant time to specify and deploy. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can still be added as an optimization - servers MAY get a signature from the policy server before sending an event to the room, which would allow other servers to skip the policy server check when receiving the event.
This may be an existing logical server, such as matrix.org, or a dedicated host which serves no other | ||
purpose. | ||
|
||
Rooms which elect to use a policy server would do so via the new `m.room.policy` state |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bikeshedding: not a fan of m.room.policy
as a state event name, it's too generic. Maybe something like m.room.event_filtering
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The terminology also would otherwise conflict with the widely used "policy lists"
If a policy server is in use by the room, homeservers SHOULD call the `/check` API defined below on | ||
all locally-generated events before fanning them out and on all remote events before delivering them | ||
to local users. If the policy server recommends treating the event as spam, the event SHOULD be soft |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an escape hatch, should the homeserver accept events recognised as coming from a room admin without a policy check?
(Maybe even allow a room admin to set a threshold, so that a moderation bot can operate directly, while letting the admins to remove the bot with a normal kick)
An alternative was considered where, in a future room version, all events must be signed by the policy | ||
server before they're able to be added to the DAG. However, this results in compulsory centralization | ||
and usage, removing the room's agency to choose which moderation tools they utilize and that room's | ||
ability to survive network partitions. This alternative does have an advantage of reducing bandwidth |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a Certificate-Transparency-like option?
A room admin MAY set a list L of policy servers, a count N, and a power level threshold T. By default, count is N=0, list L is empty, PL threshold is T=100. An even can only be incorporated if it originates from a user with PL≥T, OR it has N signatures from policy servers in L.
This way room admins can choose whom to trust, while avoiding a SPOF; they can also do an emergency override if it becomes necessary.
This comment was marked as duplicate.
This comment was marked as duplicate.
``` | ||
|
||
The request body is *optional* but *strongly recommended* for efficient processing, as the policy | ||
server may not make efforts to locate the event over federation, especially during `/check`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add «If the body is provided, the policy server SHALL verify that the event is signed by the claimed originating server.» to make the answer to the concerns in #4284 explicit?
spend across the federation (as there's no point in sending a spammy event if the policy server won't | ||
sign it), but would require that communities upgrade their rooms to a compatible room version, which | ||
typically take significant time to specify and deploy. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We’d especially like to see implementations for non-Synapse servers
I would like to suggest Kubewarden's policy-server
. Kubewarden is a CNCF project implementing a policy engine for Kubernetes, and its policy-server
can run outside k8s and process any type of query (disclaimer, I'm a maintainer of the Kubewarden project).
The policy-server
runs small policies compiled to Wasm (written in Rust, Go, CEL, Rego, with our provided small SDKs). These policies are shipped as OCI wasm artifacts. The policy-server
implements a Wasm host with wapc-rs, receives a JSON request and accepts, rejects, or mutates the request depending on the outcome from the policies. The policy-server
also does context-aware calls to other services apart from the JSON request that is evaluating at that moment (in this specific case, that would be adding querying a Matrix client). Policy definitions allow for specifying granular permissions WRT those context-aware needs, ala smartphone apps.
Users of the policy-server can develop their own policies in their preferred languages, test them locally with our kwctl
CLI tool, and share and reuse them via OCI registries.
If interested, don't hesitate to have a look at our docs, ping me, or get in contact in our Slack channel.
This comment was marked as duplicate.
This comment was marked as duplicate.
policy server ahead of sending their event(s). For example, `matrix.example.org` may have a user in | ||
the room with permission to send redactions and `/check`s all events. | ||
|
||
## Potential issues |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if a malicious server claims that they received abusive content from a specific user (and forges events that seem to be originating from that user) in order to get a user banned globally? Is there anything protecting against such a scenario or is it something that should be considered by policy servers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following the attack vector here. The server cannot forge events to appear as coming from another server without getting those events rejected completely, making them out of scope of the policy server.
If a malicious policy server does decide to auto-fail all events from a specific sender though, it can do so. The room can also elect to not use that policy server anymore. Policy servers should be cognisant of the impact they have when making decisions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attack vector is: a malicious homeserver in the room asks the policy server about another homeserver's event, and includes the event content as an optimisation. The content is forged, however. The policy server only follows explicit SHALL and SHOULD of the spec, accepts the event content and does not properly check its authenticity. The policy server proceeds to give a signed response that the event should be redacted. The malicious homeserver posts the response to get other homeservers to throw out the event. The stretch goal is to have enough blocked events allegedely from the same user in a row that some other policy mechanism bans the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose the question is whether the policy server should be compelled to check hashes, or if it should be left as an implementation detail. I'm leaning towards implementation detail, as a room can change policy servers if needed, and it could be considered a security vulnerability in the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is annoying because it means that basic policy servers written as bots need to ask their own homeserver for each event (ie via GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}
) they get asked about. But i haven't read the whole proposal yet so my bad if i'm missing something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The remainder of the proposal addresses that concern.
|
||
**TODO**: This section. | ||
|
||
## Security considerations |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Servers should not send policy server state events through the policy server, or at least not act on them. Especially if the senders are the same.
This is to prevent a malicious policy server from not allowing the room to escape, but we should still have a mechanism to prevent compromised accounts from adding/setting malicious servers if we can.
Risk level of these 2 concerns is TBD.
Rendered
Disclosure: I am Director of Standards Development at The Matrix.org Foundation C.I.C., Matrix Spec Core Team (SCT) member, employed by Element, and operate the t2bot.io service. This proposal is written and published as a Trust & Safety team member allocated in full to the Foundation.