From 2e284c5e5ad02a70035a9f44269fa92d7187279b Mon Sep 17 00:00:00 2001 From: Sola Date: Mon, 23 Feb 2026 16:50:13 +0800 Subject: [PATCH] Fix biometric authentication in sandboxed environments (Flatpak, Snap, etc.) (#18625) Biometric authentication was failing in Flatpak with the error "Unix process subject does not have uid set". This occurred because polkit could not validate the sandboxed PID against the host PID namespace. Use polkit's system-bus-name subject type instead of unix-process. This allows polkit to query D-Bus for the connection owner's host PID and credentials, bypassing the PID namespace issue. Includes fallback to unix-process for edge cases where D-Bus unique name is unavailable. --- .../desktop_native/core/src/biometric/unix.rs | 27 ++++++++++++++++++- .../core/src/biometric_v2/linux.rs | 27 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/apps/desktop/desktop_native/core/src/biometric/unix.rs b/apps/desktop/desktop_native/core/src/biometric/unix.rs index 3f4f10a1fcf..f120408a9e5 100644 --- a/apps/desktop/desktop_native/core/src/biometric/unix.rs +++ b/apps/desktop/desktop_native/core/src/biometric/unix.rs @@ -21,7 +21,32 @@ impl super::BiometricTrait for Biometric { async fn prompt(_hwnd: Vec, _message: String) -> Result { let connection = Connection::system().await?; let proxy = AuthorityProxy::new(&connection).await?; - let subject = Subject::new_for_owner(std::process::id(), None, None)?; + + // Use system-bus-name instead of unix-process to avoid PID namespace issues in + // sandboxed environments (e.g., Flatpak). When using unix-process with a PID from + // inside the sandbox, polkit cannot validate it against the host PID namespace. + // + // By using system-bus-name, polkit queries D-Bus for the connection's credentials, + // which includes the correct host PID and UID, avoiding namespace mismatches. + // + // If D-Bus unique name is not available, fall back to the traditional unix-process + // approach for compatibility with non-sandboxed environments. + let subject = if let Some(bus_name) = connection.unique_name() { + use zbus::zvariant::{OwnedValue, Str}; + let mut subject_details = std::collections::HashMap::new(); + subject_details.insert( + "name".to_string(), + OwnedValue::from(Str::from(bus_name.as_str())), + ); + Subject { + subject_kind: "system-bus-name".to_string(), + subject_details, + } + } else { + // Fallback: use unix-process with PID (may not work in sandboxed environments) + Subject::new_for_owner(std::process::id(), None, None)? + }; + let details = std::collections::HashMap::new(); let result = proxy .check_authorization( diff --git a/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs b/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs index ef6527e7b26..2656bd3fdf9 100644 --- a/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs +++ b/apps/desktop/desktop_native/core/src/biometric_v2/linux.rs @@ -96,7 +96,32 @@ async fn polkit_authenticate_bitwarden_policy() -> Result { let connection = Connection::system().await?; let proxy = AuthorityProxy::new(&connection).await?; - let subject = Subject::new_for_owner(std::process::id(), None, None)?; + + // Use system-bus-name instead of unix-process to avoid PID namespace issues in + // sandboxed environments (e.g., Flatpak). When using unix-process with a PID from + // inside the sandbox, polkit cannot validate it against the host PID namespace. + // + // By using system-bus-name, polkit queries D-Bus for the connection's credentials, + // which includes the correct host PID and UID, avoiding namespace mismatches. + // + // If D-Bus unique name is not available, fall back to the traditional unix-process + // approach for compatibility with non-sandboxed environments. + let subject = if let Some(bus_name) = connection.unique_name() { + use zbus::zvariant::{OwnedValue, Str}; + let mut subject_details = std::collections::HashMap::new(); + subject_details.insert( + "name".to_string(), + OwnedValue::from(Str::from(bus_name.as_str())), + ); + Subject { + subject_kind: "system-bus-name".to_string(), + subject_details, + } + } else { + // Fallback: use unix-process with PID (may not work in sandboxed environments) + Subject::new_for_owner(std::process::id(), None, None)? + }; + let details = std::collections::HashMap::new(); let authorization_result = proxy .check_authorization(