From c72617202e7558f54b4a3c3de8313be560c084e8 Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Thu, 23 Apr 2026 08:11:43 -0400 Subject: [PATCH 1/2] daemon: Improve logging of trusted caller checks --- credentialsd/src/gateway/dbus.rs | 5 ++++- credentialsd/src/gateway/mod.rs | 10 +++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/credentialsd/src/gateway/dbus.rs b/credentialsd/src/gateway/dbus.rs index 94f9846..92a9a37 100644 --- a/credentialsd/src/gateway/dbus.rs +++ b/credentialsd/src/gateway/dbus.rs @@ -484,7 +484,10 @@ async fn validate_app_details( }; if claimed_app_id.is_empty() || !super::should_trust_app_id(pid).await { - tracing::warn!("App ID could not be determined. Rejecting request."); + tracing::warn!( + ?claimed_app_id, + "App ID could not be verified. Rejecting request." + ); return Err(Error::SecurityError); } // Now we can trust these app detail parameters. diff --git a/credentialsd/src/gateway/mod.rs b/credentialsd/src/gateway/mod.rs index d982909..5154f14 100644 --- a/credentialsd/src/gateway/mod.rs +++ b/credentialsd/src/gateway/mod.rs @@ -290,12 +290,14 @@ async fn should_trust_app_id(pid: u32) -> bool { } let Ok(exe_path) = tokio::fs::read_link(format!("/proc/{pid}/exe")).await else { + tracing::warn!("Cannot read executable name from procfs"); return false; }; // The target binaries are hard-coded to valid UTF-8, so it's acceptable to // lose some data here. let Some(exe_path) = exe_path.to_str() else { + tracing::warn!("Could not read executable path from procfs"); return false; }; tracing::debug!(?exe_path, %pid, "Found executable path:"); @@ -305,7 +307,13 @@ async fn should_trust_app_id(pid: u32) -> bool { } else { vec!["/usr/bin/xdg-desktop-portal".to_string()] }; - trusted_callers.as_slice().contains(&exe_path.to_string()) + tracing::debug!(?trusted_callers, %exe_path, "Testing whether request is from trusted caller"); + if !trusted_callers.as_slice().contains(&exe_path.to_string()) { + tracing::warn!(%exe_path, "Request received from untrusted caller"); + return false; + } else { + return true; + } } fn check_origin_from_app( From 1365e84757fc1cf3e013ae3997ac33550f8128e5 Mon Sep 17 00:00:00 2001 From: Isaiah Inuwa Date: Tue, 5 May 2026 14:57:20 -0500 Subject: [PATCH 2/2] daemon: Canonicalize paths for trusted callers before comparing --- credentialsd/src/gateway/mod.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/credentialsd/src/gateway/mod.rs b/credentialsd/src/gateway/mod.rs index 5154f14..ce1b64a 100644 --- a/credentialsd/src/gateway/mod.rs +++ b/credentialsd/src/gateway/mod.rs @@ -4,7 +4,10 @@ mod dbus; mod util; -use std::sync::Arc; +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; use credentialsd_common::{ model::{GetClientCapabilitiesResponse, RequestingApplication, WebAuthnError}, @@ -294,22 +297,23 @@ async fn should_trust_app_id(pid: u32) -> bool { return false; }; - // The target binaries are hard-coded to valid UTF-8, so it's acceptable to - // lose some data here. - let Some(exe_path) = exe_path.to_str() else { - tracing::warn!("Could not read executable path from procfs"); - return false; - }; tracing::debug!(?exe_path, %pid, "Found executable path:"); - let trusted_callers: Vec = if cfg!(debug_assertions) { + let trusted_callers: Vec = if cfg!(debug_assertions) { let trusted_callers_env = std::env::var("CREDSD_TRUSTED_CALLERS").unwrap_or_default(); - trusted_callers_env.split(',').map(String::from).collect() + trusted_callers_env + .split(',') + .filter_map(|path| Path::new(path).canonicalize().ok()) + .collect() } else { - vec!["/usr/bin/xdg-desktop-portal".to_string()] + vec![PathBuf::from("/usr/bin/xdg-desktop-portal")] }; - tracing::debug!(?trusted_callers, %exe_path, "Testing whether request is from trusted caller"); - if !trusted_callers.as_slice().contains(&exe_path.to_string()) { - tracing::warn!(%exe_path, "Request received from untrusted caller"); + tracing::debug!( + ?trusted_callers, + ?exe_path, + "Testing whether request is from trusted caller" + ); + if !trusted_callers.as_slice().contains(&exe_path) { + tracing::warn!(?exe_path, "Request received from untrusted caller"); return false; } else { return true;