From 99f9395c104ea6d95e6ab315c330e3355a9c02a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Krist=C3=B3f=20T=C3=B3th?= Date: Wed, 25 Mar 2026 23:54:35 +0100 Subject: [PATCH] Move require_run_user to lib.rs and make blacklist module private --- src/blacklist.rs | 16 +--------------- src/lib.rs | 21 ++++++++++++++++++++- tests/integration.rs | 7 +++---- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/blacklist.rs b/src/blacklist.rs index c3dad1b..fe93a92 100644 --- a/src/blacklist.rs +++ b/src/blacklist.rs @@ -42,10 +42,7 @@ pub fn resolve_overlays(ctx: &PathContext) -> Result Result { let home = crate::require_home()?; - let run_user = std::env::var("XDG_RUNTIME_DIR") - .ok() - .or_else(resolve_run_user_from_proc) - .ok_or(SandboxError::RunUserNotFound)?; + let run_user = crate::require_run_user()?; Ok(PathContext { home, run_user }) } @@ -88,17 +85,6 @@ fn is_under_tmpfs_dir(path: &Path, tmpfs_dirs: &[PathBuf]) -> bool { tmpfs_dirs.iter().any(|dir| path.starts_with(dir)) } -fn resolve_run_user_from_proc() -> Option { - let status = fs::read_to_string("/proc/self/status").ok()?; - for line in status.lines() { - if let Some(rest) = line.strip_prefix("Uid:") { - let uid = rest.split_whitespace().next()?; - return Some(format!("/run/user/{uid}")); - } - } - None -} - // --------------------------------------------------------------------------- // Curated sensitive paths from firejail disable-common.inc + disable-programs.inc. // Goal: protect secrets, credentials, and session tokens from agentic access. diff --git a/src/lib.rs b/src/lib.rs index c7e1dae..0d5cba1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ mod agents; -pub mod blacklist; +mod blacklist; mod errors; mod preflight; mod sandbox; @@ -8,6 +8,7 @@ pub use errors::SandboxError; use std::env; use std::ffi::OsString; +use std::fs; use std::os::unix::process::CommandExt; use std::path::PathBuf; @@ -35,6 +36,24 @@ pub fn require_home() -> Result { .ok_or(SandboxError::HomeNotSet) } +pub fn require_run_user() -> Result { + env::var("XDG_RUNTIME_DIR") + .ok() + .or_else(resolve_run_user_from_proc) + .ok_or(SandboxError::RunUserNotFound) +} + +fn resolve_run_user_from_proc() -> Option { + let status = fs::read_to_string("/proc/self/status").ok()?; + for line in status.lines() { + if let Some(rest) = line.strip_prefix("Uid:") { + let uid = rest.split_whitespace().next()?; + return Some(format!("/run/user/{uid}")); + } + } + None +} + pub fn run(config: SandboxConfig) -> Result<(), SandboxError> { preflight::check(&config)?; diff --git a/tests/integration.rs b/tests/integration.rs index 5719b14..5c5d122 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,7 +1,6 @@ use std::fs; use std::process::Command; -use agent_sandbox::blacklist; use tempfile::TempDir; fn sandbox(extra_args: &[&str]) -> Command { @@ -391,8 +390,8 @@ fn blacklist_run_dbus_socket_accessible() { #[test] fn blacklist_runuser_is_tmpfs() { - let ctx = blacklist::resolve_path_context().expect("failed to resolve path context"); - let script = format!("ls -A {} | grep -v '^bus$'", ctx.run_user); + let run_user = agent_sandbox::require_run_user().expect("failed to determine XDG_RUNTIME_DIR"); + let script = format!("ls -A {} | grep -v '^bus$'", run_user); let output = sandbox(&[]) .args(["--", "bash", "-c", &script]) @@ -403,7 +402,7 @@ fn blacklist_runuser_is_tmpfs() { assert!( stdout.is_empty(), "expected only 'bus' (or empty) in {}, got unexpected entries: {stdout}", - ctx.run_user + run_user ); }