From 8d302851607222363f3e2f7427474d40fb21e9b4 Mon Sep 17 00:00:00 2001 From: Mathijs van Veluw Date: Sat, 1 Nov 2025 22:20:38 +0100 Subject: [PATCH] Fix issue with key-rotation and emergency-access (#6421) When a user has an unconfirmed emergency-access user, and tries to do a key-rotation, the validation fails. The reason is that Bitwarden only returns new keys for confirmed users, not for invited or accepted. This commit fixes this by only requesting confirmed or higher status emergency-access users. Signed-off-by: BlackDex --- src/api/core/accounts.rs | 2 +- src/db/models/emergency_access.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/api/core/accounts.rs b/src/api/core/accounts.rs index 5699b20e..ad3cb48b 100644 --- a/src/api/core/accounts.rs +++ b/src/api/core/accounts.rs @@ -780,7 +780,7 @@ async fn post_rotatekey(data: Json, headers: Headers, conn: DbConn, nt: let mut existing_ciphers = Cipher::find_owned_by_user(user_id, &conn).await; let mut existing_folders = Folder::find_by_user(user_id, &conn).await; - let mut existing_emergency_access = EmergencyAccess::find_all_by_grantor_uuid(user_id, &conn).await; + let mut existing_emergency_access = EmergencyAccess::find_all_confirmed_by_grantor_uuid(user_id, &conn).await; let mut existing_memberships = Membership::find_by_user(user_id, &conn).await; // We only rotate the reset password key if it is set. existing_memberships.retain(|m| m.reset_password_key.is_some()); diff --git a/src/db/models/emergency_access.rs b/src/db/models/emergency_access.rs index aa1eed7c..cf7f5385 100644 --- a/src/db/models/emergency_access.rs +++ b/src/db/models/emergency_access.rs @@ -340,6 +340,16 @@ impl EmergencyAccess { }} } + pub async fn find_all_confirmed_by_grantor_uuid(grantor_uuid: &UserId, conn: &DbConn) -> Vec { + db_run! { conn: { + emergency_access::table + .filter(emergency_access::grantor_uuid.eq(grantor_uuid)) + .filter(emergency_access::status.ge(EmergencyAccessStatus::Confirmed as i32)) + .load::(conn) + .expect("Error loading emergency_access") + }} + } + pub async fn accept_invite(&mut self, grantee_uuid: &UserId, grantee_email: &str, conn: &DbConn) -> EmptyResult { if self.email.is_none() || self.email.as_ref().unwrap() != grantee_email { err!("User email does not match invite.");