A talk by Midhun Suresh R and Kieran Lane at The Matrix Conference 2026.
Defence and government organisations need to share classified information quickly, with their own people and with allies, without it ever reaching someone who isn't cleared to see it. Speaking at The Matrix Conference, Midhun Suresh R. and Kieran Lane showed how the Mission Partner Environment (MPE) add-on for Element Server Suite Pro (ESS Pro) makes that possible.
Naming a room "top secret chat" doesn't keep classified information from unwanted eyes. ESS Pro supports NATO's labelling standard, STANAG 4774, so it fits into the infrastructure defence organisations already run. It also enforces clearance on the server: only people cleared for a message can read it.
The team built it across three components: Element Pro lets people label rooms and messages, Synapse Pro checks every join and message against the reader's clearance, and Advanced Identity and Access Management functionality removes anyone whose clearance no longer fits the room.
We reused NATO's labelling format
Because Matrix is an open standard,, it can adopt the formats defence organisations already use instead of forcing them to switch. Kieran, a senior technical engineer at Element, explained that NATO already has a label format, made of three layers:
- The rulebook, an XML file called a SPIF (Security Policy Information File), that defines which labels are allowed
- The label itself, defined in STANAG 4774 (Confidentiality Metadata Label Syntax) and written in either XML or JSON
- The binding, defined in STANAG 4778 (Metadata Binding Mechanism), which describes how a label attaches to data, with a profile for each protocol. The NATO standards have no binding for Matrix events, so this is where a Matrix spec proposal comes in
A SPIF defines the classifications and their order (top secret above secret, and so on). It also defines category tags, of which there are three kinds:
- Permissive tags, such as "releasable to Five Eyes", widen access. A reader needs at least one of them.
- Restrictive tags, such as "intelligence", narrow access. A reader must hold every one.
- Informative tags, such as "budget", are for handling only and don't affect access.
The SPIF can also define how each value appears as a marking in clients, including colours and human-readable, translatable names. Organisations already have SPIFs, so there's no new policy language to learn.
Kieran then showed how one message label plays out for two readers: John Smith, who has secret clearance and is German, and Jane, who has top secret clearance, is American and is cleared for intelligence.
Every room and every message carries its own label
Labels work at two levels. A room has a maximum label, the highest label its messages can carry, and every message has a label of its own. NATO's standard lets labels be written in XML or JSON, the format Matrix already uses for state and timeline events.
A room is currently labelled with a state event io.element.security_labels which will hopefully become m.security_labels after our work makes it to the Matrix Specification. It contains:
- a link to the SPIF file (an MXC URI, that is an internal link to the file, pointing to the file on the homeserver), plus its SHA-256 hash, so any tampering with the SPIF can be detected
- the maximum label, which also sets the clearance anyone needs to join
- the default label, which new messages get unless the sender picks another
Here's the state event for a room whose maximum is Kieran's example label:
{
"type": "m.security_labels",
"state_key": "",
"content": {
"spif": "mxc://example.org/spif-gbr",
"spif_hashes": {"sha256": "vOSRYkr4…"},
"max_labels": {
"pol": "GBR",
"cls": "SECRET",
"catl": [
{"type": "P", "name": "Releasable To", "vals": ["FVEY"]},
{"type": "R", "name": "Designators", "vals": ["INT"]},
{"type": "I", "name": "Admin Marking", "vals": ["BUDGET"]}
]
},
"default_labels": {
"pol": "GBR",
"cls": "SECRET",
"catl": [
{"type": "P", "name": "Releasable To", "vals": ["FVEY"]},
{"type": "R", "name": "Designators", "vals": ["INT"]},
{"type": "I", "name": "Admin Marking", "vals": ["BUDGET"]}
]
}
}
}
Whenever someone sends a message, the event that carries it holds both the encrypted message and its label in clear text, along with a reference to the SPIF and its hash. That lets homeservers check clearance without being able to read the message.
Here's a labelled message, shown unencrypted for readability:
{
"type": "m.room.message",
"content": {
"msgtype": "m.text",
"body": "hello",
"m.security_labels": [{
"label": {
"pol": "GBR",
"cls": "SECRET",
"catl": [
{"type": "P", "name": "Releasable To", "vals": ["FVEY"]},
{"type": "R", "name": "Designators", "vals": ["INT"]},
{"type": "I", "name": "Admin Marking", "vals": ["BUDGET"]}
]
},
"spif": "mxc://example.org/spif-gbr",
"spif_hashes": {"sha256": "vOSRYkr4…"}
}]
}
}
Leaving the label in clear text raises the obvious worry that someone could change or strip it in transit. In encrypted rooms, a hash of the label also goes inside the ciphertext, and recipients compare the two. This allows the recipient to detect malicious attempts to change the clearance requirements.
Once decrypted, the message carries that hash alongside its content:
{
"type": "m.room.message",
"content": {
"msgtype": "m.text",
"body": "hello",
"m.security_labels_hashes": [
{"sha256": "Hq2Lw7Xe…"}
]
}
}The maximum label also limits what messages can carry: every message must be readable by everyone in the room. Since everyone in the room is cleared for the maximum, a message can always use that label. A message can also leave out a restrictive tag like "intelligence", because that only widens the audience. But it can't leave out a permissive tag like "releasable to Five Eyes": that tag is what lets the room's Five Eyes members in, so without it they'd be locked out.
Extending Element Pro
The team extended the user interface to allow users to:
- upload a SPIF and set a room's maximum and default labels in its security settings
- see the room's maximum classification in its header
- pick a label for each message from the composer, choosing just the classification or, if enabled, individual tags too
- see each message's label in the timeline
The code follows our web team's MVVM (model-view-viewmodel) style: views hold no logic or state, and a store holds the classification logic. That covers downloading and parsing the SPIF, verifying the hashes on the SPIF and on message labels, and building event content.
The team added a fair amount to the module API along the way. That included custom settings (Element Web's settings were all defined statically, so modules couldn't add their own at runtime), more places for modules to render UI, and message content transformation. The label is attached after encryption, while its hash is added before.
Enforcement happens on the server
Access control splits into two roles. A policy enforcement point (PEP) asks for a decision and enforces it. A policy decision point (PDP) knows the policy and the users and makes the decision.
The implementation has two PEPs:
- Server-side modules act preventively, checking room joins and message sends.
- Advanced Identity & Access Management keeps a bot in each room and acts correctively, checking that every member still holds the required clearance and removing anyone who doesn't.
For the demo, the PDP was OpenTDF, an open-source platform for attribute-based access control. Whenever Synapse or the bot needs a decision, it sends OpenTDF the label and the person in question. OpenTDF looks up the persons’ clearance in the organisation's identity system, and answers yes or no. Kieran stressed that OpenTDF is one example: other PDPs could be used - for instance, Element partners with both Virtru and Cord3.
When servers federate, each one checks only its own users. A server can't verify the clearance of someone on another server, so it trusts that server to have done the checking. Kieran suggested federated identity providers such as Ping Federate could one day let a homeserver's PDP make decisions about remote users too.
Next: from one organisation to a whole coalition
Element built security labels because the organisations that need them already work with us, and because Matrix gives them something few messaging platforms do. It's an open standard they can run on their own infrastructure, extend to fit their policies, and never be locked into. That control matters most when the data is classified.
The talk showed labels within one organisation. In coalition operations, several nations share information, each under its own policy and often in different apps. This is what's known as a Mission Partner Environment: shared infrastructure that lets allied forces and their partners exchange classified information across national boundaries.
With Matrix, each nation runs its own deployment and connects to the others through federation, so no single country controls the network. Several next steps would help extend labels further across a coalition:
- Label equivalents. Part of the NATO standards, they map one organisation's labels to another's, so partners with different policies can share labelled messages.
- Decisions about remote users. With federated identity providers such as Ping Federate, a homeserver could check a remote user's clearance itself instead of trusting their server to do it.
- Revocable access to data. "Level 3" data-centric security double-wraps messages and files, so access can be revoked independently of Matrix. This is already being worked on, including a ZTDF approach for files.