use crate::common::*; const BWRAP_COMMAND_LINE_PATH: &str = "/run/agent-sandbox/bwrap-args"; #[test] fn whitelist_exposes_exact_bwrap_invocation() { assert_exposes_exact_invocation(&[]); } #[test] fn blacklist_exposes_exact_bwrap_invocation() { assert_exposes_exact_invocation(&["--blacklist"]); } fn assert_exposes_exact_invocation(mode_args: &[&str]) { let output = Sandbox::new(mode_args) .args(["--", "cat", BWRAP_COMMAND_LINE_PATH]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( output.status.success(), "reading {BWRAP_COMMAND_LINE_PATH} failed: {}", String::from_utf8_lossy(&output.stderr) ); let argv = shlex::split(stdout.trim()).expect("file content is not valid shell"); assert_eq!(argv[0], "bwrap"); assert!( argv.windows(3) .any(|w| w[0] == "--ro-bind-data" && w[2] == BWRAP_COMMAND_LINE_PATH), "invocation should include the bind of itself, got: {stdout}" ); let [separator, command, argument] = &argv[argv.len() - 3..] else { unreachable!() }; assert_eq!(separator, "--"); assert!( command.ends_with("/cat"), "resolved inner command, got: {command}" ); assert_eq!(argument, BWRAP_COMMAND_LINE_PATH); } #[test] fn bwrap_command_line_is_read_only() { let output = Sandbox::new(&[]) .args([ "--", "bash", "-c", &format!("echo x >> {BWRAP_COMMAND_LINE_PATH} && echo WRITABLE || echo READ_ONLY"), ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert_eq!(stdout.trim(), "READ_ONLY"); } #[test] fn user_rw_bind_can_override_run_agent_sandbox() { let dir = tempfile::TempDir::new().unwrap(); let dir_str = dir.path().to_str().unwrap(); let output = Sandbox::new(&["--rw", &format!("{dir_str}:/run/agent-sandbox")]) .args([ "--", "bash", "-c", &format!("test -e {BWRAP_COMMAND_LINE_PATH} || echo GONE"), ]) .output() .expect("agent-sandbox binary failed to execute"); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.contains("GONE"), "user --rw must win over the info directory, got: {stdout}" ); }