Skip to content

Rotate the team DEK on membership change (defense in depth, not offboarding) #217

Description

@kipavy

Split out of #72 so its rationale is recorded honestly rather than assumed.

Current behaviour

Removing a member deletes their row from team_vault_keys (server/src/routes/teams.rs:545-550) and revokes their session grants, and the client evicts the in-memory vault key (src/services/sync.ts:882-886). The team DEK itself is never rotated, and the team blob is never re-encrypted.

What rotation would and would not buy

It is tempting to treat rotation as the fix for offboarding. It isn't, because a departing member held the plaintext:

Exposure Protected today? Does rotation help?
Secrets they already read No — permanently compromised No. Only rotating the credentials themselves helps
Future team content Yes — membership row, wrapped key row and session grants all deleted server-side No, absent a server-authz bypass
Blob ciphertext they exfiltrated before leaving They held the DEK, so they can decrypt it No — a copy someone already holds cannot be retroactively re-encrypted
Plaintext left in their local keychain No — see #216 No

Rotation protects only blobs written after rotation, which a removed member can no longer fetch anyway.

The case for doing it anyway

Defense in depth on the ciphertext at rest. Today a single DEK covers the entire lifetime of a team, so any leak of the encrypted blob — a database backup, a stale replica, a misconfigured storage bucket — exposes everything the team has ever stored, including data added long after a member left. Rotating on membership change bounds that blast radius to one membership epoch.

That is a real property, and it is worth stating as the reason. It is not an answer to "what happens to a removed member's access", which is #72's question.

Rough shape

  • Generate a new team DEK, re-encrypt the team blob, re-wrap for every remaining member.
  • Handle partial rotation: some members re-wrapped, some not, and the blob in one state or the other. This needs to be atomic or resumable — a half-rotated team where some members cannot decrypt is worse than no rotation.
  • Handle offline members: someone who is not connected at rotation time must re-key on next connect without losing access in the meantime.
  • Decide the trigger: automatic on every removal, or an explicit admin action. Automatic is safer but makes every removal a heavyweight operation.
  • Decide what "rotate" does to older blob versions retained server-side, if any.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestteam-uxTeam & collaboration UX flows (sessions, vaults, invites, presence)

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions