diff --git a/codex-rs/utils/pty/Cargo.toml b/codex-rs/utils/pty/Cargo.toml index ec221bfc94..cf98ac4904 100644 --- a/codex-rs/utils/pty/Cargo.toml +++ b/codex-rs/utils/pty/Cargo.toml @@ -1,5 +1,5 @@ [package] -edition = "2021" +edition = "2024" license.workspace = true name = "codex-utils-pty" version.workspace = true diff --git a/codex-rs/utils/pty/src/lib.rs b/codex-rs/utils/pty/src/lib.rs index 48fcd53b50..87898ddf71 100644 --- a/codex-rs/utils/pty/src/lib.rs +++ b/codex-rs/utils/pty/src/lib.rs @@ -13,14 +13,14 @@ pub const DEFAULT_OUTPUT_BYTES_CAP: usize = 1024 * 1024; pub use pipe::spawn_process as spawn_pipe_process; /// Spawn a non-interactive process using regular pipes, but close stdin immediately. pub use pipe::spawn_process_no_stdin as spawn_pipe_process_no_stdin; -/// Combine stdout/stderr receivers into a single broadcast receiver. -pub use process::combine_output_receivers; /// Handle for interacting with a spawned process (PTY or pipe). pub use process::ProcessHandle; /// Bundle of process handles plus split output and exit receivers returned by spawn helpers. pub use process::SpawnedProcess; /// Terminal size in character cells used for PTY spawn and resize operations. pub use process::TerminalSize; +/// Combine stdout/stderr receivers into a single broadcast receiver. +pub use process::combine_output_receivers; /// Backwards-compatible alias for ProcessHandle. pub type ExecCommandSession = ProcessHandle; /// Backwards-compatible alias for SpawnedProcess. diff --git a/codex-rs/utils/pty/src/pipe.rs b/codex-rs/utils/pty/src/pipe.rs index 2cebdef49f..903d1cf55e 100644 --- a/codex-rs/utils/pty/src/pipe.rs +++ b/codex-rs/utils/pty/src/pipe.rs @@ -3,9 +3,9 @@ use std::io; use std::io::ErrorKind; use std::path::Path; use std::process::Stdio; -use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::sync::Mutex as StdMutex; +use std::sync::atomic::AtomicBool; use anyhow::Result; use tokio::io::AsyncRead; @@ -64,11 +64,7 @@ fn kill_process(pid: u32) -> io::Result<()> { let success = winapi::um::processthreadsapi::TerminateProcess(handle, 1); let err = io::Error::last_os_error(); winapi::um::handleapi::CloseHandle(handle); - if success == 0 { - Err(err) - } else { - Ok(()) - } + if success == 0 { Err(err) } else { Ok(()) } } } diff --git a/codex-rs/utils/pty/src/process.rs b/codex-rs/utils/pty/src/process.rs index 61bdd3cd1b..8459f2b68f 100644 --- a/codex-rs/utils/pty/src/process.rs +++ b/codex-rs/utils/pty/src/process.rs @@ -2,9 +2,9 @@ use core::fmt; use std::io; #[cfg(unix)] use std::os::fd::RawFd; -use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::sync::Mutex as StdMutex; +use std::sync::atomic::AtomicBool; use anyhow::anyhow; use portable_pty::MasterPty; @@ -118,10 +118,10 @@ impl ProcessHandle { /// Returns a channel sender for writing raw bytes to the child stdin. pub fn writer_sender(&self) -> mpsc::Sender> { - if let Ok(writer_tx) = self.writer_tx.lock() { - if let Some(writer_tx) = writer_tx.as_ref() { - return writer_tx.clone(); - } + if let Ok(writer_tx) = self.writer_tx.lock() + && let Some(writer_tx) = writer_tx.as_ref() + { + return writer_tx.clone(); } let (writer_tx, writer_rx) = mpsc::channel(1); @@ -165,10 +165,10 @@ impl ProcessHandle { /// Attempts to kill the child while leaving the reader/writer tasks alive /// so callers can still drain output until EOF. pub fn request_terminate(&self) { - if let Ok(mut killer_opt) = self.killer.lock() { - if let Some(mut killer) = killer_opt.take() { - let _ = killer.kill(); - } + if let Ok(mut killer_opt) = self.killer.lock() + && let Some(mut killer) = killer_opt.take() + { + let _ = killer.kill(); } } @@ -176,25 +176,25 @@ impl ProcessHandle { pub fn terminate(&self) { self.request_terminate(); - if let Ok(mut h) = self.reader_handle.lock() { - if let Some(handle) = h.take() { - handle.abort(); - } + if let Ok(mut h) = self.reader_handle.lock() + && let Some(handle) = h.take() + { + handle.abort(); } if let Ok(mut handles) = self.reader_abort_handles.lock() { for handle in handles.drain(..) { handle.abort(); } } - if let Ok(mut h) = self.writer_handle.lock() { - if let Some(handle) = h.take() { - handle.abort(); - } + if let Ok(mut h) = self.writer_handle.lock() + && let Some(handle) = h.take() + { + handle.abort(); } - if let Ok(mut h) = self.wait_handle.lock() { - if let Some(handle) = h.take() { - handle.abort(); - } + if let Ok(mut h) = self.wait_handle.lock() + && let Some(handle) = h.take() + { + handle.abort(); } } } diff --git a/codex-rs/utils/pty/src/pty.rs b/codex-rs/utils/pty/src/pty.rs index e7bc9f9c97..4ae6facb7d 100644 --- a/codex-rs/utils/pty/src/pty.rs +++ b/codex-rs/utils/pty/src/pty.rs @@ -15,15 +15,15 @@ use std::path::Path; use std::process::Command as StdCommand; #[cfg(unix)] use std::process::Stdio; -use std::sync::atomic::AtomicBool; use std::sync::Arc; use std::sync::Mutex as StdMutex; +use std::sync::atomic::AtomicBool; use std::time::Duration; use anyhow::Result; +use portable_pty::CommandBuilder; #[cfg(not(windows))] use portable_pty::native_pty_system; -use portable_pty::CommandBuilder; use tokio::sync::mpsc; use tokio::sync::oneshot; use tokio::task::JoinHandle; diff --git a/codex-rs/utils/pty/src/tests.rs b/codex-rs/utils/pty/src/tests.rs index e7135114d9..fa0e821a24 100644 --- a/codex-rs/utils/pty/src/tests.rs +++ b/codex-rs/utils/pty/src/tests.rs @@ -3,6 +3,8 @@ use std::path::Path; use pretty_assertions::assert_eq; +use crate::SpawnedProcess; +use crate::TerminalSize; use crate::combine_output_receivers; #[cfg(unix)] use crate::pipe::spawn_process_no_stdin_with_inherited_fds; @@ -11,18 +13,15 @@ use crate::pty::spawn_process_with_inherited_fds; use crate::spawn_pipe_process; use crate::spawn_pipe_process_no_stdin; use crate::spawn_pty_process; -use crate::SpawnedProcess; -use crate::TerminalSize; fn find_python() -> Option { for candidate in ["python3", "python"] { if let Ok(output) = std::process::Command::new(candidate) .arg("--version") .output() + && output.status.success() { - if output.status.success() { - return Some(candidate.to_string()); - } + return Some(candidate.to_string()); } } None @@ -855,8 +854,7 @@ async fn pty_spawn_with_inherited_fds_supports_resize() -> anyhow::Result<()> { let write_end = unsafe { std::fs::File::from_raw_fd(fds[1]) }; let env_map: HashMap = std::env::vars().collect(); - let script = - "stty -echo; printf 'start:%s\\n' \"$(stty size)\"; IFS= read _line; printf 'after:%s\\n' \"$(stty size)\""; + let script = "stty -echo; printf 'start:%s\\n' \"$(stty size)\"; IFS= read _line; printf 'after:%s\\n' \"$(stty size)\""; let spawned = spawn_process_with_inherited_fds( "/bin/sh", &["-c".to_string(), script.to_string()], diff --git a/codex-rs/utils/pty/src/win/conpty.rs b/codex-rs/utils/pty/src/win/conpty.rs index a0e5903810..ae490160ae 100644 --- a/codex-rs/utils/pty/src/win/conpty.rs +++ b/codex-rs/utils/pty/src/win/conpty.rs @@ -22,13 +22,13 @@ use crate::win::psuedocon::PsuedoCon; use anyhow::Error; use filedescriptor::FileDescriptor; use filedescriptor::Pipe; -use portable_pty::cmdbuilder::CommandBuilder; use portable_pty::Child; use portable_pty::MasterPty; use portable_pty::PtyPair; use portable_pty::PtySize; use portable_pty::PtySystem; use portable_pty::SlavePty; +use portable_pty::cmdbuilder::CommandBuilder; use std::mem::ManuallyDrop; use std::os::windows::io::AsRawHandle; use std::os::windows::io::RawHandle; diff --git a/codex-rs/utils/pty/src/win/mod.rs b/codex-rs/utils/pty/src/win/mod.rs index bcd65eb487..78f5af2ce7 100644 --- a/codex-rs/utils/pty/src/win/mod.rs +++ b/codex-rs/utils/pty/src/win/mod.rs @@ -142,11 +142,7 @@ impl Child for WinChild { fn process_id(&self) -> Option { let res = unsafe { GetProcessId(self.proc.lock().unwrap().as_raw_handle() as _) }; - if res == 0 { - None - } else { - Some(res) - } + if res == 0 { None } else { Some(res) } } fn as_raw_handle(&self) -> Option { diff --git a/codex-rs/utils/pty/src/win/procthreadattr.rs b/codex-rs/utils/pty/src/win/procthreadattr.rs index 6d464e99de..c7cf68fed9 100644 --- a/codex-rs/utils/pty/src/win/procthreadattr.rs +++ b/codex-rs/utils/pty/src/win/procthreadattr.rs @@ -19,8 +19,8 @@ // SOFTWARE. use super::psuedocon::HPCON; -use anyhow::ensure; use anyhow::Error; +use anyhow::ensure; use std::io::Error as IoError; use std::mem; use std::ptr; diff --git a/codex-rs/utils/pty/src/win/psuedocon.rs b/codex-rs/utils/pty/src/win/psuedocon.rs index b1c72a739d..3476665633 100644 --- a/codex-rs/utils/pty/src/win/psuedocon.rs +++ b/codex-rs/utils/pty/src/win/psuedocon.rs @@ -21,9 +21,9 @@ use super::WinChild; use crate::win::procthreadattr::ProcThreadAttributeList; +use anyhow::Error; use anyhow::bail; use anyhow::ensure; -use anyhow::Error; use filedescriptor::FileDescriptor; use filedescriptor::OwnedHandle; use lazy_static::lazy_static; @@ -356,8 +356,8 @@ fn append_quoted(arg: &OsStr, cmdline: &mut Vec) { #[cfg(test)] mod tests { - use super::windows_build_number; use super::MIN_CONPTY_BUILD; + use super::windows_build_number; #[test] fn windows_build_number_returns_value() { diff --git a/codex-rs/windows-sandbox-rs/BUILD.bazel b/codex-rs/windows-sandbox-rs/BUILD.bazel index b09ee38ed0..e3f0112a85 100644 --- a/codex-rs/windows-sandbox-rs/BUILD.bazel +++ b/codex-rs/windows-sandbox-rs/BUILD.bazel @@ -7,5 +7,4 @@ codex_rust_crate( "Cargo.toml", "codex-windows-sandbox-setup.manifest", ], - crate_edition = "2021", ) diff --git a/codex-rs/windows-sandbox-rs/Cargo.toml b/codex-rs/windows-sandbox-rs/Cargo.toml index 91cb178435..0fb2192578 100644 --- a/codex-rs/windows-sandbox-rs/Cargo.toml +++ b/codex-rs/windows-sandbox-rs/Cargo.toml @@ -1,6 +1,6 @@ [package] build = "build.rs" -edition = "2021" +edition = "2024" license.workspace = true name = "codex-windows-sandbox" version.workspace = true diff --git a/codex-rs/windows-sandbox-rs/src/audit.rs b/codex-rs/windows-sandbox-rs/src/audit.rs index d85c5dea8e..0f115323ea 100644 --- a/codex-rs/windows-sandbox-rs/src/audit.rs +++ b/codex-rs/windows-sandbox-rs/src/audit.rs @@ -33,10 +33,10 @@ const SKIP_DIR_SUFFIXES: &[&str] = &[ ]; fn unique_push(set: &mut HashSet, out: &mut Vec, p: PathBuf) { - if let Ok(abs) = p.canonicalize() { - if set.insert(abs.clone()) { - out.push(abs); - } + if let Ok(abs) = p.canonicalize() + && set.insert(abs.clone()) + { + out.push(abs); } } diff --git a/codex-rs/windows-sandbox-rs/src/conpty/mod.rs b/codex-rs/windows-sandbox-rs/src/conpty/mod.rs index 9c05e9ea67..c7b992f518 100644 --- a/codex-rs/windows-sandbox-rs/src/conpty/mod.rs +++ b/codex-rs/windows-sandbox-rs/src/conpty/mod.rs @@ -23,8 +23,8 @@ use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::INVALID_HANDLE_VALUE; use windows_sys::Win32::System::Console::ClosePseudoConsole; -use windows_sys::Win32::System::Threading::CreateProcessAsUserW; use windows_sys::Win32::System::Threading::CREATE_UNICODE_ENVIRONMENT; +use windows_sys::Win32::System::Threading::CreateProcessAsUserW; use windows_sys::Win32::System::Threading::EXTENDED_STARTUPINFO_PRESENT; use windows_sys::Win32::System::Threading::PROCESS_INFORMATION; use windows_sys::Win32::System::Threading::STARTF_USESTDHANDLES; diff --git a/codex-rs/windows-sandbox-rs/src/conpty/proc_thread_attr.rs b/codex-rs/windows-sandbox-rs/src/conpty/proc_thread_attr.rs index 3fe3870f9c..393172a0f8 100644 --- a/codex-rs/windows-sandbox-rs/src/conpty/proc_thread_attr.rs +++ b/codex-rs/windows-sandbox-rs/src/conpty/proc_thread_attr.rs @@ -8,8 +8,8 @@ use std::io; use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::System::Threading::DeleteProcThreadAttributeList; use windows_sys::Win32::System::Threading::InitializeProcThreadAttributeList; -use windows_sys::Win32::System::Threading::UpdateProcThreadAttribute; use windows_sys::Win32::System::Threading::LPPROC_THREAD_ATTRIBUTE_LIST; +use windows_sys::Win32::System::Threading::UpdateProcThreadAttribute; const PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE: usize = 0x00020016; diff --git a/codex-rs/windows-sandbox-rs/src/desktop.rs b/codex-rs/windows-sandbox-rs/src/desktop.rs index 822e43b071..d2aa129b92 100644 --- a/codex-rs/windows-sandbox-rs/src/desktop.rs +++ b/codex-rs/windows-sandbox-rs/src/desktop.rs @@ -89,7 +89,7 @@ struct PrivateDesktop { impl PrivateDesktop { fn create(logs_base_dir: Option<&Path>) -> Result { let mut rng = SmallRng::from_entropy(); - let name = format!("CodexSandboxDesktop-{:x}", rng.gen::()); + let name = format!("CodexSandboxDesktop-{:x}", rng.r#gen::()); let name_wide = to_wide(&name); let handle = unsafe { CreateDesktopW( diff --git a/codex-rs/windows-sandbox-rs/src/elevated/command_runner_win.rs b/codex-rs/windows-sandbox-rs/src/elevated/command_runner_win.rs index 82347fcca7..5572c1bf8e 100644 --- a/codex-rs/windows-sandbox-rs/src/elevated/command_runner_win.rs +++ b/codex-rs/windows-sandbox-rs/src/elevated/command_runner_win.rs @@ -8,34 +8,35 @@ //! path spawns the child directly and does not use this runner. #![cfg(target_os = "windows")] +#![allow(unsafe_op_in_unsafe_fn)] use anyhow::Context; use anyhow::Result; +use codex_windows_sandbox::PipeSpawnHandles; +use codex_windows_sandbox::SandboxPolicy; +use codex_windows_sandbox::StderrMode; +use codex_windows_sandbox::StdinMode; use codex_windows_sandbox::allow_null_device; use codex_windows_sandbox::convert_string_sid_to_sid; use codex_windows_sandbox::create_readonly_token_with_caps_from; use codex_windows_sandbox::create_workspace_write_token_with_caps_from; use codex_windows_sandbox::get_current_token_for_restriction; use codex_windows_sandbox::hide_current_user_profile_dir; -use codex_windows_sandbox::ipc_framed::decode_bytes; -use codex_windows_sandbox::ipc_framed::encode_bytes; -use codex_windows_sandbox::ipc_framed::read_frame; -use codex_windows_sandbox::ipc_framed::write_frame; use codex_windows_sandbox::ipc_framed::ErrorPayload; use codex_windows_sandbox::ipc_framed::ExitPayload; use codex_windows_sandbox::ipc_framed::FramedMessage; use codex_windows_sandbox::ipc_framed::Message; use codex_windows_sandbox::ipc_framed::OutputPayload; use codex_windows_sandbox::ipc_framed::OutputStream; +use codex_windows_sandbox::ipc_framed::decode_bytes; +use codex_windows_sandbox::ipc_framed::encode_bytes; +use codex_windows_sandbox::ipc_framed::read_frame; +use codex_windows_sandbox::ipc_framed::write_frame; use codex_windows_sandbox::log_note; use codex_windows_sandbox::parse_policy; use codex_windows_sandbox::read_handle_loop; use codex_windows_sandbox::spawn_process_with_pipes; use codex_windows_sandbox::to_wide; -use codex_windows_sandbox::PipeSpawnHandles; -use codex_windows_sandbox::SandboxPolicy; -use codex_windows_sandbox::StderrMode; -use codex_windows_sandbox::StdinMode; use std::ffi::c_void; use std::fs::File; use std::os::windows::io::FromRawHandle; @@ -46,9 +47,9 @@ use std::sync::Arc; use std::sync::Mutex as StdMutex; use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::GetLastError; -use windows_sys::Win32::Foundation::LocalFree; use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HLOCAL; +use windows_sys::Win32::Foundation::LocalFree; use windows_sys::Win32::Storage::FileSystem::CreateFileW; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_READ; use windows_sys::Win32::Storage::FileSystem::FILE_GENERIC_WRITE; @@ -56,16 +57,16 @@ use windows_sys::Win32::Storage::FileSystem::OPEN_EXISTING; use windows_sys::Win32::System::Console::ClosePseudoConsole; use windows_sys::Win32::System::JobObjects::AssignProcessToJobObject; use windows_sys::Win32::System::JobObjects::CreateJobObjectW; +use windows_sys::Win32::System::JobObjects::JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; +use windows_sys::Win32::System::JobObjects::JOBOBJECT_EXTENDED_LIMIT_INFORMATION; use windows_sys::Win32::System::JobObjects::JobObjectExtendedLimitInformation; use windows_sys::Win32::System::JobObjects::SetInformationJobObject; -use windows_sys::Win32::System::JobObjects::JOBOBJECT_EXTENDED_LIMIT_INFORMATION; -use windows_sys::Win32::System::JobObjects::JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; use windows_sys::Win32::System::Threading::GetExitCodeProcess; use windows_sys::Win32::System::Threading::GetProcessId; -use windows_sys::Win32::System::Threading::TerminateProcess; -use windows_sys::Win32::System::Threading::WaitForSingleObject; use windows_sys::Win32::System::Threading::INFINITE; use windows_sys::Win32::System::Threading::PROCESS_INFORMATION; +use windows_sys::Win32::System::Threading::TerminateProcess; +use windows_sys::Win32::System::Threading::WaitForSingleObject; #[path = "cwd_junction.rs"] mod cwd_junction; @@ -332,13 +333,13 @@ fn spawn_output_reader( }, }, }; - if let Ok(mut guard) = writer.lock() { - if let Err(err) = write_frame(&mut *guard, &msg) { - log_note( - &format!("runner output write failed: {err}"), - log_dir.as_deref(), - ); - } + if let Ok(mut guard) = writer.lock() + && let Err(err) = write_frame(&mut *guard, &msg) + { + log_note( + &format!("runner output write failed: {err}"), + log_dir.as_deref(), + ); } }) } @@ -382,11 +383,11 @@ fn spawn_input_loop( } } Message::Terminate { .. } => { - if let Ok(guard) = process_handle.lock() { - if let Some(handle) = guard.as_ref() { - unsafe { - let _ = TerminateProcess(*handle, 1); - } + if let Ok(guard) = process_handle.lock() + && let Some(handle) = guard.as_ref() + { + unsafe { + let _ = TerminateProcess(*handle, 1); } } } @@ -544,10 +545,10 @@ pub fn main() -> Result<()> { }, }, }; - if let Ok(mut guard) = pipe_write.lock() { - if let Err(err) = write_frame(&mut *guard, &exit_msg) { - log_note(&format!("runner exit write failed: {err}"), log_dir); - } + if let Ok(mut guard) = pipe_write.lock() + && let Err(err) = write_frame(&mut *guard, &exit_msg) + { + log_note(&format!("runner exit write failed: {err}"), log_dir); } std::process::exit(exit_code); diff --git a/codex-rs/windows-sandbox-rs/src/elevated/ipc_framed.rs b/codex-rs/windows-sandbox-rs/src/elevated/ipc_framed.rs index 37590c34b9..d56ec1d0e0 100644 --- a/codex-rs/windows-sandbox-rs/src/elevated/ipc_framed.rs +++ b/codex-rs/windows-sandbox-rs/src/elevated/ipc_framed.rs @@ -8,8 +8,8 @@ //! through the elevated runner. use anyhow::Result; -use base64::engine::general_purpose::STANDARD; use base64::Engine as _; +use base64::engine::general_purpose::STANDARD; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; diff --git a/codex-rs/windows-sandbox-rs/src/elevated_impl.rs b/codex-rs/windows-sandbox-rs/src/elevated_impl.rs index 365ac37d6f..cc2b7fdad6 100644 --- a/codex-rs/windows-sandbox-rs/src/elevated_impl.rs +++ b/codex-rs/windows-sandbox-rs/src/elevated_impl.rs @@ -16,37 +16,37 @@ pub struct ElevatedSandboxCaptureRequest<'a> { mod windows_impl { use super::ElevatedSandboxCaptureRequest; use crate::acl::allow_null_device; - use crate::allow::compute_allow_paths; use crate::allow::AllowDenyPaths; + use crate::allow::compute_allow_paths; use crate::cap::load_or_create_cap_sids; use crate::env::ensure_non_interactive_pager; use crate::env::inherit_path_env; use crate::env::normalize_null_device_env; - use crate::helper_materialization::resolve_helper_for_launch; use crate::helper_materialization::HelperExecutable; + use crate::helper_materialization::resolve_helper_for_launch; use crate::identity::require_logon_sandbox_creds; - use crate::ipc_framed::decode_bytes; - use crate::ipc_framed::read_frame; - use crate::ipc_framed::write_frame; use crate::ipc_framed::FramedMessage; use crate::ipc_framed::Message; use crate::ipc_framed::OutputStream; use crate::ipc_framed::SpawnRequest; + use crate::ipc_framed::decode_bytes; + use crate::ipc_framed::read_frame; + use crate::ipc_framed::write_frame; use crate::logging::log_failure; use crate::logging::log_note; use crate::logging::log_start; use crate::logging::log_success; - use crate::policy::parse_policy; use crate::policy::SandboxPolicy; + use crate::policy::parse_policy; use crate::token::convert_string_sid_to_sid; use crate::winutil::quote_windows_arg; use crate::winutil::resolve_sid; use crate::winutil::string_from_sid_bytes; use crate::winutil::to_wide; use anyhow::Result; - use rand::rngs::SmallRng; use rand::Rng; use rand::SeedableRng; + use rand::rngs::SmallRng; use std::collections::HashMap; use std::ffi::c_void; use std::fs::File; @@ -84,16 +84,16 @@ mod windows_impl { return Some(cur); } if marker.is_file() { - if let Ok(txt) = std::fs::read_to_string(&marker) { - if let Some(rest) = txt.trim().strip_prefix("gitdir:") { - let gitdir = rest.trim(); - let resolved = if Path::new(gitdir).is_absolute() { - PathBuf::from(gitdir) - } else { - cur.join(gitdir) - }; - return resolved.parent().map(|p| p.to_path_buf()).or(Some(cur)); - } + if let Ok(txt) = std::fs::read_to_string(&marker) + && let Some(rest) = txt.trim().strip_prefix("gitdir:") + { + let gitdir = rest.trim(); + let resolved = if Path::new(gitdir).is_absolute() { + PathBuf::from(gitdir) + } else { + cur.join(gitdir) + }; + return resolved.parent().map(|p| p.to_path_buf()).or(Some(cur)); } return Some(cur); } @@ -143,7 +143,11 @@ mod windows_impl { /// Generates a unique named-pipe path used to communicate with the runner process. fn pipe_name(suffix: &str) -> String { let mut rng = SmallRng::from_entropy(); - format!(r"\\.\pipe\codex-runner-{:x}-{}", rng.gen::(), suffix) + format!( + r"\\.\pipe\codex-runner-{:x}-{}", + rng.r#gen::(), + suffix + ) } /// Creates a named pipe whose DACL only allows the sandbox user to connect. @@ -507,8 +511,8 @@ pub use windows_impl::run_windows_sandbox_capture; #[cfg(not(target_os = "windows"))] mod stub { use super::ElevatedSandboxCaptureRequest; - use anyhow::bail; use anyhow::Result; + use anyhow::bail; #[derive(Debug, Default)] pub struct CaptureResult { diff --git a/codex-rs/windows-sandbox-rs/src/env.rs b/codex-rs/windows-sandbox-rs/src/env.rs index c69a0033e9..c3f85cfffd 100644 --- a/codex-rs/windows-sandbox-rs/src/env.rs +++ b/codex-rs/windows-sandbox-rs/src/env.rs @@ -30,15 +30,15 @@ pub fn ensure_non_interactive_pager(env_map: &mut HashMap) { // Keep PATH and PATHEXT stable for callers that rely on inheriting the parent process env. pub fn inherit_path_env(env_map: &mut HashMap) { - if !env_map.contains_key("PATH") { - if let Ok(path) = env::var("PATH") { - env_map.insert("PATH".into(), path); - } + if !env_map.contains_key("PATH") + && let Ok(path) = env::var("PATH") + { + env_map.insert("PATH".into(), path); } - if !env_map.contains_key("PATHEXT") { - if let Ok(pathext) = env::var("PATHEXT") { - env_map.insert("PATHEXT".into(), pathext); - } + if !env_map.contains_key("PATHEXT") + && let Ok(pathext) = env::var("PATHEXT") + { + env_map.insert("PATHEXT".into(), pathext); } } diff --git a/codex-rs/windows-sandbox-rs/src/firewall.rs b/codex-rs/windows-sandbox-rs/src/firewall.rs index a95d3b57e2..c0caa165fc 100644 --- a/codex-rs/windows-sandbox-rs/src/firewall.rs +++ b/codex-rs/windows-sandbox-rs/src/firewall.rs @@ -4,25 +4,25 @@ use anyhow::Result; use std::fs::File; use std::io::Write; -use windows::core::Interface; -use windows::core::BSTR; use windows::Win32::Foundation::VARIANT_TRUE; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwPolicy2; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRule3; use windows::Win32::NetworkManagement::WindowsFirewall::INetFwRules; -use windows::Win32::NetworkManagement::WindowsFirewall::NetFwPolicy2; -use windows::Win32::NetworkManagement::WindowsFirewall::NetFwRule; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_ACTION_BLOCK; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_ANY; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_TCP; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_IP_PROTOCOL_UDP; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_PROFILE2_ALL; use windows::Win32::NetworkManagement::WindowsFirewall::NET_FW_RULE_DIR_OUT; +use windows::Win32::NetworkManagement::WindowsFirewall::NetFwPolicy2; +use windows::Win32::NetworkManagement::WindowsFirewall::NetFwRule; +use windows::Win32::System::Com::CLSCTX_INPROC_SERVER; +use windows::Win32::System::Com::COINIT_APARTMENTTHREADED; use windows::Win32::System::Com::CoCreateInstance; use windows::Win32::System::Com::CoInitializeEx; use windows::Win32::System::Com::CoUninitialize; -use windows::Win32::System::Com::CLSCTX_INPROC_SERVER; -use windows::Win32::System::Com::COINIT_APARTMENTTHREADED; +use windows::core::BSTR; +use windows::core::Interface; use codex_windows_sandbox::SetupErrorCode; use codex_windows_sandbox::SetupFailure; @@ -40,8 +40,7 @@ const OFFLINE_BLOCK_LOOPBACK_TCP_RULE_FRIENDLY: &str = const OFFLINE_BLOCK_LOOPBACK_UDP_RULE_FRIENDLY: &str = "Codex Sandbox Offline - Block Loopback UDP"; const OFFLINE_PROXY_ALLOW_RULE_NAME: &str = "codex_sandbox_offline_allow_loopback_proxy"; const LOOPBACK_REMOTE_ADDRESSES: &str = "127.0.0.0/8,::1"; -const NON_LOOPBACK_REMOTE_ADDRESSES: &str = - "0.0.0.0-126.255.255.255,128.0.0.0-255.255.255.255,::,::2-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; +const NON_LOOPBACK_REMOTE_ADDRESSES: &str = "0.0.0.0-126.255.255.255,128.0.0.0-255.255.255.255,::,::2-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; struct BlockRuleSpec<'a> { internal_name: &'a str, diff --git a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs index 37db3c59c2..375199f5cc 100644 --- a/codex-rs/windows-sandbox-rs/src/helper_materialization.rs +++ b/codex-rs/windows-sandbox-rs/src/helper_materialization.rs @@ -45,12 +45,12 @@ pub(crate) fn helper_bin_dir(codex_home: &Path) -> PathBuf { } pub(crate) fn legacy_lookup(kind: HelperExecutable) -> PathBuf { - if let Ok(exe) = std::env::current_exe() { - if let Some(dir) = exe.parent() { - let candidate = dir.join(kind.file_name()); - if candidate.exists() { - return candidate; - } + if let Ok(exe) = std::env::current_exe() + && let Some(dir) = exe.parent() + { + let candidate = dir.join(kind.file_name()); + if candidate.exists() { + return candidate; } } PathBuf::from(kind.file_name()) @@ -377,4 +377,3 @@ mod tests { ); } } - diff --git a/codex-rs/windows-sandbox-rs/src/lib.rs b/codex-rs/windows-sandbox-rs/src/lib.rs index 11afda750d..b0de8c2e02 100644 --- a/codex-rs/windows-sandbox-rs/src/lib.rs +++ b/codex-rs/windows-sandbox-rs/src/lib.rs @@ -1,3 +1,7 @@ +// Rust 2024 surfaces this lint across the crate; keep the edition bump separate +// from the eventual unsafe cleanup. +#![allow(unsafe_op_in_unsafe_fn)] + macro_rules! windows_modules { ($($name:ident),+ $(,)?) => { $(#[cfg(target_os = "windows")] mod $name;)+ @@ -70,10 +74,10 @@ pub use dpapi::protect as dpapi_protect; #[cfg(target_os = "windows")] pub use dpapi::unprotect as dpapi_unprotect; #[cfg(target_os = "windows")] -pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated; -#[cfg(target_os = "windows")] pub use elevated_impl::ElevatedSandboxCaptureRequest; #[cfg(target_os = "windows")] +pub use elevated_impl::run_windows_sandbox_capture as run_windows_sandbox_capture_elevated; +#[cfg(target_os = "windows")] pub use helper_materialization::resolve_current_exe_for_launch; #[cfg(target_os = "windows")] pub use hide_users::hide_current_user_profile_dir; @@ -84,15 +88,21 @@ pub use identity::require_logon_sandbox_creds; #[cfg(target_os = "windows")] pub use identity::sandbox_setup_is_complete; #[cfg(target_os = "windows")] -pub use logging::log_note; -#[cfg(target_os = "windows")] pub use logging::LOG_FILE_NAME; #[cfg(target_os = "windows")] +pub use logging::log_note; +#[cfg(target_os = "windows")] pub use path_normalization::canonicalize_path; #[cfg(target_os = "windows")] +pub use policy::SandboxPolicy; +#[cfg(target_os = "windows")] pub use policy::parse_policy; #[cfg(target_os = "windows")] -pub use policy::SandboxPolicy; +pub use process::PipeSpawnHandles; +#[cfg(target_os = "windows")] +pub use process::StderrMode; +#[cfg(target_os = "windows")] +pub use process::StdinMode; #[cfg(target_os = "windows")] pub use process::create_process_as_user; #[cfg(target_os = "windows")] @@ -100,11 +110,11 @@ pub use process::read_handle_loop; #[cfg(target_os = "windows")] pub use process::spawn_process_with_pipes; #[cfg(target_os = "windows")] -pub use process::PipeSpawnHandles; +pub use setup::SETUP_VERSION; #[cfg(target_os = "windows")] -pub use process::StderrMode; +pub use setup::SandboxSetupRequest; #[cfg(target_os = "windows")] -pub use process::StdinMode; +pub use setup::SetupRootOverrides; #[cfg(target_os = "windows")] pub use setup::run_elevated_setup; #[cfg(target_os = "windows")] @@ -118,11 +128,11 @@ pub use setup::sandbox_dir; #[cfg(target_os = "windows")] pub use setup::sandbox_secrets_dir; #[cfg(target_os = "windows")] -pub use setup::SandboxSetupRequest; +pub use setup_error::SetupErrorCode; #[cfg(target_os = "windows")] -pub use setup::SetupRootOverrides; +pub use setup_error::SetupErrorReport; #[cfg(target_os = "windows")] -pub use setup::SETUP_VERSION; +pub use setup_error::SetupFailure; #[cfg(target_os = "windows")] pub use setup_error::extract_failure as extract_setup_failure; #[cfg(target_os = "windows")] @@ -132,12 +142,6 @@ pub use setup_error::setup_error_path; #[cfg(target_os = "windows")] pub use setup_error::write_setup_error_report; #[cfg(target_os = "windows")] -pub use setup_error::SetupErrorCode; -#[cfg(target_os = "windows")] -pub use setup_error::SetupErrorReport; -#[cfg(target_os = "windows")] -pub use setup_error::SetupFailure; -#[cfg(target_os = "windows")] pub use token::convert_string_sid_to_sid; #[cfg(target_os = "windows")] pub use token::create_readonly_token_with_cap_from; @@ -148,14 +152,14 @@ pub use token::create_workspace_write_token_with_caps_from; #[cfg(target_os = "windows")] pub use token::get_current_token_for_restriction; #[cfg(target_os = "windows")] +pub use windows_impl::CaptureResult; +#[cfg(target_os = "windows")] pub use windows_impl::run_windows_sandbox_capture; #[cfg(target_os = "windows")] pub use windows_impl::run_windows_sandbox_capture_with_extra_deny_write_paths; #[cfg(target_os = "windows")] pub use windows_impl::run_windows_sandbox_legacy_preflight; #[cfg(target_os = "windows")] -pub use windows_impl::CaptureResult; -#[cfg(target_os = "windows")] pub use winutil::quote_windows_arg; #[cfg(target_os = "windows")] pub use winutil::string_from_sid_bytes; @@ -168,14 +172,14 @@ pub use workspace_acl::protect_workspace_agents_dir; #[cfg(target_os = "windows")] pub use workspace_acl::protect_workspace_codex_dir; +#[cfg(not(target_os = "windows"))] +pub use stub::CaptureResult; #[cfg(not(target_os = "windows"))] pub use stub::apply_world_writable_scan_and_denies; #[cfg(not(target_os = "windows"))] pub use stub::run_windows_sandbox_capture; #[cfg(not(target_os = "windows"))] pub use stub::run_windows_sandbox_legacy_preflight; -#[cfg(not(target_os = "windows"))] -pub use stub::CaptureResult; #[cfg(target_os = "windows")] mod windows_impl { @@ -183,8 +187,8 @@ mod windows_impl { use super::acl::add_deny_write_ace; use super::acl::allow_null_device; use super::acl::revoke_ace; - use super::allow::compute_allow_paths; use super::allow::AllowDenyPaths; + use super::allow::compute_allow_paths; use super::cap::load_or_create_cap_sids; use super::cap::workspace_cap_sid_for_cwd; use super::env::apply_no_network_to_env; @@ -194,8 +198,8 @@ mod windows_impl { use super::logging::log_start; use super::logging::log_success; use super::path_normalization::canonicalize_path; - use super::policy::parse_policy; use super::policy::SandboxPolicy; + use super::policy::parse_policy; use super::process::create_process_as_user; use super::token::convert_string_sid_to_sid; use super::token::create_workspace_write_token_with_caps_from; @@ -211,13 +215,13 @@ mod windows_impl { use std::ptr; use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::GetLastError; - use windows_sys::Win32::Foundation::SetHandleInformation; use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::Foundation::HANDLE_FLAG_INHERIT; + use windows_sys::Win32::Foundation::SetHandleInformation; use windows_sys::Win32::System::Pipes::CreatePipe; use windows_sys::Win32::System::Threading::GetExitCodeProcess; - use windows_sys::Win32::System::Threading::WaitForSingleObject; use windows_sys::Win32::System::Threading::INFINITE; + use windows_sys::Win32::System::Threading::WaitForSingleObject; type PipeHandles = ((HANDLE, HANDLE), (HANDLE, HANDLE), (HANDLE, HANDLE)); @@ -355,15 +359,15 @@ mod windows_impl { }; unsafe { - if is_workspace_write { - if let Ok(base) = super::token::get_current_token_for_restriction() { - if let Ok(bytes) = super::token::get_logon_sid_bytes(base) { - let mut tmp = bytes.clone(); - let psid2 = tmp.as_mut_ptr() as *mut c_void; - allow_null_device(psid2); - } - windows_sys::Win32::Foundation::CloseHandle(base); + if is_workspace_write + && let Ok(base) = super::token::get_current_token_for_restriction() + { + if let Ok(bytes) = super::token::get_logon_sid_bytes(base) { + let mut tmp = bytes.clone(); + let psid2 = tmp.as_mut_ptr() as *mut c_void; + allow_null_device(psid2); } + windows_sys::Win32::Foundation::CloseHandle(base); } } @@ -384,23 +388,24 @@ mod windows_impl { } else { psid_generic }; - if let Ok(added) = add_allow_ace(p, psid) { - if added { - if persist_aces { - if p.is_dir() { - // best-effort seeding omitted intentionally - } - } else { - guards.push((p.clone(), psid)); + if let Ok(added) = add_allow_ace(p, psid) + && added + { + if persist_aces { + if p.is_dir() { + // best-effort seeding omitted intentionally } + } else { + guards.push((p.clone(), psid)); } } } for p in &deny { - if let Ok(added) = add_deny_write_ace(p, psid_generic) { - if added && !persist_aces { - guards.push((p.clone(), psid_generic)); - } + if let Ok(added) = add_deny_write_ace(p, psid_generic) + && added + && !persist_aces + { + guards.push((p.clone(), psid_generic)); } } allow_null_device(psid_generic); @@ -631,8 +636,8 @@ mod windows_impl { #[cfg(not(target_os = "windows"))] mod stub { - use anyhow::bail; use anyhow::Result; + use anyhow::bail; use codex_protocol::protocol::SandboxPolicy; use std::collections::HashMap; use std::path::Path; diff --git a/codex-rs/windows-sandbox-rs/src/logging.rs b/codex-rs/windows-sandbox-rs/src/logging.rs index f575ce3b8d..1c0d695f32 100644 --- a/codex-rs/windows-sandbox-rs/src/logging.rs +++ b/codex-rs/windows-sandbox-rs/src/logging.rs @@ -37,12 +37,11 @@ fn log_file_path(base_dir: &Path) -> Option { } fn append_line(line: &str, base_dir: Option<&Path>) { - if let Some(dir) = base_dir { - if let Some(path) = log_file_path(dir) { - if let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) { - let _ = writeln!(f, "{}", line); - } - } + if let Some(dir) = base_dir + && let Some(path) = log_file_path(dir) + && let Ok(mut f) = OpenOptions::new().create(true).append(true).open(path) + { + let _ = writeln!(f, "{line}"); } } diff --git a/codex-rs/windows-sandbox-rs/src/read_acl_mutex.rs b/codex-rs/windows-sandbox-rs/src/read_acl_mutex.rs index 0b3435fec1..643d70fa37 100644 --- a/codex-rs/windows-sandbox-rs/src/read_acl_mutex.rs +++ b/codex-rs/windows-sandbox-rs/src/read_acl_mutex.rs @@ -1,14 +1,14 @@ use anyhow::Result; use std::ffi::OsStr; use windows_sys::Win32::Foundation::CloseHandle; -use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::ERROR_ALREADY_EXISTS; use windows_sys::Win32::Foundation::ERROR_FILE_NOT_FOUND; +use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::HANDLE; use windows_sys::Win32::System::Threading::CreateMutexW; +use windows_sys::Win32::System::Threading::MUTEX_ALL_ACCESS; use windows_sys::Win32::System::Threading::OpenMutexW; use windows_sys::Win32::System::Threading::ReleaseMutex; -use windows_sys::Win32::System::Threading::MUTEX_ALL_ACCESS; use super::to_wide; diff --git a/codex-rs/windows-sandbox-rs/src/sandbox_users.rs b/codex-rs/windows-sandbox-rs/src/sandbox_users.rs index e006b696fb..13460b9444 100644 --- a/codex-rs/windows-sandbox-rs/src/sandbox_users.rs +++ b/codex-rs/windows-sandbox-rs/src/sandbox_users.rs @@ -1,27 +1,27 @@ #![cfg(target_os = "windows")] use anyhow::Result; -use base64::engine::general_purpose::STANDARD as BASE64; use base64::Engine; -use rand::rngs::SmallRng; +use base64::engine::general_purpose::STANDARD as BASE64; use rand::RngCore; use rand::SeedableRng; +use rand::rngs::SmallRng; use serde::Serialize; -use std::ffi::c_void; use std::ffi::OsStr; +use std::ffi::c_void; use std::fs::File; use std::path::Path; use std::path::PathBuf; +use windows_sys::Win32::Foundation::ERROR_INSUFFICIENT_BUFFER; use windows_sys::Win32::Foundation::GetLastError; use windows_sys::Win32::Foundation::LocalFree; -use windows_sys::Win32::Foundation::ERROR_INSUFFICIENT_BUFFER; +use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_INFO_1; +use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_MEMBERS_INFO_3; use windows_sys::Win32::NetworkManagement::NetManagement::NERR_Success; use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAdd; use windows_sys::Win32::NetworkManagement::NetManagement::NetLocalGroupAddMembers; use windows_sys::Win32::NetworkManagement::NetManagement::NetUserAdd; use windows_sys::Win32::NetworkManagement::NetManagement::NetUserSetInfo; -use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_INFO_1; -use windows_sys::Win32::NetworkManagement::NetManagement::LOCALGROUP_MEMBERS_INFO_3; use windows_sys::Win32::NetworkManagement::NetManagement::UF_DONT_EXPIRE_PASSWD; use windows_sys::Win32::NetworkManagement::NetManagement::UF_SCRIPT; use windows_sys::Win32::NetworkManagement::NetManagement::USER_INFO_1; @@ -34,14 +34,14 @@ use windows_sys::Win32::Security::LookupAccountNameW; use windows_sys::Win32::Security::LookupAccountSidW; use windows_sys::Win32::Security::SID_NAME_USE; +use codex_windows_sandbox::SETUP_VERSION; +use codex_windows_sandbox::SetupErrorCode; +use codex_windows_sandbox::SetupFailure; use codex_windows_sandbox::dpapi_protect; use codex_windows_sandbox::sandbox_dir; use codex_windows_sandbox::sandbox_secrets_dir; use codex_windows_sandbox::string_from_sid_bytes; use codex_windows_sandbox::to_wide; -use codex_windows_sandbox::SetupErrorCode; -use codex_windows_sandbox::SetupFailure; -use codex_windows_sandbox::SETUP_VERSION; pub const SANDBOX_USERS_GROUP: &str = "CodexSandboxUsers"; const SANDBOX_USERS_GROUP_COMMENT: &str = "Codex sandbox internal group (managed)"; diff --git a/codex-rs/windows-sandbox-rs/src/setup_error.rs b/codex-rs/windows-sandbox-rs/src/setup_error.rs index 23022450a0..64e618ace1 100644 --- a/codex-rs/windows-sandbox-rs/src/setup_error.rs +++ b/codex-rs/windows-sandbox-rs/src/setup_error.rs @@ -189,15 +189,16 @@ pub fn sanitize_setup_metric_tag_value(value: &str) -> String { fn redact_home_paths(value: &str) -> String { let mut usernames: Vec = Vec::new(); - if let Ok(username) = std::env::var("USERNAME") { - if !username.trim().is_empty() { - usernames.push(username); - } + if let Ok(username) = std::env::var("USERNAME") + && !username.trim().is_empty() + { + usernames.push(username); } - if let Ok(user) = std::env::var("USER") { - if !user.trim().is_empty() && !usernames.iter().any(|v| v.eq_ignore_ascii_case(&user)) { - usernames.push(user); - } + if let Ok(user) = std::env::var("USER") + && !user.trim().is_empty() + && !usernames.iter().any(|v| v.eq_ignore_ascii_case(&user)) + { + usernames.push(user); } redact_username_segments(value, &usernames) diff --git a/codex-rs/windows-sandbox-rs/src/setup_main_win.rs b/codex-rs/windows-sandbox-rs/src/setup_main_win.rs index 8a72b22a91..5696432853 100644 --- a/codex-rs/windows-sandbox-rs/src/setup_main_win.rs +++ b/codex-rs/windows-sandbox-rs/src/setup_main_win.rs @@ -4,8 +4,13 @@ mod firewall; use anyhow::Context; use anyhow::Result; -use base64::engine::general_purpose::STANDARD as BASE64; use base64::Engine; +use base64::engine::general_purpose::STANDARD as BASE64; +use codex_windows_sandbox::LOG_FILE_NAME; +use codex_windows_sandbox::SETUP_VERSION; +use codex_windows_sandbox::SetupErrorCode; +use codex_windows_sandbox::SetupErrorReport; +use codex_windows_sandbox::SetupFailure; use codex_windows_sandbox::canonicalize_path; use codex_windows_sandbox::convert_string_sid_to_sid; use codex_windows_sandbox::ensure_allow_mask_aces_with_inheritance; @@ -25,16 +30,11 @@ use codex_windows_sandbox::string_from_sid_bytes; use codex_windows_sandbox::to_wide; use codex_windows_sandbox::workspace_cap_sid_for_cwd; use codex_windows_sandbox::write_setup_error_report; -use codex_windows_sandbox::SetupErrorCode; -use codex_windows_sandbox::SetupErrorReport; -use codex_windows_sandbox::SetupFailure; -use codex_windows_sandbox::LOG_FILE_NAME; -use codex_windows_sandbox::SETUP_VERSION; use serde::Deserialize; use serde::Serialize; use std::collections::HashSet; -use std::ffi::c_void; use std::ffi::OsStr; +use std::ffi::c_void; use std::fs::File; use std::io::Write; use std::os::windows::process::CommandExt; @@ -44,17 +44,17 @@ use std::process::Command; use std::process::Stdio; use std::sync::mpsc; use windows_sys::Win32::Foundation::GetLastError; -use windows_sys::Win32::Foundation::LocalFree; use windows_sys::Win32::Foundation::HLOCAL; +use windows_sys::Win32::Foundation::LocalFree; +use windows_sys::Win32::Security::ACL; use windows_sys::Win32::Security::Authorization::ConvertStringSidToSidW; -use windows_sys::Win32::Security::Authorization::SetEntriesInAclW; -use windows_sys::Win32::Security::Authorization::SetNamedSecurityInfoW; use windows_sys::Win32::Security::Authorization::EXPLICIT_ACCESS_W; use windows_sys::Win32::Security::Authorization::GRANT_ACCESS; use windows_sys::Win32::Security::Authorization::SE_FILE_OBJECT; +use windows_sys::Win32::Security::Authorization::SetEntriesInAclW; +use windows_sys::Win32::Security::Authorization::SetNamedSecurityInfoW; use windows_sys::Win32::Security::Authorization::TRUSTEE_IS_SID; use windows_sys::Win32::Security::Authorization::TRUSTEE_W; -use windows_sys::Win32::Security::ACL; use windows_sys::Win32::Security::CONTAINER_INHERIT_ACE; use windows_sys::Win32::Security::DACL_SECURITY_INFORMATION; use windows_sys::Win32::Security::OBJECT_INHERIT_ACE; diff --git a/codex-rs/windows-sandbox-rs/src/setup_orchestrator.rs b/codex-rs/windows-sandbox-rs/src/setup_orchestrator.rs index 962a53d60c..f6583e0de4 100644 --- a/codex-rs/windows-sandbox-rs/src/setup_orchestrator.rs +++ b/codex-rs/windows-sandbox-rs/src/setup_orchestrator.rs @@ -10,22 +10,22 @@ use std::path::PathBuf; use std::process::Command; use std::process::Stdio; -use crate::allow::compute_allow_paths; use crate::allow::AllowDenyPaths; +use crate::allow::compute_allow_paths; use crate::helper_materialization::helper_bin_dir; use crate::logging::log_note; use crate::path_normalization::canonical_path_key; use crate::policy::SandboxPolicy; +use crate::setup_error::SetupErrorCode; +use crate::setup_error::SetupFailure; use crate::setup_error::clear_setup_error_report; use crate::setup_error::failure; use crate::setup_error::read_setup_error_report; -use crate::setup_error::SetupErrorCode; -use crate::setup_error::SetupFailure; -use anyhow::anyhow; use anyhow::Context; use anyhow::Result; -use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; +use anyhow::anyhow; use base64::Engine; +use base64::engine::general_purpose::STANDARD as BASE64_STANDARD; use windows_sys::Win32::Foundation::CloseHandle; use windows_sys::Win32::Foundation::GetLastError; @@ -332,10 +332,10 @@ fn profile_read_roots(user_profile: &Path) -> Vec { fn gather_helper_read_roots(codex_home: &Path) -> Vec { let mut roots = Vec::new(); - if let Ok(exe) = std::env::current_exe() { - if let Some(dir) = exe.parent() { - roots.push(dir.to_path_buf()); - } + if let Ok(exe) = std::env::current_exe() + && let Some(dir) = exe.parent() + { + roots.push(dir.to_path_buf()); } let helper_dir = helper_bin_dir(codex_home); let _ = std::fs::create_dir_all(&helper_dir); @@ -503,10 +503,10 @@ pub(crate) fn offline_proxy_settings_from_env( pub(crate) fn proxy_ports_from_env(env_map: &HashMap) -> Vec { let mut ports = BTreeSet::new(); for key in PROXY_ENV_KEYS { - if let Some(value) = env_map.get(*key) { - if let Some(port) = loopback_proxy_port_from_url(value) { - ports.insert(port); - } + if let Some(value) = env_map.get(*key) + && let Some(port) = loopback_proxy_port_from_url(value) + { + ports.insert(port); } } ports.into_iter().collect() @@ -570,12 +570,12 @@ fn quote_arg(arg: &str) -> String { } fn find_setup_exe() -> PathBuf { - if let Ok(exe) = std::env::current_exe() { - if let Some(dir) = exe.parent() { - let candidate = dir.join("codex-windows-sandbox-setup.exe"); - if candidate.exists() { - return candidate; - } + if let Ok(exe) = std::env::current_exe() + && let Some(dir) = exe.parent() + { + let candidate = dir.join("codex-windows-sandbox-setup.exe"); + if candidate.exists() { + return candidate; } } PathBuf::from("codex-windows-sandbox-setup.exe") @@ -606,11 +606,11 @@ fn run_setup_exe( codex_home: &Path, ) -> Result<()> { use windows_sys::Win32::System::Threading::GetExitCodeProcess; - use windows_sys::Win32::System::Threading::WaitForSingleObject; use windows_sys::Win32::System::Threading::INFINITE; - use windows_sys::Win32::UI::Shell::ShellExecuteExW; + use windows_sys::Win32::System::Threading::WaitForSingleObject; use windows_sys::Win32::UI::Shell::SEE_MASK_NOCLOSEPROCESS; use windows_sys::Win32::UI::Shell::SHELLEXECUTEINFOW; + use windows_sys::Win32::UI::Shell::ShellExecuteExW; let exe = find_setup_exe(); let payload_json = serde_json::to_string(payload).map_err(|err| { failure( @@ -801,13 +801,13 @@ fn filter_sensitive_write_roots(mut roots: Vec, codex_home: &Path) -> V #[cfg(test)] mod tests { + use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS; use super::gather_legacy_full_read_roots; use super::gather_read_roots; use super::loopback_proxy_port_from_url; use super::offline_proxy_settings_from_env; use super::profile_read_roots; use super::proxy_ports_from_env; - use super::WINDOWS_PLATFORM_DEFAULT_READ_ROOTS; use crate::helper_materialization::helper_bin_dir; use crate::policy::SandboxPolicy; use codex_protocol::protocol::ReadOnlyAccess; @@ -1020,8 +1020,10 @@ mod tests { let policy = SandboxPolicy::ReadOnly { access: ReadOnlyAccess::Restricted { include_platform_defaults: false, - readable_roots: vec![AbsolutePathBuf::from_absolute_path(&readable_root) - .expect("absolute readable root")], + readable_roots: vec![ + AbsolutePathBuf::from_absolute_path(&readable_root) + .expect("absolute readable root"), + ], }, network_access: false, }; @@ -1036,9 +1038,11 @@ mod tests { assert!(roots.contains(&expected_helper)); assert!(roots.contains(&expected_cwd)); assert!(roots.contains(&expected_readable)); - assert!(canonical_windows_platform_default_roots() - .into_iter() - .all(|path| !roots.contains(&path))); + assert!( + canonical_windows_platform_default_roots() + .into_iter() + .all(|path| !roots.contains(&path)) + ); } #[test] @@ -1057,9 +1061,11 @@ mod tests { let roots = gather_read_roots(&command_cwd, &policy, &codex_home); - assert!(canonical_windows_platform_default_roots() - .into_iter() - .all(|path| roots.contains(&path))); + assert!( + canonical_windows_platform_default_roots() + .into_iter() + .all(|path| roots.contains(&path)) + ); } #[test] @@ -1071,8 +1077,10 @@ mod tests { fs::create_dir_all(&command_cwd).expect("create workspace"); fs::create_dir_all(&writable_root).expect("create writable root"); let policy = SandboxPolicy::WorkspaceWrite { - writable_roots: vec![AbsolutePathBuf::from_absolute_path(&writable_root) - .expect("absolute writable root")], + writable_roots: vec![ + AbsolutePathBuf::from_absolute_path(&writable_root) + .expect("absolute writable root"), + ], read_only_access: ReadOnlyAccess::Restricted { include_platform_defaults: false, readable_roots: Vec::new(), @@ -1099,8 +1107,10 @@ mod tests { let roots = gather_legacy_full_read_roots(&command_cwd, &policy, &codex_home); - assert!(canonical_windows_platform_default_roots() - .into_iter() - .all(|path| roots.contains(&path))); + assert!( + canonical_windows_platform_default_roots() + .into_iter() + .all(|path| roots.contains(&path)) + ); } } diff --git a/codex-rs/windows-sandbox-rs/src/token.rs b/codex-rs/windows-sandbox-rs/src/token.rs index 0cc9f59da4..56d97ff01e 100644 --- a/codex-rs/windows-sandbox-rs/src/token.rs +++ b/codex-rs/windows-sandbox-rs/src/token.rs @@ -130,7 +130,7 @@ pub unsafe fn world_sid() -> Result> { /// Caller is responsible for freeing the returned SID with `LocalFree`. pub unsafe fn convert_string_sid_to_sid(s: &str) -> Option<*mut c_void> { #[link(name = "advapi32")] - extern "system" { + unsafe extern "system" { fn ConvertStringSidToSidW(StringSid: *const u16, Sid: *mut *mut c_void) -> i32; } let mut psid: *mut c_void = std::ptr::null_mut(); @@ -153,7 +153,7 @@ pub unsafe fn get_current_token_for_restriction() -> Result { | TOKEN_ADJUST_PRIVILEGES; let mut h: HANDLE = 0; #[link(name = "advapi32")] - extern "system" { + unsafe extern "system" { fn OpenProcessToken( ProcessHandle: HANDLE, DesiredAccess: u32,