Legal hold
Author: Tiago Loureiro
Legal hold introduces a new type of device, named legal hold device, for the sake of satisfying corporate compliance rules without sacrificing end to end encryption with full transparency.
A legal hold device is a device bound to a team user account but managed outside of the user’s control - this is managed by the Legal hold service. The management/operation of said Legal hold service is of the responsibility of the team.
This Backend service makes this type of device available for clients that are visually distinguishable, for full transparency, with a clear, constant indication on the UI. There can be only one such device per user account and they can only be added to the user’s device list with the user’s consent and confirmed with a password prompt (if they have one - there can be exceptions such as SSO users).
A team admin may ask members of the team to be put under legal hold. Once a person is prompted, they should then verify that the presented signature matches the one generated by the legalhold service to avoid any potential MITM attack.
Conceptually, there are the following actors in this use case:
A team admin - someone who requests legal hold for a specific user
A team member - the user who will be put under legal hold
Backend - serves as intermediary between team members/admin and the Legal hold Service
Legal hold service - stores users’ Legal hold devices on customers’ premises
Legal hold device - a user’s device that is managed by customers
Once a user accepts the legal hold request, then a device is added to that user’s account. This device, also known as legal hold device, is managed by the Legal hold service - only team admins can remove that device from a user’s account.
Note that every user talking to someone under legal hold (including, of course, the self user) is made aware by means of displaying a red dot on the user’s profile.
API and flows
Legal hold flow (client perspective)
Request (by admin) for a user to be put under legalhold
POST /teams/{tid}/legalhold/{uid}
201 Created
Approval by the user
PUT /teams/{tid}/legalhold/{uid}/approve
{
"password": <user's password> # optional if the user has no set password
}
200 OK
Deletion by an admin
DELETE /teams/{tid}/legalhold/{uid}
{
"password": <admin's password> # optional if the admin has no set password
}
200 OK
Get Legal hold status for team members
GET /team/{tid}/members
200 OK
...
{
"members": [{
"user": member used id,
...
"legalhold_status": "disabled" | "enabled", <-- new field
...
}
}
Admin Panel -> Backend: Activate LH for Alice
Backend -> LegalHold Service: Request to create Cryptobox for Alice (does NOT include scoped token)
LegalHold Service –> Backend: Respond with Public Key etc. for Device
Backend -> Admin Panel: LH for Alice is PENDING Backend –> Alice’s Client: (Async) Request Approval for LH (includes device fingerprint)
Alice’s Client -> Backend: Alice APPROVES LH
Backend -> LegalHold Service: Send scoped access_token Backend -> Backend: Add Compliance Device to Alice Backend -> Admin Panel: LH for Alice is ACTIVE
=: Deactivation
Admin Panel -> Backend: Deactivate LH for Alice Backend -> Backend: Remove Compliance Device from Alice; revoke access token.
Events
New legalhold request event:
{ "type": "user.legalhold-request"
, "id": UserID of the one for whom LH is being requested
, "last_prekey": Last-prekey of the legal hold device
, "client": {"id": Client ID of the legalhold device}
}
New legalhold enabled event:
{ "type": "user.legalhold-enable"
, "id": UserID for whom LH was enabled
}
New legalhold disabled event:
{ "type": "user.legalhold-disable"
, "id": UserID for whom LH was disabled
}
These events are sent to the user, all team members (including admins) and connections.
Whitelisting and implicit consent
This release introduces a notion of intial “consent” to legalhold (LH): In addition to the popup before getting exposed to LH devices (either by getting assigned one or by entering a conversation or connection with one present), users needs to grant their consent to even have the option of being exposed. Until they do, they may be blocked from using wire by their team admin (if they are a team user), but they cannot be assigned a LH device, and they cannot enter conversations with LH devices present.
For now, there isn’t any UI for the user to grant their initial consent. Instead, an “implict consent” can be given by the site operator by setting
featureFlags:
# [...]
legalhold: whitelist-teams-and-implicit-consent
in galley’s config and then using non-exposed, internal endpoints on the galley pod to update the set of teams whose users are considered to have given their initial consent:
put /i/legalhold/whitelisted-teams/:team-id
- Add teamdelete /i/legalhold/whitelisted-teams/:team-id
- Remove teamget /i/legalhold/whitelisted-teams
- List all teams
Since consent is required for LH to work, users in teams that are not whitelisted cannot be assigned LH devices (pull request #1502), and they are blocked or removed from conversations that are exposed to LH devices (#1507, #1595).
Implementation status and future work
The notion of consent is introduced to make it explicit, ie. users would have UI components to grant consent themselves, and there would be clear feedback in situations where communication is blocked for lack of consent, so that these situations can be resolved offline.
Whitelisting and implicit consent is a short cut. The server side already implements granting explicit consent, but until the UI is ready, site operators have the option of allowing LH to function on a fixed set of teams.