use crate::common::*; #[test] fn whitelist_hides_home_contents() { let output = sandbox(&["--whitelist"]) .args(["--", "bash", "-c", "ls ~/Documents 2>&1 || echo hidden"]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("hidden"), "expected ~/Documents to be hidden, got: {stdout}" ); } #[test] fn whitelist_sys_is_readable() { let output = sandbox(&["--whitelist"]) .args(["--", "bash", "-c", "cat /sys/class/net/lo/address"]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); assert_eq!( stdout, "00:00:00:00:00:00", "expected loopback address from /sys, got: {stdout}" ); } #[test] fn blacklist_run_is_tmpfs() { let output = sandbox(&[]) .args([ "--", "bash", "-c", "touch /run/test_canary 2>&1 && echo WRITABLE || echo BLOCKED", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("WRITABLE"), "expected /run to be a writable tmpfs in blacklist mode, got: {stdout}" ); } #[test] fn blacklist_run_dbus_socket_accessible() { let output = sandbox(&[]) .args([ "--", "bash", "-c", "test -e /run/dbus/system_bus_socket && echo EXISTS || echo MISSING", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); assert_eq!( stdout, "EXISTS", "expected /run/dbus/system_bus_socket to be accessible in blacklist mode" ); } #[test] fn blacklist_runuser_is_tmpfs() { 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]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); assert!( stdout.is_empty(), "expected only 'bus' (or empty) in {}, got unexpected entries: {stdout}", run_user ); } #[test] fn blacklist_dev_input_hidden() { let output = sandbox(&[]) .args(["--", "bash", "-c", "ls /dev/input/ 2>/dev/null | wc -l"]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout).trim().to_string(); assert_eq!( stdout, "0", "expected /dev/input/ to be empty in blacklist mode, got {stdout} entries" ); } #[test] fn blacklist_root_is_readonly() { let output = sandbox(&[]) .args([ "--", "bash", "-c", "touch /rootfile 2>&1 && echo WRITABLE || echo READONLY; \ mkdir /newdir 2>&1 && echo MKDIR_OK || echo MKDIR_FAIL", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("READONLY"), "expected root to be read-only in blacklist mode, got: {stdout}" ); assert!( stdout.contains("MKDIR_FAIL"), "expected mkdir at root to fail in blacklist mode, got: {stdout}" ); } #[test] fn whitelist_root_is_readonly() { let output = sandbox(&["--whitelist"]) .args([ "--", "bash", "-c", "touch /rootfile 2>&1 && echo WRITABLE || echo READONLY; \ mkdir /newdir 2>&1 && echo MKDIR_OK || echo MKDIR_FAIL", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("READONLY"), "expected root to be read-only in whitelist mode, got: {stdout}" ); assert!( stdout.contains("MKDIR_FAIL"), "expected mkdir at root to fail in whitelist mode, got: {stdout}" ); } #[test] fn whitelist_mountpoint_parents_are_readonly() { let output = sandbox(&["--whitelist"]) .args([ "--", "bash", "-c", "echo pwned > /home/testfile 2>&1 && echo HOME_WRITABLE || echo HOME_READONLY; \ touch /etc/newfile 2>&1 && echo ETC_WRITABLE || echo ETC_READONLY; \ touch /var/newfile 2>&1 && echo VAR_WRITABLE || echo VAR_READONLY", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("HOME_READONLY"), "expected /home to be read-only in whitelist mode, got: {stdout}" ); assert!( stdout.contains("ETC_READONLY"), "expected /etc to be read-only in whitelist mode, got: {stdout}" ); assert!( stdout.contains("VAR_READONLY"), "expected /var to be read-only in whitelist mode, got: {stdout}" ); } #[test] fn whitelist_tmp_still_writable() { let output = sandbox(&["--whitelist"]) .args([ "--", "bash", "-c", "touch /tmp/ok 2>&1 && echo TMP_WRITABLE || echo TMP_READONLY; \ touch /var/tmp/ok 2>&1 && echo VARTMP_WRITABLE || echo VARTMP_READONLY", ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("TMP_WRITABLE"), "expected /tmp to remain writable in whitelist mode, got: {stdout}" ); assert!( stdout.contains("VARTMP_WRITABLE"), "expected /var/tmp to remain writable in whitelist mode, got: {stdout}" ); }